Theme
Sound
Jump to a component
AniCanonKit · Characters
CoverageTable
Wardrobe coverage: a row per character and a column per occasion the scripts ask for.
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.
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). legendnames the three states over the table;summarycounts the gaps and says which script they come from.- A gap is the only accent; nothing else is coloured.
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
occasionsrequiredstring[]rowsrequired{ name: string; image?: string; cells: { state: CoverState; label?: string; }[]; }[]legend{ state: CoverState; label: string; }[]summarystringrowLabelstringlabelstringclassNamestringTypes
type CoverState = 'own' | 'gap' | 'idle';
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-gapgap-lg12px
coverage-legend-gapgap-xl16px
coverage-legend-span-gapgap-sm6px
coverage-key-sizeicon-size-md20px
coverage-key-radiusradius-sm8px
coverage-table-border-spacinggap-sm6px
coverage-table-th-padding-bottominset-xs4px
coverage-table-who-widthits own value
200px
coverage-who-span-gapgap-md8px
coverage-who-img-sizeits own value
36px
coverage-who-img-radiusradius-full9999px
coverage-cell-heightits own value
56px
coverage-cell-radiusradius-md12px
coverage-gap-inset-ring-widthline-strong2px
coverage-idle-inset-ring-widthline-hairline1px
Type
coverage-font-familyfont-sansFunnel Sans
coverage-legend-fonttext-caption500 13px/18px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
coverage-table-th-fonttext-micro700 12px/16px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
coverage-table-who-font-sizetext-body-size14px
Aa
coverage-cell-fonttext-caption-strong600 13px/18px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
Motion
coverage-cell-durationmotion-base240ms
coverage-cell-easingease-standardcubic-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
labelwith 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.