Experimental: The AI extension and its component APIs may change in the future. Please give us feedback on your experience with them.
Demos#
Confirmation states#
The four design states: pending, required, confirmed and expired. The application owns their state.
Share history?
Do you want to give the customer advisor access to this conversation’s history?
Awaiting confirmationShare history?
RequiredDo you want to give the customer advisor access to this conversation’s history?
RequiredShare history?
Do you want to give the customer advisor access to this conversation’s history?
ConfirmedShare history?
ExpiredDo you want to give the customer advisor access to this conversation’s history?
Expired<Provider locale="en-GB"> <Flex.Vertical gap="medium" style={{ maxWidth: '32.6875rem', }} > {(['pending', 'required', 'confirmed', 'expired'] as const).map( (status) => ( <Confirmation key={status} title="Share history?" status={status} onConfirm={() => null} onDecline={() => null} > Do you want to give the customer advisor access to this conversation’s history? </Confirmation> ) )} </Flex.Vertical> </Provider>
Choose and reset#
Confirm or decline the request, then reset it to try again. A declined decision stays visible, with a text label rather than color alone.
Add these companies to your watchlist?
PåkrevdReview the companies from the attached document before continuing.
Påkrevdconst Decision = () => { const [status, setStatus] = useState< 'required' | 'confirmed' | 'declined' >('required') return ( <> <Confirmation title="Add these companies to your watchlist?" status={status} onConfirm={() => setStatus('confirmed')} onDecline={() => setStatus('declined')} confirmLabel="Add to watchlist" declineLabel="Keep current list" > Review the companies from the attached document before continuing. </Confirmation> <Button top onClick={() => setStatus('required')}> Reset decision </Button> </> ) } render(<Decision />)
Application-owned expiry#
Start a one-minute request, extend it or turn off the limit. The application warns before expiry and keeps completed decisions visible.
Continue with this request?
UtløptReview the request before continuing.
Utløptconst TimedDecision = () => { const [status, setStatus] = useState< 'expired' | 'required' | 'confirmed' | 'declined' >('expired') const startRef = useRef<HTMLButtonElement>(null) const [deadline, setDeadline] = useState<number>(null) const [now, setNow] = useState(Date.now()) useEffect(() => { if (status !== 'required' || deadline === null) { return undefined } const update = () => { const time = Date.now() setNow(time) if (time >= deadline) { const focused = document.activeElement if ( focused instanceof HTMLElement && focused.closest('[data-visual-test="ai-confirmation-expiry"]') && !focused.closest('.dnb-ai-confirmation') ) { startRef.current?.focus() } setStatus('expired') } } const interval = setInterval(update, 1000) update() return () => clearInterval(interval) }, [status, deadline]) return ( <> <Flex.Horizontal bottom> <Button ref={startRef} onClick={() => { setNow(Date.now()) setDeadline(Date.now() + 60000) setStatus('required') }} > {status === 'required' ? 'Restart request' : 'Start a request'} </Button> {status === 'required' && deadline !== null && ( <> <Button onClick={() => setDeadline(Date.now() + 60000)}> Extend by one minute </Button> <Button onClick={() => { setDeadline(null) startRef.current?.focus() }} > Turn off time limit </Button> </> )} </Flex.Horizontal> <Confirmation title="Continue with this request?" status={status} onConfirm={() => setStatus('confirmed')} onDecline={() => setStatus('declined')} > {status === 'required' && deadline !== null ? 'You have ' + Math.max(0, Math.ceil((deadline - now) / 1000)) + ' seconds. Extend or turn off the limit if you need more time.' : 'Review the request before continuing.'} </Confirmation> <AriaLive> {status === 'required' && deadline !== null && deadline - now <= 30000 ? 'This request expires soon. Extend or turn off the time limit using the buttons above.' : ''} </AriaLive> </> ) } render(<TimedDecision />)