React
React components and hooks for verification flows
Installation
npm install @aho-sdk/components-react
Quick Start
Install the React SDK:
npm install @aho-sdk/components-react
Wrap your app with the provider and use the components:
import { AhoProvider, CredentialButton, Claim } from '@aho-sdk/components-react';
function App() {
return (
<AhoProvider config={{ publishableKey: 'aho_pub_xxx'
<CredentialButton
claims={[Claim.GIVEN_NAME, Claim.FAMILY_NAME
Examples
Basic Usage
Simple age verification with a single claim.
import React, { useState } from 'react';
import { createRoot } from 'react-dom/client';
import { AhoProvider, CredentialButton, Claim } from '@aho-sdk/components-react';
function BasicDemo() {
return (
<AhoProvider config={{ publishableKey: 'aho_pub_xxx', nonce: '...' }}>
<CredentialButton
claims={[Claim.AGE_OVER_21]}
onVerified={(result) => console.log('Verified:', result)}
>
Verify Age
</CredentialButton>
</AhoProvider>
);
}
createRoot(document.getElementById('basic-demo')).render(<BasicDemo />);
Custom Styling
Customize button appearance with CSS custom properties.
import React from 'react';
import { createRoot } from 'react-dom/client';
import { AhoProvider, CredentialButton, Claim } from '@aho-sdk/components-react';
function StyledDemo() {
return (
<AhoProvider config={{ publishableKey: 'aho_pub_xxx', nonce: '...' }}>
<CredentialButton
claims={[Claim.GIVEN_NAME, Claim.FAMILY_NAME]}
className="custom-button"
onVerified={(result) => console.log('Verified:', result)}
>
Verify Identity
</CredentialButton>
</AhoProvider>
);
}
createRoot(document.getElementById('styled-demo')).render(<StyledDemo />);
.custom-button {
--aho-button-bg: #059669;
--aho-button-bg-hover: #047857;
--aho-button-radius: 9999px;
}
Event Handling
Handle verification lifecycle with callbacks.
import React, { useState } from 'react';
import { createRoot } from 'react-dom/client';
import { AhoProvider, CredentialButton, Claim } from '@aho-sdk/components-react';
function EventsDemo() {
const [log, setLog] = useState('Click button to see events...');
const addLog = (msg) => setLog(prev => prev + '\n' + new Date().toISOString().substr(11, 12) + ' ' + msg);
return (
<AhoProvider config={{ publishableKey: 'aho_pub_xxx', nonce: '...' }}>
<CredentialButton
claims={[Claim.AGE_OVER_18]}
onVerified={(result) => addLog('verified: ' + JSON.stringify({ verified: result.verified }))}
onError={(error) => addLog('error: ' + error.message)}
>
Verify (Watch Events)
</CredentialButton>
<pre className="mt-4 bg-gray-900 text-gray-100 p-4 rounded-lg text-sm overflow-auto max-h-40">{log}</pre>
</AhoProvider>
);
}
createRoot(document.getElementById('events-demo')).render(<EventsDemo />);
Credential Display
After verification, display the credential card automatically.
import React, { useState } from 'react';
import { createRoot } from 'react-dom/client';
import { AhoProvider, CredentialButton, CredentialDisplay, ALL_CLAIMS } from '@aho-sdk/components-react';
function DisplayDemo() {
const [renderUrl, setRenderUrl] = useState(null);
return (
<AhoProvider config={{ publishableKey: 'aho_pub_xxx', nonce: '...' }}>
<CredentialButton
claims={ALL_CLAIMS}
onVerified={(result) => setRenderUrl(result.renderUrl)}
>
Verify Identity
</CredentialButton>
{renderUrl && (
<div className="mt-4">
<p className="text-green-600 font-medium mb-2">Verification successful!</p>
<CredentialDisplay src={renderUrl} enableDownload />
</div>
)}
</AhoProvider>
);
}
createRoot(document.getElementById('display-demo')).render(<DisplayDemo />);
Display Size Variants
Display credentials in compact (280px), default (400px), or large (600px) max-widths.
import React from 'react';
import { createRoot } from 'react-dom/client';
import { CredentialDisplay } from '@aho-sdk/components-react';
const compactData = compactData;
const defaultData = defaultData;
const largeData = largeData;
function SizesDemo() {
return (
<div className="space-y-6">
<div>
<p className="text-sm font-medium text-gray-500 mb-2">Compact (max-width: 280px)</p>
<CredentialDisplay size="compact" data={compactData} nonce="..." />
</div>
<div>
<p className="text-sm font-medium text-gray-500 mb-2">Default (max-width: 400px)</p>
<CredentialDisplay data={defaultData} nonce="..." />
</div>
<div>
<p className="text-sm font-medium text-gray-500 mb-2">Large (max-width: 600px)</p>
<CredentialDisplay size="large" data={largeData} nonce="..." />
</div>
</div>
);
}
createRoot(document.getElementById('sizes-demo')).render(<SizesDemo />);
Controlled Mode
Pass pre-fetched render data directly to skip the fetch.
Static (inline data)
import { CredentialDisplay, type RenderResponse } from '@aho-sdk/components-react';
const data: RenderResponse = {
format: 'svg',
content: '<svg>...</svg>',
template: { key: 'mobile_drivers_license', source: 'built_in', verified: true }
};
<CredentialDisplay data={data} />
Dynamic (fetch then set)
import { useState } from 'react';
import { CredentialButton, CredentialDisplay, Claim, type RenderResponse, type VerifyResult } from '@aho-sdk/components-react';
function VerifyAndDisplay() {
const [data, setData] = useState<RenderResponse
Display Styling
Customize display appearance with CSS custom properties.
import React from 'react';
import { createRoot } from 'react-dom/client';
import { CredentialDisplay } from '@aho-sdk/components-react';
const customData = customData;
function StyledDisplayDemo() {
return <CredentialDisplay data={customData} className="custom-display" nonce="..." />;
}
createRoot(document.getElementById('styled-display-demo')).render(<StyledDisplayDemo />);
.custom-display {
--aho-display-bg: #1f2937;
--aho-display-border: 2px solid #4ade80;
--aho-display-radius: 1rem;
}
Display Events
Handle display lifecycle with callbacks.
<CredentialDisplay
src={renderUrl}
onLoaded={(format, templateKey
API Reference
<CredentialButton>
A React component that initiates the credential verification flow.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
publishableKey |
string | — | Publishable key (aho_pub_xxx). Required unless set via configure() or AhoProvider. |
claims |
string | string[] | — | Claims to request. Comma-separated string or array. Use 'all' for all claims. |
returnClaims |
boolean | 'all' | string[] | true | Which claims to return in the result. true=all requested, false=none, 'all'=all, array=specific claims. Must be subset of claims. |
documentTypes |
string | string[] | all | Accepted document types (e.g., 'mDL', 'passport'). Defaults to all. |
clientName |
string | — | Display name shown in wallet dialog. |
baseUrl |
string | https://api.aho.com | API base URL. Defaults to production. |
unsupported |
'hide' | 'disable' | 'fallback' | disable | Behavior when browser doesn't support Digital Credentials API. |
disabled |
boolean | false | Disable the button. |
Callback Props
| Prop | Type | Description |
|---|---|---|
onVerified |
(result: VerifyResult) => void | Callback when verification succeeds |
onError |
(error: Error) => void | Callback when verification fails |
onStateChange |
(state: VerifyState) => void | Callback when state changes |
children |
ReactNode | Button content |
loadingContent |
ReactNode | Content shown while verifying |
successContent |
ReactNode | Content shown on success |
errorContent |
ReactNode | Content shown on error |
<CredentialDisplay>
A React component that displays a rendered credential.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
src |
string | — | URL to fetch rendered credential from. |
data |
string | object | — | Pre-fetched render response. JSON string (web) or object (React/Vue). |
size |
'compact' | 'default' | 'large' | default | Display size variant. Controls max-width. |
enableDownload |
boolean | false | Show download button on hover. |
loadingText |
string | Loading... | Text shown while loading. |
errorText |
string | Failed to load credential | Text shown on error. |
verifyAuthenticity |
boolean | false | Verify credential authenticity and show trust indicator with link to verification page. |
Callback Props
| Prop | Type | Description |
|---|---|---|
onLoaded |
(format: string, templateKey?: string) => void | Callback when content loads |
onError |
(error: Error) => void | Callback when loading fails |
onDownload |
(format: string, filename: string) => void | Callback when download triggered |
<AhoProvider>
Context provider for configuration.
Config Options
| Property | Type | Description |
|---|---|---|
publishableKey
*
|
string | Publishable key (aho_pub_xxx) |
baseUrl
|
string | Override API base URL |
nonce
|
string | CSP nonce for child components |