@aho-sdk/components-web
v0.1.2
Published
Web Components for Digital Credentials API verification via Aho
Maintainers
Readme
@aho-sdk/components-web
Web Components for Digital Credentials API verification via Aho.
Installation
npm install @aho-sdk/components-webOr use the CDN:
<script src="https://js.aho.com/v1/components-web"></script>Quick Start
Using AhoProvider (Recommended)
<script type="module" src="@aho-sdk/components-web"></script>
<aho-provider api-key="aho_pub_xxx" client-name="My App">
<credential-button claims="age_over_21">
Verify Age
</credential-button>
</aho-provider>Using Global Configuration
<script type="module">
import { configure } from '@aho-sdk/components-web';
configure({
apiKey: 'aho_pub_xxx',
clientName: 'My App',
});
</script>
<credential-button claims="age_over_21">
Verify Age
</credential-button>Using Data Attributes (Plain HTML)
<script src="https://js.aho.com/v1/components-web"></script>
<script>
AhoComponents.configure({ apiKey: 'aho_pub_xxx' });
</script>
<button data-aho-verify data-aho-claims="age_over_21">
Verify Age
</button>Configuration
There are three ways to configure Aho components (in priority order):
- Element attributes - Most specific, per-element
<aho-provider>- Scoped to descendantsconfigure()- Global fallback
Using <aho-provider>
Wrap components in a provider element:
<aho-provider api-key="aho_pub_xxx" client-name="My App">
<credential-button claims="age_over_21">Verify</credential-button>
<credential-display></credential-display>
</aho-provider>You can nest providers for different configurations:
<aho-provider api-key="aho_pub_main">
<credential-button claims="age_over_21">Main App</credential-button>
<aho-provider api-key="aho_pub_partner" client-name="Partner">
<credential-button claims="given_name">Partner Widget</credential-button>
</aho-provider>
</aho-provider>Or configure programmatically:
const provider = document.querySelector('aho-provider');
provider.configure({
apiKey: 'aho_pub_xxx',
clientName: 'My App',
});Using configure()
Call configure() once before using any components:
import { configure } from '@aho-sdk/components-web';
configure({
// Required: Your publishable API key
apiKey: 'aho_pub_xxx',
// Optional: Base URL for API calls (defaults to current origin)
baseUrl: 'https://api.example.com',
// Optional: Default client name shown in wallet dialogs
clientName: 'My App',
// Optional: Auto-initialize data-attribute buttons (default: true)
autoInit: true,
});Web Component: <aho-provider>
Configuration provider for descendant components.
Attributes
| Attribute | Description | Example |
|-----------|-------------|---------|
| api-key | Publishable API key | "aho_pub_xxx" |
| base-url | Base URL for API calls | "https://api.example.com" |
| client-name | Default client name for wallet dialogs | "My App" |
Methods
| Method | Description |
|--------|-------------|
| configure(config) | Set configuration programmatically |
| config | Get current configuration (readonly) |
Web Component: <credential-button>
Attributes
| Attribute | Description | Example |
|-----------|-------------|---------|
| claims | Space or comma-separated claim types | "age_over_21 given_name" |
| document-types | Document types to accept | "org.iso.18013.5.1.mDL" |
| client-name | Name shown in wallet dialog | "My App" |
| api-key | Override global API key | "aho_pub_xxx" |
| base-url | Override global base URL | "https://api.example.com" |
| unsupported | Behavior when DC API unavailable | "hide", "disable", "fallback" |
| disabled | Disable the button | (boolean attribute) |
Events
Events are namespaced as aho:credential:*:
const button = document.querySelector('credential-button');
button.addEventListener('aho:credential:statechange', (e) => {
console.log('State:', e.detail.state);
// States: creating_session, awaiting_credential, verifying, completed, failed, cancelled
});
button.addEventListener('aho:credential:verified', (e) => {
console.log('Verified!', e.detail.result);
// result: { verified, trusted, claims, issuer, sessionId }
});
button.addEventListener('aho:credential:failed', (e) => {
console.log('Requirements not met:', e.detail.reason);
});
button.addEventListener('aho:credential:error', (e) => {
console.error('Error:', e.detail.error);
});
button.addEventListener('aho:credential:cancelled', (e) => {
console.log('User cancelled:', e.detail.reason);
});
button.addEventListener('aho:credential:unsupported', (e) => {
console.warn('Not supported:', e.detail.reason);
});CSS Custom Properties
Style the button using CSS custom properties:
credential-button {
/* Base styles */
--aho-button-bg: #2563eb;
--aho-button-color: white;
--aho-button-padding: 0.75rem 1.5rem;
--aho-button-radius: 0.5rem;
--aho-button-font: inherit;
--aho-button-font-size: 1rem;
--aho-button-font-weight: 500;
/* Hover state */
--aho-button-bg-hover: #1d4ed8;
/* Verification states */
--aho-button-bg-verifying: #6b7280;
--aho-button-bg-success: #059669;
--aho-button-bg-error: #dc2626;
/* Disabled state */
--aho-button-disabled-opacity: 0.5;
/* Focus outline */
--aho-button-outline: 2px solid #60a5fa;
--aho-button-outline-offset: 2px;
}State Classes
The component applies these classes based on verification state:
| Class | When Applied |
|-------|--------------|
| .aho-idle | Initial state, ready for verification |
| .aho-verifying | Verification in progress |
| .aho-success | Verification completed successfully |
| .aho-error | Verification failed or was cancelled |
Web Component: <credential-display>
Display rendered credentials after verification.
Basic Usage
<!-- Server-rendered mode (typical post-verification) -->
<credential-display src="/v1/sessions/abc123/render?sig=xyz"></credential-display>
<!-- With options -->
<credential-display
src="/v1/sessions/abc123/render?sig=xyz"
size="large"
enable-download
></credential-display>
<!-- Controlled mode (pre-fetched data) -->
<credential-display
data='{"format":"svg","content":"<svg>...</svg>"}'
></credential-display>Post-Verification Pattern
<credential-button claims="age_over_21" id="verify-btn">
Verify Age
</credential-button>
<div id="credential-result" style="display: none;">
<credential-display id="credential-display"></credential-display>
</div>
<script>
document.getElementById('verify-btn').addEventListener('aho:credential:verified', (e) => {
document.getElementById('credential-display').setAttribute('src', e.detail.result.renderUrl);
document.getElementById('credential-result').style.display = 'block';
});
</script>Attributes
| Attribute | Description | Example |
|-----------|-------------|---------|
| src | URL to fetch rendered credential | "/v1/sessions/abc/render?sig=xyz" |
| data | Pre-fetched render response JSON | '{"format":"svg","content":"..."}' |
| size | Size variant | "compact", "default", "large" |
| enable-download | Show download button | (boolean attribute) |
Events
const display = document.querySelector('credential-display');
display.addEventListener('aho:display:ready', () => {
console.log('Component ready');
});
display.addEventListener('aho:display:loaded', (e) => {
console.log('Loaded:', e.detail.format, e.detail.templateKey);
});
display.addEventListener('aho:display:error', (e) => {
console.error('Error:', e.detail.error);
});
display.addEventListener('aho:display:download', (e) => {
console.log('Downloaded:', e.detail.format, e.detail.filename);
});Programmatic Ready Check
const display = document.querySelector('credential-display');
await display.ready(); // Resolves when component is interactiveCSS Custom Properties
credential-display {
--aho-display-bg: #ffffff;
--aho-display-border: 1px solid #e5e7eb;
--aho-display-radius: 0.75rem;
--aho-display-compact-width: 280px;
--aho-display-default-width: 400px;
--aho-display-large-width: 600px;
--aho-display-loading-bg: rgba(255, 255, 255, 0.9);
--aho-display-spinner-color: #e5e7eb;
--aho-display-spinner-active: #3b82f6;
--aho-display-error-color: #dc2626;
--aho-display-download-bg: rgba(255, 255, 255, 0.9);
--aho-display-download-border: 1px solid #e5e7eb;
}State Classes
| Class | When Applied |
|-------|--------------|
| .aho-idle | Initial state |
| .aho-verifying | Fetching content |
| .aho-success | Content rendered |
| .aho-error | Loading failed |
Data Attributes API
For plain HTML buttons without custom elements:
<button
data-aho-verify
data-aho-claims="age_over_21 given_name"
data-aho-document-types="org.iso.18013.5.1.mDL"
data-aho-client-name="My App"
data-aho-unsupported="disable"
>
Verify Identity
</button>Manual Initialization
If autoInit is disabled or you add buttons dynamically:
import { initDataAttributes } from '@aho-sdk/components-web';
// Initialize all data-aho-verify buttons
initDataAttributes();
// Or initialize within a specific container
initDataAttributes(document.querySelector('#my-container'));Available Claims
import { Claim } from '@aho-sdk/components-web';
// Age verification
Claim.AGE_OVER_18 // 'age_over_18'
Claim.AGE_OVER_21 // 'age_over_21'
Claim.AGE // 'age'
Claim.BIRTH_DATE // 'birth_date'
// Identity
Claim.GIVEN_NAME // 'given_name'
Claim.FAMILY_NAME // 'family_name'
Claim.PORTRAIT // 'portrait'
// Address
Claim.ADDRESS // 'resident_address'
Claim.CITY // 'resident_city'
Claim.STATE // 'resident_state'
Claim.POSTAL_CODE // 'resident_postal_code'
Claim.COUNTRY // 'resident_country'
// Document info
Claim.DOCUMENT_NUMBER // 'document_number'
Claim.ISSUE_DATE // 'issue_date'
Claim.EXPIRY_DATE // 'expiry_date'
Claim.ISSUING_AUTHORITY // 'issuing_authority'Document Types
import { DocumentType } from '@aho-sdk/components-web';
DocumentType.MOBILE_DRIVERS_LICENSE // 'org.iso.18013.5.1.mDL'
DocumentType.PHOTO_ID // 'org.iso.23220.photoid.1'
DocumentType.EU_PERSONAL_ID // 'eu.europa.ec.eudi.pid.1'
DocumentType.JAPAN_MY_NUMBER_CARD // 'org.iso.23220.1.jp.mnc'Browser Support
The Digital Credentials API is supported in:
- Chrome on Android (with Google Wallet)
- Safari on iOS 18+ (with Apple Wallet)
Use the unsupported attribute to handle unsupported browsers:
"disable"(default) - Disables the button"hide"- Hides the button completely"fallback"- Triggersaho:unsupportedevent for custom handling
TypeScript
Full TypeScript support with exported types:
import type {
AhoComponentsConfig,
AhoElementEventMap,
VerifyResult,
VerifyState,
ClaimType,
} from '@aho-sdk/components-web';License
MIT
