LikenessConsent
StableAsk for, track and control a real person's consent to use their face or voice in avatars.
Also known as face consent, likeness check
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
Every status
Asha Rao's face and voice
Waiting for Asha- Ask, done
- Record, current
- Review
- Ready
Waiting for Asha to record
We sent Asha a link to record on their phone. It expires in 23 hours.
Nothing can be made with this likeness until Asha records and agrees.
Consent covers this workspace only. It does not give anyone ownership of Asha's likeness.
Waiting for Asha to record. The link expires in 23 hours.
<LikenessConsent subjectName="Asha Rao" status="pending" linkExpiresIn="23 hours"
onSendLink={sendLink} onRecordHere={recordHere} onCancelRequest={cancel} />
<LikenessConsent subjectName="Asha Rao" status="rejected"
rejectionReason="The person in the video did not read the lines, so we could not tell they agreed."
onSendLink={sendLink} />
<LikenessConsent subjectName="Juno, the guide" status="notRealPerson" />The view of the person who asked. Pending is amber because Asha still has to act; nothing else is. They can see who may use it but not change it.
When to use it
Makes using a real person's likeness depend on that person's own recorded, scoped and revocable consent.
Made of: Whose likeness and status badge · Steps (Ask, Record, Review, Ready) · Heading · Status text · Recording (VoiceConsentCheck) · Who can use it · Where it was used · Actions · Scope note
Use it for
- Creating an avatar of a teammate or presenter.
- Cloning a person's voice for video narration (kind="voice").
- A settings page where people see and control their own likeness.
Not for
- The live recording check on its own: use VoiceConsentCheck.
- Approving one action an agent wants to take: use ApprovalPrompt.
- Asking for camera or mic permission: use PermissionPrompt.
Do and avoid
Asha Rao's face and voice
Not requested- Ask, current
- Record
- Review
- Ready
Ask Asha for consent
Asha records a short video on their own device and reads a few lines aloud. That recording is the consent. A photo is not enough.
The link lasts 24 hours. Asha can say no, and can withdraw consent at any time later.
Consent covers this workspace only. It does not give anyone ownership of Asha's likeness.
Make an avatar
Do
- Have the person record their own consent, and let it expire after 24 hours if they do not.
- Start who-can-use-it at the narrowest choice.
- List every use and tell the person each time.
- Say what happens to takes already made when consent is revoked.
Avoid
- Do not make a likeness from an uploaded photo of a real person.
- Do not use amber once the person has acted. Accepted, rejected and revoked are not waiting on anyone.
- Do not let anyone but the person in it widen who may use it.
- Do not reduce consent to a terms checkbox.
On a phone
- Fills the width. Action buttons share the row on a phone.
- The step names sit under the step bar and stay readable at 320px.
- Recording happens on the subject's own phone by default; "record now" opens the same check here.
- Choices in Who can use it are 44px tall on touch.
Seen in products
- HeyGen's avatar consent has pending, accepted and rejected statuses, null for avatars that are not real people, and a webcam link that expires in 24 hours.
- Synthesia requires explicit consent, says sharing does not transfer ownership, and lets only the avatar owner revoke access.
- Sora let people choose who could use their cameo, revoke it at any time, and be told when it was used.
- Google Flow starts avatar capture on desktop and finishes on the phone, and says where avatars are not available.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| subjectNamerequired | string | none | The person, or the made-up avatar's name. |
| kind | "face" | "voice" | "faceAndVoice" | "faceAndVoice" | What is being used. |
| statusrequired | "notRequested" | "pending" | "expired" | "recording" | "reviewing" | "accepted" | "rejected" | "revoked" | "notRealPerson" | none | Where consent is. |
| linkExpiresIn | string | none | Time left on the link, in words, from your code. Links last 24 hours. |
| rejectionReason | string | none | Why the recording was not accepted. |
| decidedOn | string | none | When consent was given or revoked, written by your code. |
| audience | "onlyMe" | "approved" | "workspace" | "anyone" | "onlyMe" | Who may use it. |
| onAudienceChange | (a: LikenessAudience) => void | none | Change who may use it. Needs canManage. |
| audienceOptions | LikenessAudience[] | ["onlyMe", "approved", "workspace"] | Choices to offer. Add "anyone" only if your product allows it. |
| canManage | boolean | false | The viewer is the person in it and may change who uses it or revoke it. |
| usage | { who: string; what: string; when: string }[] | [] | Where it was used, newest first. |
| onSendLink | () => void | none | Send a link to record on their own device, or a new one. |
| onRecordHere | () => void | none | The person is here: record on this device. |
| onCancelRequest | () => void | none | Withdraw a pending request. |
| onRevoke | () => void | none | Revoke consent, after a confirm in place. |
| check | Omit<VoiceConsentCheckProps, "subject" | "headingLevel"> | none | Props for the recording step, shown when status is "recording". |
| region | { allowed: boolean; message?: string } | none | When not allowed, explains why nothing can be requested. |
| headingLevel | 2 | 3 | 4 | 5 | 6 | 2 | Level of the heading. |
| className | string | none | Extra classes for the panel. |
"Show code under the preview gives the code for the example on the stage."
In Figma
In Figma, one LikenessConsent switches all of this from its properties panel, across 108 variants. Each property sets the React prop beside it, so design and code use the same names.
| Figma property | React | Values |
|---|---|---|
| Kind | kind | Face, Voice, FaceAndVoice |
| Status | status | NotRequested, Pending, Expired, Recording, Reviewing, Accepted, Rejected, Revoked, NotRealPerson |
| Audience | audience | OnlyMe, Approved, Workspace, Anyone |
| RejectionReason | rejectionReason | Any text |
Tokens
Change one of these and every part that uses it follows.
--surface--border--fg--fg-muted--fg-subtle--attention--warning-soft--warning-fg--success-soft--success-fg--danger-soft--danger-fg--radius-card
Built in
- A section named by its heading. The steps are an ordered list with aria-current on the current step and "done" or "current" written for screen readers.
- Every status is written in a badge and a heading, never colour alone. The amber badge carries words like "Waiting for Asha".
- Status changes are announced once through a polite status region.
- If a status change removes the button that had focus, focus moves to the heading. A change from elsewhere never takes focus.
- Revoke asks in place with InlineConfirm; Keep it gets focus first and Escape backs out.
- Who can use it is a native radio group with a legend.
What you need to do
- Work out linkExpiresIn in code from the time the link was sent, and write it in words. A model must never make up the time.
- Only set canManage for the person in the likeness (or its owner). Everyone else sees who may use it but cannot change it.
- Tell the person each time their likeness is used, and fill usage from that log.
- Offer a check by a person through check.manualReviewHref for anyone who cannot read aloud or use a camera.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide