Intro Disclosure
OnboardingMITFirst-time-user disclosure card with multi-step walkthrough.
bun add @otfdashkit/ui
Preview
Intro DisclosureOnboarding
Loading Storybook preview…
Code
@otfdashkit/uiimport React, { useState } from 'react'
import { IntroDisclosure, Button } from '@otfdashkit/ui'
import { Sparkles, Users, GitBranch, Rocket } from 'lucide-react'
const INTRO_STEPS = [
{
title: 'Welcome to OTF',
description: 'A typed, accessible component library + AI-ready kits. Ship faster, look premium by default.',
media: (
<div className="absolute inset-0 flex items-center justify-center bg-gradient-to-br from-primary/20 via-primary/5 to-transparent">
<Sparkles className="h-16 w-16 text-primary" strokeWidth={1.25} />
</div>
),
},
{
title: 'Bring your team',
description: 'Invite collaborators, assign roles, and share context across projects.',
media: (
<div className="absolute inset-0 flex items-center justify-center bg-[hsl(var(--muted)/0.5)]">
<Users className="h-16 w-16 text-foreground/70" strokeWidth={1.25} />
</div>
),
},
{
title: 'Connect your repo',
description: 'Link a GitHub repository to sync issues and let Claude ship pull requests.',
media: (
<div className="absolute inset-0 flex items-center justify-center bg-[hsl(var(--muted)/0.5)]">
<GitBranch className="h-16 w-16 text-foreground/70" strokeWidth={1.25} />
</div>
),
},
{
title: 'Ship something',
description: 'You\'re ready. Open the command palette (⌘K) and start a task.',
media: (
<div className="absolute inset-0 flex items-center justify-center bg-gradient-to-tr from-primary/15 to-transparent">
<Rocket className="h-16 w-16 text-primary" strokeWidth={1.25} />
</div>
),
},
]
export function Example() {
function Demo() {
const [open, setOpen] = useState(true)
return (
<div className="relative h-[600px] w-[800px] bg-[hsl(var(--background))] rounded-md border border-[hsl(var(--border))] overflow-hidden">
<div className="absolute inset-0 flex items-center justify-center">
<Button onClick={() => setOpen(true)}>
<Sparkles className="h-4 w-4 mr-2" /> Show intro
</Button>
</div>
<IntroDisclosure
open={open}
onOpenChange={setOpen}
eyebrow="What's new"
steps={INTRO_STEPS}
storageKey={undefined}
/>
</div>
)
}
return <Demo />
}
Free with the SDK. This pattern ships in @otfdashkit/ui under the MIT license.
Props
Props declared in the IntroDisclosure source. Inherited HTML attributes are not listed.
| Prop | Type | Default | Description |
|---|---|---|---|
| stepsrequired | IntroStep[] | The steps to walk through, in order. | |
| eyebrow | string | Optional extra label e.g. "What's new in 2.0". | |
| finishLabel | string | 'Get started' | Final-step CTA label. Default "Get started". |
| onOpenChange | (open: boolean) => void | Called when the user dismisses (skip / done / backdrop / escape). | |
| open | boolean | Controlled open prop. If omitted, falls back to localStorage on mount. | |
| skipLabel | string | 'Skip' | Skip button label. Default "Skip". |
| storageKey | string | 'otf:intro-seen' | localStorage key. Once seen, the component stays closed for that key. Set to `undefined` to disable persistence (always opens). |