Sakuga Back to Sakuga
Theme
Sound
Jump to a component

Guide

Core or AniCanonKit

Where a component lives, and how a new one earns its place.

Sakuga is one design system with two libraries, and every component belongs to exactly one.

Sakuga, the core (@anicanon/sakuga/ui) is for anything built around art: actions, forms, navigation, content, feedback, media, containers, type and icons. A component belongs here when it would make sense in a product that has never heard of AniCanon™.

AniCanonKit (@anicanon/sakuga/anicanonkit) is AniCanon™'s own: its currency (Fragments), its assistant Maki, its characters and wardrobe, its story graph, its productions, its manga pages and its writing room. It is built only from core components and core tokens, and it never restyles a core component. AniCanon™ is at anicanon.studio.

To place a component, ask in this order:

  1. Is it an existing component with other props? Then it is that component: add the prop. Two things are one component when one is the other with props, with the same states and nothing lost. Looking alike is not enough.
  2. Does it only work with AniCanon™'s own data or rules? Fragments, Maki, a character's stats or looks, a faction, a story event, a cut, a production, a manga page. Then it belongs in AniCanonKit.
  3. Otherwise it belongs in the core. Words like episode, cast or character don't make a component AniCanon™'s: any product about anime has them.

The core never draws a Kit part (Raul, 2026-10-25). Where a core component holds a value AniCanon™ fills, such as a price, it takes a neutral slot (Button's trailing, an OptionTiles option's amount and cost), and the Kit adds the part that fills it: SpendButton and SpendTiles draw the fragment mark. Nothing in the core uses the Kit.

Adding a component

  1. Pass the merge test. If it is an existing component with other props, extend that one instead.
  2. Earn its place. A new component has a real job that repeats on more than one screen. A one-off stays layout and Text.
  3. Place it in the core or AniCanonKit, with the three questions above.
  4. Name it for what it is, not for the screen it first appeared on.
  5. Give it its own tokens. It reads only its own component tokens (<prefix>-*), which alias semantic tokens. It never reads a semantic or core value directly, with one exception: keyboard focus is one ring everywhere, drawn with the shared focus-ring, focus-ring-width and focus-ring-offset (a component's own token may set where the ring sits).
  6. Write its README. The first sentence says what it is, then come its guidelines. It ends with a When to use section: what it is for, a line for every component it could be mistaken for that names the one to use instead, the platforms it is used on, what a keyboard and a screen reader get from it, and its version.
  7. Ship the rest of it: a preview.html whose @dsCard label names its library (Sakuga · Group or AniCanonKit · Group), its interface in index.d.ts, and its line in this README's component list.

Under its ## When to use heading, the section reads like this, and the tools read it in exactly this shape:

Use it for an action with a word on it: the one main action of a view.

- Not for an action inside a sentence or a row of text: use `TextLink`.
- Not for an action that one glyph says better than a word: use `IconButton`.

Used on: Web, iOS, Android
Accessibility: A native button (a link with `href`): Tab reaches it, Enter activates it, and Space does too on a button. A screen reader hears its text, or `aria-label`.
Version: 1.0

The Accessibility line says what the component does today, read from its code: its role, which prop names it, its states and its keys. Anything a keyboard or screen-reader user would miss goes after Gap: on the same line, until it is fixed. One line, one Gap: at most.

The component browser on sakuga.design and its llms.txt are built from these files, so a component added this way appears there with nothing else to edit.