| name | write-example |
| description | Write demo/example files for ink-cartridge components and APIs. Use when the user wants to create a demo, write an example, or add a showcase for a component or API. |
Entry
Must first ask the user to choose an interaction mode:
- Auto-explore — AI reads source and existing examples, analyzes, drafts boilerplate, writes after user confirms
- Step-by-step — AI asks the user one question at a time; user drives the scope
Then must ask: new example or updating existing example?
Auto-explore workflow (new example)
- Ask: which component/API needs an example?
- Read the source file — extract props signature,
focusId usage, keyboard hooks (useKeyboard, overlay, openModal), state requirements
- Must read at least one existing example from the same category to match style. Categories:
- Simple — Badge, Spinner, Divider, KeyHint, ProgressBar, theme-only, i18n-only. No
focusId, no keyboard hooks, no navigation.
- Interactive — NumberInput, Tabs, Form, Fold, MultiSelectInput, SearchBar, SearchInput. Has
focusId or keyboard bindings.
- With overlay/modal — core/overlay, core/modal. Calls
overlay() or openModal().
- Determine the pattern from the component source:
- Simple → direct
render(<Demo />), no providers, no registerComponent
- Interactive →
registerComponent(Demo, {}) + <ScenarioManagementProvider><KeyboardProvider><CurrentScreen /></>
- With overlay/modal → Interactive +
fullScreen + useWindowSize() + position="absolute"
- Draft the complete demo and present it to the user
- User confirms; write the file to
examples/<component-name>/<ComponentName>[.variant].demo.tsx
- Must run
npx tsc -p examples/tsconfig.json --noEmit and ensure it passes
- Must update
examples/README.md — add a row to the correct table (Component Demos or Core System Demos)
If tsc reports any type errors, must fix them and re-run until clean.
Auto-explore workflow (update existing example)
- Read the existing demo file
- Read the source for changed props/signatures
- Identify precise differences
- Update the demo to reflect the current API; must not rewrite the whole file
- Show the diff to the user for confirmation
- Write the changes
- Must run
npx tsc -p examples/tsconfig.json --noEmit
Step-by-step workflow (new example)
- Ask: which component/API needs an example?
- Ask: which features/variants should be demonstrated?
- Read the source and at least one existing example of the same category
- List the features to demonstrate; user confirms
- Generate the demo
- Must run
npx tsc -p examples/tsconfig.json --noEmit
- Must update
examples/README.md
Step-by-step workflow (update existing example)
- Ask: which demo file and what specifically changed?
- Read existing demo + source
- Show the identified differences; user confirms
- Modify affected sections only
Boilerplate templates
Simple (static) pattern
import React from 'react';
import { render, Box, Text } from 'ink';
import { ComponentName } from '../../src/components/<name>/ComponentName.js';
function Demo() {
return (
<Box flexDirection="column" padding={1}>
<Text bold underline>ComponentName demo</Text>
<Box flexDirection="column" marginTop={1} gap={1}>
{/* showcase variants here */}
</Box>
</Box>
);
}
render(<Demo />);
Interactive pattern
import React, { useState } from 'react';
import { render, Box, Text } from 'ink';
import {
registerComponent,
ScenarioManagementProvider,
CurrentScreen,
KeyboardProvider,
} from '../../src/index.js';
import { ComponentName } from '../../src/components/<name>/ComponentName.js';
import { Divider } from '../../src/components/divider/Divider.js';
import { KeyHint } from '../../src/components/key-hint/KeyHint.js';
function Demo() {
const [value, setValue] = useState();
return (
<Box flexDirection="column" padding={1}>
<Text bold underline>ComponentName demo</Text>
<Text dimColor>Tab to switch focus</Text>
<Box flexDirection="column" marginTop={1} gap={1}>
{/* showcase variants here */}
</Box>
<Divider />
<KeyHint keys={[
{ key: 'Tab', desc: 'Switch focus' },
{ key: 'q', desc: 'Quit' },
]} />
</Box>
);
}
registerComponent(Demo, {});
function App() {
const { boundKeyboard } = useKeyboard();
React.useEffect(() => {
const unbind = boundKeyboard(['q'], () => process.exit(0));
return unbind;
}, [boundKeyboard]);
return <CurrentScreen />;
}
registerComponent(App, {});
render(
<ScenarioManagementProvider defaultScreen={Demo}>
<KeyboardProvider>
<App />
</KeyboardProvider>
</ScenarioManagementProvider>,
);
Overlay/modal positioning (add to interactive pattern)
const OVERLAY_W = 40;
const OVERLAY_H = 8;
function center(width: number, height: number, cols: number, rows: number) {
return {
top: Math.max(0, Math.floor((rows - height) / 2)),
left: Math.max(0, Math.floor((cols - width) / 2)),
};
}
const { columns, rows } = useWindowSize();
const { top, left } = center(OVERLAY_W, OVERLAY_H, columns, rows);
<Box
position="absolute"
top={top}
left={left}
width={OVERLAY_W}
height={OVERLAY_H}
borderStyle="round"
borderColor="blue"
padding={1}
backgroundColor="black"
>
And on the provider:
<ScenarioManagementProvider defaultScreen={MainScreen} fullScreen>
Non-negotiable conventions
- File naming:
{ComponentName}[.{variant}].demo.tsx (e.g., Badge.demo.tsx, SearchBar.multi.demo.tsx)
- Directory:
examples/<component-name>/
- All text must be in English — comments, UI strings, key descriptions
- Must use JSX;
React.createElement is forbidden
- Overlay/modal components must use
position="absolute" + useWindowSize() centering + backgroundColor="black" + fullScreen on provider
- Single-API showcase only. Multi-system stress tests go to
ink-blots/
- Must add a keyboard shortcut to exit (
q → process.exit(0)) in every interactive demo
- Must update
examples/README.md when adding a new demo
- Must not write test files under
examples/
- Must run
npx tsc -p examples/tsconfig.json --noEmit and ensure zero errors
- In the interactive pattern,
KeyboardProvider must nest inside ScenarioManagementProvider (reversed silently breaks keyboard)
Audit reminder
After writing the demo, must remind the user: verify the demo reflects the current component API — no stale props, no missing features, features shown are correct for the latest version.