Theme
Sound
Jump to a component
Core · Containers
Dialog
Dialog is a desktop window over the page: pickers (references, opening frame, video plan), confirmations (story conflicts) and last checks (clip options).
Live, from @anicanon/sakuga 2.0.0
Sakuga for iOS and Android is coming
iOS
Web only
Dialog is made for the web, and isn’t part of Sakuga for iOS yet.
Android
Web only
Dialog is made for the web, and isn’t part of Sakuga for Android yet.
- Use it for
- A task or a check that needs the page's whole attention on desktop: choosing references, a story conflict, the last check before something is spent or deleted.
Guidelines
- Title says the task; description says what happens and what it costs, if anything.
- The main action sits right in the footer, labelled with what it does ("Add 2 references", "Generate clip").
- It settles in on
motion-slowwithease-enterand leaves onmotion-basewithease-exit. - Its scrim fades in over
motion-slowand out overmotion-base, both linear, so the fade reads as one. - With sound on, it plays the open sound as it arrives and the close sound as it leaves (README · Sound).
- Phones use Sheet instead.
- The footer's buttons are
footer, or children inslot="footer".
import { useState } from 'react';
import { Button, Dialog } from '@anicanon/sakuga/ui';
export default function DialogExample() {
const [open, setOpen] = useState(true);
const close = () => setOpen(false);
return (
<>
<Button variant="secondary" onClick={() => setOpen(true)}>
Choose a video plan
</Button>
<Dialog
open={open}
onClose={close}
title="Choose a video plan"
description="Plans differ in motion polish and what they need from you."
width={520}
footer={[
<Button key="a" variant="ghost" onClick={close}>
Cancel
</Button>,
<Button key="b" variant="primary" onClick={close}>
Use Regular
</Button>,
]}
>
<p style={{ margin: 0, color: 'var(--text-secondary)' }}>
Plan cards go here.
</p>
</Dialog>
</>
);
}PropsDialogProps
openrequiredbooleantitlerequiredstringdescriptionstringfooterReactNodeOr children in slot="footer".
widthnumber | stringonClose() => voidchildrenReactNodeclassNamestringEach token reads a role, and the role lands on a value in each theme. Change the role and every component that reads it follows.
Colour
dialog-bgDialog: panel.bg-surfaceneutral-0#ffffffbg-surfaceneutral-900#111117dialog-borderDialog: panel edge.border-dividershade-a12rgba(11,10,16,0.12)border-dividerwhite-a12rgba(255,255,255,0.12)dialog-scrimDialog: dim layer behind it.bg-overlayshade-a40rgba(11,10,16,0.4)bg-overlayblack-a50rgba(0,0,0,0.5)dialog-titleDialog: title.text-primaryneutral-925#0b0a10text-primaryneutral-0#ffffffdialog-descriptionDialog: line under the title.text-mutedneutral-600#5c5b67text-mutedneutral-400#a3a3a7Space and shape
dialog-widthits own value
720px
dialog-radiusradius-xl24px
dialog-inset-ring-widthline-hairline1px
dialog-head-gapgap-lg12px
dialog-head-padding-topinset-lg16px
dialog-head-padding-xinset-xl24px
dialog-head-padding-bottominset-lg16px
dialog-desc-margin-topgap-xs4px
dialog-body-padding-xinset-xl24px
dialog-body-padding-bottominset-lg16px
dialog-foot-gapgap-md8px
dialog-foot-padding-yinset-lg16px
dialog-foot-padding-xinset-xl24px
dialog-foot-border-top-widthline-hairline1px
dialog-forced-edge-widthline-hairline1px
Type
dialog-font-familyfont-sansFunnel Sans
dialog-title-fonttext-title-3700 20px/26px "Funnel Display", "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
dialog-desc-fonttext-body400 14px/20px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
Motion
dialog-scrim-fade-in-animationmotion-scrim-insk-fade-in 360ms linear
dialog-in-animationits own value
sk-emerge 360ms cubic-bezier(0, 0, 0, 1)
dialog-scrim-leaving-fade-out-animationmotion-scrim-outsk-fade-out 240ms linear
dialog-scrim-leaving-out-animationits own value
sk-recede 240ms cubic-bezier(0.3, 0, 1, 1)
dialog-scrim-fade-in-animationmotion-scrim-insk-fade-in 360ms linear
dialog-scrim-leaving-fade-out-animationmotion-scrim-outsk-fade-out 240ms linear
Checked automatically with axe-core 4.11.4 against WCAG 2.2 A and AA, on the live preview above, in light and dark, on 26 October 2026.
- Result
- No issues found, in light or in dark.
- By design
- A modal dialog named by
titleand described bydescription: focus moves to the first control in its body (else its footer, else "Close"), Tab and Shift+Tab stay inside it, a press on its words keeps focus inside, and Escape, "Close" or a click on the scrim runonClose. When it closes, focus goes back to what opened it. - Not tested
- The automated check doesn't test keyboard use, focus order or what a screen reader says. The lines above are the design system's own account of them.