Sakuga Back to Sakuga
Theme
Sound
Jump to a component

AniCanonKit · Characters

CoverageTable

Wardrobe coverage: a row per character and a column per occasion the scripts ask for.

@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

CoverageTable 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

CoverageTable 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
Wardrobe coverage across the cast: a row per character, a column per occasion the scripts ask for, and the gaps where a scene needs a look and nothing fits.
Not for

Guidelines

  • A cell says what they have (own, "2 looks"), that a scene needs a look and nothing fits (gap, "3 scenes · nothing"), or that nothing is needed yet (idle).
  • legend names the three states over the table; summary counts the gaps and says which script they come from.
  • A gap is the only accent; nothing else is coloured.
CoverageTableExample.jsxReact
import { CoverageTable } from '@anicanon/sakuga/anicanonkit';

const rows = [
  {
    name: 'Kiko',
    image: '/art/eba-cast-kiko.webp',
    cells: [
      { state: 'own', label: '1 look' },
      { state: 'idle' },
      { state: 'own', label: '1 look' },
      { state: 'idle' },
      { state: 'gap', label: '3 scenes · nothing' },
    ],
  },
  {
    name: 'The Professor',
    image: '/art/eba-cast-the-professor.webp',
    cells: [
      { state: 'own', label: '2 looks' },
      { state: 'idle' },
      { state: 'idle' },
      { state: 'gap', label: '2 scenes · nothing' },
      { state: 'idle' },
    ],
  },
];

export default function CoverageTableExample() {
  return (
    <CoverageTable
      label="Wardrobe coverage"
      summary="2 gaps · from Episode 2"
      legend={[
        { state: 'own', label: 'Has a look' },
        { state: 'gap', label: 'A scene needs it' },
        { state: 'idle', label: 'Not needed yet' },
      ]}
      occasions={['Everyday', 'Uniform', 'Formal', 'Festival', 'Combat']}
      rows={rows}
    />
  );
}

PropsCoverageTableProps

occasionsrequired
string[]
rowsrequired
{ name: string; image?: string; cells: { state: CoverState; label?: string; }[]; }[]
legend
{ state: CoverState; label: string; }[]
summary
string
rowLabel
string
label
string
className
string

Types

type CoverState = 'own' | 'gap' | 'idle';
CoverageTableExample.swiftiOS · coming soon
CoverageTableExample.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.

Space and shape

coverage-gap
gap-lg
12px
coverage-legend-gap
gap-xl
16px
coverage-legend-span-gap
gap-sm
6px
coverage-key-size
icon-size-md
20px
coverage-key-radius
radius-sm
8px
coverage-table-border-spacing
gap-sm
6px
coverage-table-th-padding-bottom
inset-xs
4px
coverage-table-who-width
its own value
200px
coverage-who-span-gap
gap-md
8px
coverage-who-img-size
its own value
36px
coverage-who-img-radius
radius-full
9999px
coverage-cell-height
its own value
56px
coverage-cell-radius
radius-md
12px
coverage-gap-inset-ring-width
line-strong
2px
coverage-idle-inset-ring-width
line-hairline
1px

Type

coverage-font-family
font-sans
Funnel Sans
coverage-legend-font
text-caption
500 13px/18px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
coverage-table-th-font
text-micro
700 12px/16px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
coverage-table-who-font-size
text-body-size
14px
Aa
coverage-cell-font
text-caption-strong
600 13px/18px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif

Motion

coverage-cell-duration
motion-base
240ms
coverage-cell-easing
ease-standard
cubic-bezier(0.2, 0, 0, 1)

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
Not focusable; a table named by label with a column header per occasion and a row header per character, each cell read as its label and its state in the legend's words ("2 looks, Has a look"; a cell without a label reads the state alone), and the legend reads as text with its swatches 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.