Sakuga Back to Sakuga
Theme
Sound
Jump to a component

Core · Containers

Sheet

Sheet is the bottom panel on phones for choices that belong to the current screen: audio and subtitles, reading direction.

@anicanon/sakuga/uiv1.0Used oniOS · Android

Native on iOS and Android

Sakuga for iOS and Android is coming

Sheet is native on iOS and Android: each platform draws it in its own language, so the web package has none to show here.

iOS

Coming soon

Sheet is native on iOS: the system draws it, and Sakuga for iOS will give it Sakuga’s tokens.

Android

Coming soon

Sheet is native on Android: the system draws it, and Sakuga for Android will give it Sakuga’s tokens.

Use it for
Choices that belong to the current phone screen: audio and subtitles, reading direction, a row's menu.
Not for

Guidelines

  • It slides up from the bottom edge on motion-slow with ease-enter, over a dim sheet-scrim, with a grab handle and a Done button. Tapping the scrim closes it; it slides back down on motion-base with ease-exit.
  • The selected option's fill slides within its group, and its check settles in.
  • Group options with Sheet.Group (a short heading) and Sheet.Option (one choice, check on the selected one).
  • media over video or manga pages, so it stays dark in either theme.
  • Desktop uses a popover menu for the same choices, not a sheet.
  • It stays silent, on the web and in the apps (README · Sound).
  • An option can hold a lead (a CastAvatar, a Thumb) and two lines of Text; the row grows past its 48 px when it needs to. doneLabel={null} drops Done when an option or a button below is the action.

Props

SheetProps

openrequired
boolean
titlerequired
string
onClose
() => void
media
boolean
doneLabel
string | null
childrenrequired
ReactNode
className
string

SheetGroupProps

titlerequired
string
childrenrequired
ReactNode

SheetOptionProps · Holds a lead (CastAvatar, Thumb) and one or two lines; grows past 48 px when it needs to.

selected
boolean
onSelect
MouseEventHandler
childrenrequired
ReactNode
TypeScript
export interface SheetProps {
  open: boolean;
  title: string;
  onClose?: () => void;
  media?: boolean;
  doneLabel?: string | null;
  children: ReactNode;
  className?: string;
}

export interface SheetGroupProps {
  title: string;
  children: ReactNode;
}

/** Holds a lead (CastAvatar, Thumb) and one or two lines; grows past 48 px when it needs to. */
export interface SheetOptionProps {
  selected?: boolean;
  onSelect?: MouseEventHandler;
  children: ReactNode;
}
SheetExample.swiftiOS · coming soon
SheetExample.ktAndroid · coming soon

Each 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

sheet-bgSheet: the sliding panel over the page.
bg-glass-strongglass-light-a90rgba(250,250,252,0.9)
bg-glass-strongglass-dark-a82rgba(28,28,34,0.82)
sheet-media-bgSheet media: the panel over video.
bg-glass-media-strongglass-dark-a82rgba(28,28,34,0.82)
bg-glass-media-strongglass-dark-a82rgba(28,28,34,0.82)
sheet-handleSheet: the grab handle.
border-controlshade-a52rgba(11,10,16,0.52)
border-controlwhite-a45rgba(255,255,255,0.45)
sheet-scrimSheet: the dim layer behind it.
bg-overlayshade-a40rgba(11,10,16,0.4)
bg-overlayblack-a50rgba(0,0,0,0.5)
sheet-row-selected-bgSheet: the chosen row.
bg-fill-selectedshade-a08rgba(11,10,16,0.08)
bg-fill-selectedwhite-a12rgba(255,255,255,0.12)
sheet-checkSheet: the check beside the chosen row.
accentcamellia-600#c2335f
accentcamellia-400#f4779f
sheet-media-done-bgSheet media: the Done button over video.
action-medianeutral-0#ffffff
action-medianeutral-0#ffffff
sheet-media-done-fgSheet media: Done label.
text-on-action-medianeutral-925#0b0a10
text-on-action-medianeutral-925#0b0a10
sheet-fgSheet: row names.
text-primaryneutral-925#0b0a10
text-primaryneutral-0#ffffff
sheet-titleSheet: group headings.
text-mutedneutral-600#5c5b67
text-mutedneutral-400#a3a3a7
sheet-borderSheet: panel edge.
border-glasswhite-a70rgba(255,255,255,0.7)
border-glasswhite-a16rgba(255,255,255,0.16)
sheet-media-fgSheet media: row names over video.
text-on-medianeutral-0#ffffff
text-on-medianeutral-0#ffffff
sheet-media-titleSheet media: group headings over video.
text-on-media-mutedneutral-400#a3a3a7
text-on-media-mutedneutral-400#a3a3a7
sheet-media-borderSheet media: panel edge.
border-glass-mediawhite-a16rgba(255,255,255,0.16)
border-glass-mediawhite-a16rgba(255,255,255,0.16)

Space and shape

sheet-radius
radius-2xl
32px
sheet-inset
inset-sm
8px
sheet-padding-top
inset-sm
8px
sheet-padding-x
inset-lg
16px
sheet-padding-bottom
inset-xl
24px
sheet-blur
blur-glass
blur(22px) saturate(1.8)
sheet-inset-ring-width
line-hairline
1px
sheet-media-inset-ring-width
line-hairline
1px
sheet-handle-width
its own value
36px
sheet-handle-height
its own value
4px
sheet-handle-radius
radius-xs
4px
sheet-handle-margin-bottom
gap-lg
12px
sheet-title-margin-bottom
gap-md
8px
sheet-row-min-height
size-target
44px
sheet-row-radius
radius-sm
8px
sheet-row-gap
gap-lg
12px
sheet-row-padding-y
inset-sm
8px
sheet-row-padding-x
inset-md
12px
sheet-row-active-scale
scale-press-lg
.98
sheet-row-check-icon-size
icon-size-sm
16px
sheet-done-margin-top
gap-lg
12px
sheet-group-margin-bottom
gap-lg
12px
sheet-group-glide-radius
radius-sm
8px

Type

sheet-font-family
font-sans
Funnel Sans
sheet-title-font
text-micro
700 12px/16px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
sheet-row-font
text-subtitle-sm
600 16px/22px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif

Motion

sheet-scrim-fade-in-animation
motion-scrim-in
sk-fade-in 360ms linear
sheet-in-animation
its own value
sk-slide-in 360ms cubic-bezier(0, 0, 0, 1)
sheet-row-duration
motion-fast
160ms
sheet-row-easing
ease-standard
cubic-bezier(0.2, 0, 0, 1)
sheet-row-active-duration
motion-instant
100ms
sheet-row-check-settle-animation
motion-settle
sk-settle 240ms cubic-bezier(0, 0, 0, 1)
sheet-scrim-leaving-fade-out-animation
motion-scrim-out
sk-fade-out 240ms linear
sheet-leaving-out-animation
its own value
sk-slide-out 240ms cubic-bezier(0.3, 0, 1, 1)
sheet-scrim-fade-in-animation
motion-scrim-in
sk-fade-in 360ms linear
sheet-scrim-leaving-fade-out-animation
motion-scrim-out
sk-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 title: focus moves to the chosen option (else the first control), Tab and Shift+Tab stay inside it, Escape, Done or a tap on the scrim run onClose, and focus goes back to what opened it. Sheet.Group is a group named by its title, and each Sheet.Option is a toggle button, "pressed" when selected, with its check hidden.
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.