Jump to a component
AniCanonKit · Productions
EditorShell
EditorShell is the full-screen editor (Cut). Slots: nav (the ProductionNav rail), header (EditorHeader), tool (the open tool’s panel, 312 px), inspector (the selected item, 300 px), overlay (a dialog over the editor). Its main content is the centre column: Monitor, MonitorBar, the ProgramBar and the Timeline.
Live, from @anicanon/sakuga 2.0.0
Sakuga for iOS and Android is coming
iOS
Web only
EditorShell is made for the web, and isn’t part of Sakuga for iOS yet.
Android
Web only
EditorShell is made for the web, and isn’t part of Sakuga for Android yet.
- Use it for
- The full-screen editor (Cut, and Art and Lettering in manga): the rail, header, tool panel, inspector and the centre column with the monitor, program bar and timeline, with
focusfor the canvas alone. - Not for
- A production view outside the editorViewHeader
- A full-screen flow that makes one thing step by stepFlowHeader
- A task over the pageDialog
Guidelines
EditorHeader:title,timecode, an optionalstatus(Rebuilds exactly) and the actions as children.Monitor: the picture (image,imageStyle) withlabelsin its corner (labelsEndfor the other corner) and overlays as children;guidesdraws title-safe or an effect's area (accentfor the selected one) andregionthe area an edit works on, with its label;centeredputs a frame in the middle;filllets it take the column's height (the manga page canvas);fit="contain"shows the whole picture (a take in Studio) instead of filling the frame.MonitorBar: slotstransportandend, thetimecode, the edit buttons as children.- Nothing floats over the picture except the corner labels and what you are editing on it.
CanvasStagereplaces theMonitorwhile an item is selected on the canvas: the frame, the item at itsbox(percent of the frame; it may run past the edges, shown dimmed), and a box with eight handles to move and resize it.focusturns the shell into focus mode: the rail, header, tool panel and inspector fold away; the monitor grows and the transport and timeline stay, since editing needs them. The page sets it: F or Full screen enters focus, F or Esc leaves it.- The
floatslot holds what comes back on demand. The shell covers itself with it and shows it as focus starts and whenever the pointer moves, then fades it out after 2 s still, never while the pointer rests on it or focus is in it. The page lays it out, as the Productions focus board does: one row across the top, 20 px from the top and 24 px (inset-xl) from the sides, 10 px apart. In it, aFloatingToolbarnamed "Production" with the production's name and the timecode; aFloatingToolbarnamed "Tools" with the tools asmediaIconButtons; and at the far end Leave focus, amedia-secondaryButton (sm, thefullscreenicon). While the bars show, the Monitor's corner labels step aside (the Production bar carries the timecode), and they come back when the bars fade. - Motion follows the editor motion sheet: panels on
motion-base, selection onmotion-instantwithease-enter, focus onmotion-slow; dragging never eases. Under reduced motion every move becomes a short fade or nothing.
CanvasStagetakesonBox(box): the box becomes one Tab stop, arrows move it a percent and Shift with an arrow resizes it.
import { Button, FloatingToolbar, IconButton } from '@anicanon/sakuga/ui';
import {
EditorHeader,
EditorShell,
Monitor,
MonitorBar,
} from '@anicanon/sakuga/anicanonkit';
const on = {
color: 'var(--text-on-media)',
font: '700 14px/18px var(--font-display)',
padding: '0 6px',
};
const onMuted = {
color: 'var(--text-on-media-muted)',
font: '600 12.5px/16px var(--font-sans)',
paddingRight: 6,
};
const tools = [
['collection', 'Media'],
['template', 'Titles'],
['effect-sparks', 'Effects'],
['sliders', 'Adjust'],
['volume', 'Audio'],
];
const focusShell = (
<EditorShell height={240} focus>
<Monitor image="/art/eba-cinema.webp" height={150} />
<MonitorBar timecode="2:41 + 04f">
<Button variant="ghost" size="sm">
Split
</Button>
</MonitorBar>
<span slot="float">
<div
style={{
position: 'absolute',
left: 24,
right: 24,
top: 20,
display: 'flex',
alignItems: 'center',
gap: 10,
}}
>
<FloatingToolbar label="Production">
<b style={on}>The First Watch</b>
<span style={onMuted}>Cut · 2:41 + 04f</span>
</FloatingToolbar>
<FloatingToolbar label="Tools">
{tools.map((t) => (
<IconButton key={t[1]} variant="media" icon={t[0]} label={t[1]} />
))}
</FloatingToolbar>
<span style={{ flex: 1 }} />
<Button variant="media-secondary" size="sm" icon="fullscreen">
Leave focus
</Button>
</div>
</span>
</EditorShell>
);
export default function EditorShellExample() {
return (
<>
<EditorShell height={240}>
<span slot="header">
<EditorHeader
title="The First Watch"
timecode="Cut · 2:41 + 04f of 6:40"
status="Rebuilds exactly"
>
<Button variant="primary" size="sm">
Screen the cut
</Button>
</EditorHeader>
</span>
<span slot="tool">
<div style={{ font: '600 13px var(--font-sans)' }}>Media</div>
</span>
<Monitor
image="/art/eba-cinema.webp"
labels={['2C · take 3', '2:41 + 04f']}
height={110}
/>
<MonitorBar timecode="2:41 + 04f">
<Button variant="ghost" size="sm">
Split
</Button>
</MonitorBar>
<span slot="inspector">
<div style={{ font: '600 13px var(--font-sans)' }}>Cut 2C</div>
</span>
</EditorShell>
{focusShell}
</>
);
}PropsEditorShellProps
heightnumberfocusbooleanfloat holds the bars that come back on demand.inspectorLabelstringchildrenReactNodeclassNamestringEach 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
editor-center-focus-padding-topinset-smeditor-center-focus-padding-xinset-mdeditor-center-focus-padding-bottominset-mdeditor-center-focus-gapgap-mdeditor-tool-widtheditor-tool-gapgap-lgeditor-tool-paddinginset-lgeditor-tool-border-right-widthline-hairlineeditor-center-gapgap-mdeditor-center-padding-yinset-mdeditor-center-padding-xinset-mdeditor-inspector-widtheditor-inspector-gapgap-lgeditor-inspector-paddinginset-lgeditor-inspector-border-left-widthline-hairlineType
editor-font-familyfont-sansMotion
editor-tool-durationmotion-baseeditor-tool-easingease-standardeditor-tool-opacity-durationmotion-fasteditor-float-durationmotion-baseeditor-float-easingease-standardChecked 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 layout with no keyboard handling of its own: Tab moves through its slots in order (nav, header, tool, centre, inspector), the inspector is a complementary region named by
inspectorLabel(default "Inspector"), and EditorHeader's title is a level-1 heading. CanvasStage's selection is a group named bylabeland described by its position and size; withonBoxit is an application (a "movable item") and one Tab stop where arrows move it and Shift with an arrow resizes it, each change said aloud, and its handles are 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.