- Accordion
- Action Bar
- Action Toast
- Alert Banner
- Alert Dialog
- Alert
- Alphabet Index
- Amount Field
- Aspect Ratio
- Attachment
- Availability List
- Avatar
- Badge
- Bank Card
- Breadcrumb
- Bubble
- Button Group
- Button
- Calendar
- Camera Frame
- Card Design Picker
- Card Details
- Card Peek
- Card Stack
- Card
- Carousel
- Chart
- Chat Thread
- Checkbox
- Chip Group
- Choice Tile
- Code Block
- Code Dots
- Collapsible
- Combobox
- Command
- Context Menu
- Copy Field
- Countdown
- Country Select
- Data Table
- Date Field
- Date Picker
- Date Range Picker
- Dialog
- Direction
- Document Paper
- Drawer
- Dropdown Menu
- Empty
- Entity Avatar
- Field
- File Trigger
- File Upload Item
- Hover Card
- Input Group
- Input OTP
- Input
- Item
- Kbd
- Key Value
- Keypad
- Label
- Live Region
- Marker
- Message Scroller
- Message
- Money Amount
- Native Select
- Number Field
- Pagination
- Percent Split Editor
- Phone Field
- Popover
- Progress
- QR Code
- Questionnaire
- Radio Group
- Range Histogram
- Rating
- Resizable
- Scroll Area
- Search Field
- Select
- Separator
- Share Bar
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Sortable List
- Spinner
- Status Timeline
- Step Header
- Steps List
- Swipe Row
- Switch
- Table
- Tabs
- Text Field
- Textarea
- Tier Ladder
- Toggle Group
- Toggle
- Token Search Field
- Tooltip
- Trace
- Transaction Row
- Usage Meter
Photo of your ID
Front of your ID card
Fit all four corners inside the frame
"use client"
import * as React from "react"The CameraFrame component is the screen around a live camera picture: photographing an ID for verification, a selfie check, or scanning a QR code to pay. It draws the frame, the dimmed surround, the hint and the capture buttons, and stays dark in both themes. It never touches the camera itself: you render your own <video> or <img> in CameraFrameMedia. To let the user pick an existing photo or file instead, use FileTrigger.
Installation#
pnpm dlx shadcn@latest add @dots/camera-frame
Usage#
import {
CameraFrame,
CameraFrameActions,
CameraFrameHeader,
CameraFrameHint,
CameraFrameHintDescription,
CameraFrameHintTitle,
CameraFrameMedia,
CameraFrameShutter,
CameraFrameTitle,
CameraFrameViewfinder,
} from "@/components/ui/camera-frame"<CameraFrame aria-label="ID photo">
<CameraFrameMedia>
<video ref={videoRef} autoPlay playsInline muted />
</CameraFrameMedia>
<CameraFrameHeader>
<CameraFrameTitle>Photo of your ID</CameraFrameTitle>
</CameraFrameHeader>
<CameraFrameViewfinder shape="document" />
<CameraFrameHint>
<CameraFrameHintTitle>Front of your ID card</CameraFrameHintTitle>
<CameraFrameHintDescription>
Fit all four corners inside the frame
</CameraFrameHintDescription>
</CameraFrameHint>
<CameraFrameActions>
<CameraFrameShutter onPress={takePhoto} />
</CameraFrameActions>
</CameraFrame>Composition#
Use the following composition to build a camera frame:
CameraFrame
├── CameraFrameMedia
├── CameraFrameHeader
│ └── CameraFrameTitle
├── CameraFrameViewfinder
├── CameraFrameHint
│ ├── CameraFrameHintTitle
│ └── CameraFrameHintDescription
└── CameraFrameActions
├── CameraFrameAction
├── CameraFrameShutter
└── CameraFrameTorchFeatures#
- Dark in both themes: the root scopes the dark tokens to itself
screenfills its container edge to edge for a full-screen capture step.insetis a rounded, fixed-height panel for use inside a page, as in the demos here- Document, oval and square frames with a dimmed surround
- A scan line for QR codes, a progress arc for face checks, and
foundanderrorstates - A hint that is read out politely whenever it changes
- A round shutter, round icon actions and a flashlight toggle
- Any direct child, such as a plain
Button, is lifted above the dimmed surround
Face check#
Set shape="oval" and pass progress from 0 to 1 to draw an arc around the oval. Set status="found" when the check is done.
Selfie check
Turn your head slowly
Keep your face inside the oval
"use client"
import * as React from "react"QR code#
Set shape="square" and scanning to show the scan line. The line stops when status is "found".
Scan to pay
Point the camera at a QR code
Payment links and bill codes work
"use client"
import * as React from "react"Error#
Set status="error" to tint the corners, and say what went wrong in the hint. Use ratio to match the document, such as 1.42 for a passport spread.
Passport
Too much glare
Turn off the flashlight or tilt the passport away from the light
import {
CameraFrame,
CameraFrameActions,Accessibility#
CameraFrame renders a group. The shutter, actions and torch are React Aria buttons, so they work with a keyboard, a pointer and touch.
Name the frame#
Pass aria-label to CameraFrame so the group is announced, such as "ID photo" or "QR scanner".
Say what to do in the hint#
The viewfinder is decorative and hidden from assistive tech. CameraFrameHint has role="status", so its text is read politely whenever it changes. Keep it short and change it only when the instruction really changes.
Label the buttons#
CameraFrameShutter is named "Take photo" and CameraFrameTorch is named "Flashlight" unless you pass aria-label. CameraFrameAction shows only an icon, so aria-label is required. The torch is a toggle button, so its on or off state is announced.
<CameraFrameAction aria-label="Choose from gallery">
<ImageIcon />
</CameraFrameAction>Name the progress#
On an oval frame, progress renders a progress bar named by progressLabel, "Check progress" by default.
API Reference#
CameraFrame#
The root. Accepts all <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "screen" | "inset" | "screen" | screen fills its container. inset is a rounded, fixed-height panel. |
className | string | - | Additional classes to apply to the root. |
CameraFrameMedia#
Holds the camera picture, a <video> or <img>, behind every other part. Accepts all <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Your <video> or <img>. |
className | string | - | Additional classes to apply to the media slot. |
CameraFrameHeader#
The top row: close, title and help. Items after the title are aligned to the end. Accepts all <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the header. |
CameraFrameTitle#
The screen title, centered in the header. Renders an <h2> and accepts all of its props.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the title. |
CameraFrameViewfinder#
The cut-out the user lines the subject up with. Accepts all <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
shape | "document" | "oval" | "square" | "document" | document for cards and passports, oval for a face, square for QR codes. |
ratio | number | 1.586 | Width over height of the document frame, e.g. 1.42 for a passport spread. |
status | "searching" | "found" | "error" | "searching" | found settles the frame, error tints the corners. |
scanning | boolean | false | Shows the scan line. Stops when status is "found". |
progress | number | - | Progress of a face check, 0 to 1. Draws an arc on the oval shape only. |
progressLabel | string | "Check progress" | Names the progress arc for assistive tech. |
children | React.ReactNode | - | Decorative guides drawn inside the frame. Hidden from assistive tech. |
className | string | - | Additional classes to apply to the viewfinder. |
CameraFrameHint#
What to do now. Has role="status". Accepts all <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the hint. |
CameraFrameHintTitle#
The main instruction. Renders a <p> and accepts all of its props.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the title. |
CameraFrameHintDescription#
Supporting text under the instruction. Renders a <p> and accepts all of its props.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the description. |
CameraFrameActions#
The bottom row: secondary actions either side of the shutter. Accepts all <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the row. |
CameraFrameShutter#
The round capture button. Accepts React Aria Button props except children.
| Prop | Type | Default | Description |
|---|---|---|---|
onPress | (e: PressEvent) => void | - | Called when the shutter is pressed. |
aria-label | string | "Take photo" | Name of the button. |
isDisabled | boolean | - | Disables the shutter, e.g. while processing. |
className | string | - | Additional classes. |
CameraFrameAction#
A round icon action, such as picking from the gallery. Accepts React Aria Button props.
| Prop | Type | Default | Description |
|---|---|---|---|
aria-label | string | - | Name of the button. Required. |
children | React.ReactNode | - | The icon. |
className | string | - | Additional classes. |
CameraFrameTorch#
The flashlight toggle. Renders its own icon. Accepts React Aria ToggleButton props except children.
| Prop | Type | Default | Description |
|---|---|---|---|
isSelected | boolean | - | Whether the flashlight is on (controlled). |
defaultSelected | boolean | - | Whether the flashlight is on (uncontrolled). |
onChange | (isSelected: boolean) => void | - | Called when the flashlight is toggled. |
aria-label | string | "Flashlight" | Name of the button. |
className | string | - | Additional classes. |
On This Page
InstallationUsageCompositionFeaturesFace checkQR codeErrorAccessibilityName the frameSay what to do in the hintLabel the buttonsName the progressAPI ReferenceCameraFrameCameraFrameMediaCameraFrameHeaderCameraFrameTitleCameraFrameViewfinderCameraFrameHintCameraFrameHintTitleCameraFrameHintDescriptionCameraFrameActionsCameraFrameShutterCameraFrameActionCameraFrameTorch