Styled drop-in
The fastest path: the prebuilt, Dialogue-branded interview. Wrap your tree in the provider, render <Interview>, theme via appearance.
Minimal example
'use client';
import { DialogueProvider } from '@dialogueai/react';
import { Interview } from '@dialogueai/react-ui';
import '@dialogueai/react-ui/styles.css';
export function Widget() {
return (
<DialogueProvider publishableKey="pk_live_…" bootstrapTokenProvider={getToken}>
<Interview
studyId="019e16c4-ce3f-7388-b236-24455b07e857"
onCompleted={({ completionToken }) => console.log('done', completionToken)}
onFinish={() => console.log('widget dismissed')}
/>
</DialogueProvider>
);
}<Interview> must be inside <DialogueProvider>. It does not self-bootstrap the provider, but it does auto-open the study from its studyId.Inline vs floating
appearance.layout controls positioning. 'inline' (default) fills its container; 'floating' anchors to a viewport corner over your page, a chat-bubble style pop-in.
<Interview studyId={studyId} appearance={{ layout: 'floating' }} />Theming
The appearance prop is a small, closed token API mapped to CSS variables; you can’t inject arbitrary CSS through it. See Appearance & theming for the full surface.
<Interview
studyId={studyId}
appearance={{
colorScheme: 'auto',
variables: { colorPrimary: '#B43F7F', borderRadius: '12px' },
}}
/>Overriding screens
Stay in the styled layer but replace individual phase screens with slots. Each slot maps to a phase; everything else keeps the default branded screen.
<Interview
studyId={studyId}
slots={{
completion: <MyThankYou />,
// A ReactNode replaces the errored-phase screen. Read the error via
// useInterview().error from inside your component.
error: <MyErrorScreen />,
}}
/>error slot’s function form is for React render crashes, not SDK errors. See the full slot → phase mapping.Restarting the journey
Terminal phases (e.g. completed) are one-shot. To run again, remount the provider by bumping a React key. That builds a fresh core and the journey starts over.
const [runId, setRunId] = useState(0);
<DialogueProvider key={runId} bootstrapTokenProvider={getToken}>
<Interview studyId={studyId} onFinish={() => setRunId((n) => n + 1)} />
</DialogueProvider>