Skip to content

Feature request: New Camera component (with QR code scanning) for Vaadin 26 #9116

Description

@letrthang

Motivation

Modern web applications frequently need camera access — for capturing photos, scanning QR codes / barcodes, document scanning, video previews, and more. With the widespread support of the MediaDevices.getUserMedia() API across all modern browsers (including mobile), camera access from the web is now reliable and commonplace.

Vaadin currently has no first-class component for camera access. Developers must drop down to raw JavaScript, call getUserMedia() manually, attach a stream to a <video> element, handle permissions/errors, and — if QR scanning is needed — integrate a separate library like jsQR or zxing-js. This is complex, repetitive, and hard to maintain across projects.

Proposed Component: Camera (working name)

A new component that accesses the device camera, displays a live preview, and optionally scans for QR codes / barcodes in real time.

Core behavior

┌──────────────────────────────────────────────────┐
│                                                   │
│                                                   │
│              [ live camera preview ]              │
│                                                   │
│              ┌─────────────┐                      │
│              │   ▓▓▓▓▓▓▓   │  ← QR scan overlay   │
│              │   ▓ ▓ ▓ ▓   │     (optional)       │
│              │   ▓▓▓▓▓▓▓   │                      │
│              └─────────────┘                      │
│                                                   │
├──────────────────────────────────────────────────┤
│  [ 📸 Capture ]  [ 🔄 Flip ]  [ QR: ON/OFF ]      │
└──────────────────────────────────────────────────┘
  • Accesses the device camera(s) via getUserMedia() and shows a live video preview.
  • Supports capturing photos (snapshot to image).
  • Optionally enables real-time QR code / barcode scanning with a scan-overlay UI.
  • Handles camera selection (front/back), especially important on mobile devices.

Suggested API

Camera camera = new Camera();

// Configure
camera.setFacingMode(CameraFacingMode.ENVIRONMENT); // back camera on mobile
camera.setQrScanningEnabled(true);                   // turn on QR detection
camera.setPhotoResolution(1920, 1080);

// Capture a photo
camera.capturePhoto();
camera.addPhotoCaptureListener(e -> {
    byte[] jpeg = e.getImageData();    // captured photo as JPEG bytes
    // save to DB, S3, etc.
});

// QR code scanning
camera.addQrCodeDetectedListener(e -> {
    String code = e.getValue();         // decoded QR code text
    Notification.show("Scanned: " + code);
});

// Lifecycle
camera.start();   // request camera permission and begin stream
camera.stop();    // release the camera
camera.flip();    // switch between front/back cameras

// Error handling
camera.addErrorListener(e -> {
    String msg = e.getMessage();  // permission denied, no camera, etc.
});

Key features

Feature Description
Live camera preview Real-time video feed from the device camera
Photo capture Take a snapshot and retrieve it as JPEG/PNG bytes or data URL
QR code scanning Real-time QR code detection and decoding (e.g. via jsQR / zxing-js)
Barcode scanning Optionally support 1D barcodes (EAN, UPC, Code128, etc.)
Camera selection Switch between front/back cameras (facingMode)
Scan overlay Configurable viewfinder/reticle UI for QR scanning guidance
Permission handling Graceful handling of permission denied / no camera / insecure context
Responsive Full-screen on mobile, inline panel on desktop
Theme variants Lumo theme variants for overlay style and control layout
Server-side events Photo and QR data delivered to the server via Vaadin's communication layer

Use cases

  1. QR code login / check-in — scan a QR to authenticate or register attendance.
  2. Product / asset scanning — scan QR/barcodes for inventory, logistics, retail.
  3. Document / ID capture — photograph documents, receipts, or IDs.
  4. Profile photos — capture user avatars directly from the camera.
  5. Contactless info — scan QR codes on posters, menus, packaging.

Alternatives considered

  • Manual getUserMedia() + <video> via Element API: every team reimplements permission handling, stream lifecycle, camera switching, and QR detection. High duplication and inconsistent quality.
  • Third-party JS libraries: jsQR, @zxing/library, html5-qrcode — capable but require custom Vaadin wrappers, have no server-side integration, and aren't maintained alongside Vaadin releases.
  • Vaadin Directory add-ons: a few camera/signature add-ons exist but are limited in scope and not QR-focused.

A built-in Camera component with optional QR scanning would cover the most common camera needs out of the box, with proper server-side integration and Lumo theming.

Prior art

  • HTML5 MediaDevices.getUserMedia() — the underlying web standard, now universally supported
  • PrimeFacesCamera (photo capture via <p:camera>)
  • ** Ionic / Capacitor** — community camera + QR scanner plugins
  • NativeScript / Cordovacordova-plugin-qrscanner, phone camera plugins
  • jsQR / @zxing/library — popular open-source QR decoding libraries

Implementation notes

The component would wrap a <video> element fed by getUserMedia(). For QR scanning, a lightweight decoder (e.g. jsQR or @zxing/browser) would analyze video frames on the client and emit decoded values to the server via Vaadin's RPC. Photo capture would draw the current video frame to a <canvas> and encode it server-side. All browser permission prompts and error states would be surfaced as server-side events.

Accessibility & privacy

  • Camera access requires HTTPS (secure context) and explicit user permission — the component should surface permission-denied states clearly.
  • The scan overlay and control buttons should be keyboard-accessible with proper ARIA labels.
  • The component should always release the camera stream (stop()) when no longer needed to protect user privacy.

I'd be happy to help refine the API. Is this something the team would consider for Vaadin 26?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions