Sakuga Back to Sakuga
Theme
Sound
Jump to a component

AniCanonKit · Productions

PromptComposer

PromptComposer is Studio's prompt: who and where it binds on top, the words, then its tools.

@anicanon/sakuga/anicanonkitv1.0Used onWeb · iOS · AndroidFrom AniCanon™

Live, from @anicanon/sakuga 2.0.0

Sakuga for iOS and Android is coming

iOS

Coming soon

PromptComposer for iOS is in the roughs. The tokens it will read are the ones on this page, the same on every platform.

Android

Coming soon

PromptComposer for Android is in the roughs. The tokens it will read are the ones on this page, the same on every platform.

Use it for
The prompt that makes a take (in Studio, and for episodes in Quick mode): the cast, places and references it binds on top, the words, then its tools with Generate and its cost, and variant="media" as the phone's dock over the take.
Not for

Guidelines

  • slot="refs": MentionChips for the cast (@), places (#) and references ($) the prompt binds.
  • The words are its children; a mention inside them is a Mention.
  • slot="tools": the opening frame, the length, templates, with Generate (a SpendButton and its cost) at the end of the row (or in slot="footer").
  • placeholder shows while there are no words; slot="hint" is the one line that says what is missing before Generate works ("Add a place, or describe the moment in 24 characters or more").
  • variant="media" is the phone's dock over the take: glass, and its chips take tone="media".
  • Episodes in Quick mode and Studio take from the same composer.
  • onInput(text) makes the words a field the creator writes in, as plain text, showing placeholder until they type; value sets its text. Without onInput the words only show.
PromptComposerExample.jsxReact
import { Button, IconButton } from '@anicanon/sakuga/ui';
import {
  Mention,
  MentionChip,
  PromptComposer,
  SpendButton,
} from '@anicanon/sakuga/anicanonkit';

export default function PromptComposerExample() {
  return (
    <PromptComposer label="Make a take">
      <Mention>Lisa</Mention>
      {
        ' waits for the last train in the rain; the doors close before she moves.'
      }
      <span slot="refs">
        <MentionChip name="Lisa" note="school" />
        <MentionChip
          kind="place"
          name="Red Line Platform Edge"
          image="/art/eba-cinema.webp"
        />
      </span>
      <span slot="tools">
        <IconButton variant="plain" icon="image" label="Opening frame" />
        <Button variant="ghost" size="sm" icon="clock">
          10 s
        </Button>
      </span>
      <span slot="footer">
        <SpendButton variant="primary" fullWidth cost="~100">
          Generate
        </SpendButton>
      </span>
    </PromptComposer>
  );
}

PropsPromptComposerProps

label
string
promptLabel
string
placeholder
string
onInput
(text: string) => void
Makes the words a plain-text field the creator writes in; called with its text. Without it the words only show.
value
string
With onInput: the text the field holds.
children
ReactNode
className
string
PromptComposerExample.swiftiOS · coming soon
PromptComposerExample.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

composer-bgPromptComposer: its surface.
bg-surfaceneutral-0#ffffff
bg-surfaceneutral-900#111117
composer-edgePromptComposer: its edge.
border-dividershade-a12rgba(11,10,16,0.12)
border-dividerwhite-a12rgba(255,255,255,0.12)
composer-fgPromptComposer: the words.
text-primaryneutral-925#0b0a10
text-primaryneutral-0#ffffff
composer-rulePromptComposer: the rule over its tools.
border-hairlineshade-a08rgba(11,10,16,0.08)
border-hairlinewhite-a06rgba(255,255,255,0.06)

Space and shape

composer-radius
radius-xl
24px
composer-inset-ring-width
line-hairline
1px
composer-padding-y
inset-md
12px
composer-padding-x
inset-lg
16px
composer-refs-gap
gap-sm
6px
composer-prompt-padding-top
inset-md
12px
composer-prompt-padding-x
inset-xs
4px
composer-prompt-padding-bottom
inset-sm
8px
composer-prompt-focus-radius
radius-xs
4px
composer-tools-gap
gap-xs
4px
composer-tools-border-top-width
line-hairline
1px
composer-tools-padding-top
inset-md
12px
composer-foot-padding-top
inset-sm
8px
composer-hint-gap
gap-sm
6px
composer-hint-margin-bottom
gap-md
8px
composer-hint-padding-x
inset-xs
4px
composer-media-radius
radius-xl
24px
composer-media-padding
inset-md
12px
composer-media-blur
blur-glass
blur(22px) saturate(1.8)
composer-media-inset-ring-width
line-hairline
1px
composer-media-prompt-padding-y
inset-sm
8px
composer-media-prompt-padding-x
inset-xs
4px
composer-media-tools-gap
gap-xs
4px
composer-forced-edge-width
line-hairline
1px
composer-forced-focus-width
line-strong
2px

Type

composer-prompt-font
text-body-lg
400 15px/24px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
composer-hint-font
text-caption
500 13px/18px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
composer-media-prompt-font-size
text-body-lg-size
15px
Aa
composer-media-prompt-line-height
text-body-lg-line-height
24px

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 region named by label (default "Prompt"): Tab reaches the refs, then the words, then the tools. With onInput the words are a multi-line text box named by promptLabel (default "Prompt") that takes typing as plain text, with placeholder as its placeholder; without it they are text and take no focus.
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.