Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .claude/skills/ink-tui/references/PRIMITIVES.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ Tabs array can be built conditionally — see `RunScreen.tsx` for an example of

Single and multi select. Fully custom renderers — does NOT use `@inkjs/ui` Select/MultiSelect.

- **Single select**: `▸` triangle cursor on focused item, enter selects
- **Multi select** (`mode="multi"`): `◻`/`◼` toggles with space, enter submits
- **Single select**: `▸` triangle cursor on focused item, space selects
- **Multi select** (`mode="multi"`): `◻`/`◼` toggles with enter, space submits

### ConfirmationInput
`src/ui/tui/primitives/ConfirmationInput.tsx`

Continue/cancel prompt with two bordered button boxes. Left/right arrows switch focus, enter activates focused, escape always cancels.
Continue/cancel prompt with two bordered button boxes. Left/right arrows or enter switch focus, space activates focused, escape always cancels.

### DissolveTransition
`src/ui/tui/primitives/DissolveTransition.tsx`
Expand Down
4 changes: 2 additions & 2 deletions e2e-tests/utils/framework-test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ export const DEFAULT_WIZARD_STEPS: WizardStep[] = [
// {
// name: 'uncommitted',
// waitFor: 'You have uncommitted or untracked files in your repo:',
// response: [KEYS.DOWN, KEYS.ENTER],
// response: [KEYS.DOWN, KEYS.SPACE],
// timeout: 2000,
// optional: true,
// },
{
name: 'mcp',
waitFor:
'Would you like to install the PostHog MCP server to use PostHog in your editor?',
response: [KEYS.DOWN, KEYS.ENTER],
response: [KEYS.DOWN, KEYS.SPACE],
responseWaitFor: 'No',
},
{
Expand Down
2 changes: 1 addition & 1 deletion src/ui/tui/playground/demos/HealthCheckDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const HealthCheckDemo = () => {
footer={
<Box marginLeft={2}>
<Text dimColor>
Continue [Enter] / Exit [Esc] (disabled in playground)
Continue [Space] / Exit [Esc] (disabled in playground)
</Text>
</Box>
}
Expand Down
2 changes: 1 addition & 1 deletion src/ui/tui/playground/demos/ModalDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const ModalDemo = () => {
footer={
<Box marginLeft={2}>
<Text dimColor>
Continue [Enter] / Exit [Esc] (disabled in playground)
Continue [Space] / Exit [Esc] (disabled in playground)
</Text>
</Box>
}
Expand Down
6 changes: 3 additions & 3 deletions src/ui/tui/playground/demos/WelcomeDemo.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* WelcomeDemo — Splash screen. Press enter to push the tabbed view.
* WelcomeDemo — Splash screen. Press space to push the tabbed view.
*/

import { Box, Text, useInput } from 'ink';
Expand All @@ -11,8 +11,8 @@
}

export const WelcomeDemo = ({ store }: WelcomeDemoProps) => {
useInput((_input, key) => {

Check failure on line 14 in src/ui/tui/playground/demos/WelcomeDemo.tsx

View workflow job for this annotation

GitHub Actions / Lint

'key' is defined but never used. Allowed unused args must match /^_/u
if (key.return) {
if (_input === ' ') {
store.completeSetup();
}
});
Expand All @@ -34,7 +34,7 @@
</Text>
<Box height={1} />
<Text color={Colors.primary}>
Press enter to continue {Icons.triangleRight}
Press space to continue {Icons.triangleRight}
</Text>
</Box>
);
Expand Down
8 changes: 4 additions & 4 deletions src/ui/tui/primitives/ConfirmationInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* ConfirmationInput — Continue/cancel prompt.
* Enter confirms, escape cancels. Arrow keys toggle focus.
* Space confirms the focused action, Enter or arrow keys move focus. Escape cancels.
*/

import { Box, Text, useInput } from 'ink';
Expand All @@ -25,18 +25,18 @@ export const ConfirmationInput = ({
message,
onConfirm,
onCancel,
confirmLabel = 'Continue [Enter]',
confirmLabel = 'Continue [Space]',
cancelLabel = 'Cancel [Esc]',
}: ConfirmationInputProps) => {
const [focused, setFocused] = useState<FocusTarget>(FocusTarget.Continue);

useInput((_input, key) => {
if (key.leftArrow || key.rightArrow) {
if (key.leftArrow || key.rightArrow || key.return) {
setFocused((f) =>
f === FocusTarget.Continue ? FocusTarget.Cancel : FocusTarget.Continue,
);
}
if (key.return) {
if (_input === ' ') {
if (focused === FocusTarget.Continue) {
onConfirm();
} else {
Expand Down
8 changes: 4 additions & 4 deletions src/ui/tui/primitives/GroupedPickerMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Renders groups of options with bold category labels.
* Arrow keys navigate selectable items (headers are skipped),
* space toggles, "a" toggles all, enter submits.
* enter toggles, "a" toggles all, space submits.
*
* When content exceeds available terminal height, the list scrolls
* to keep the focused item visible with ↑/↓ indicators.
Expand Down Expand Up @@ -185,7 +185,7 @@ export const GroupedPickerMenu = ({
}
}

if (input === ' ') {
if (key.return) {
const targetRowIdx = selectableIndices[newFocused] ?? 0;
const row = rows[targetRowIdx];
if (row?.kind === 'option') {
Expand All @@ -208,7 +208,7 @@ export const GroupedPickerMenu = ({
return new Set(allValues);
});
}
if (key.return) {
if (input === ' ') {
onSelect([...selected]);
}
});
Expand All @@ -231,7 +231,7 @@ export const GroupedPickerMenu = ({
<PromptLabel message={message} />
<Text dimColor>
{' '}
(space to toggle, a to toggle all, enter to confirm)
(enter to toggle, a to toggle all, space to confirm)
</Text>
<Box flexDirection="column" marginTop={1} marginLeft={2}>
{needsScroll && (
Expand Down
10 changes: 5 additions & 5 deletions src/ui/tui/primitives/PickerMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* PickerMenu — Single and multi select.
* Single mode: custom renderer with small triangle indicator.
* Multi mode: checkbox glyphs with space to toggle.
* Multi mode: checkbox glyphs with Enter to toggle, Space to confirm.
*/

import { Box, Text, useInput } from 'ink';
Expand Down Expand Up @@ -99,7 +99,7 @@ const SinglePickerMenu = <T,>({
const nextCol = col < columns - 1 ? col + 1 : 0;
setFocused(Math.min(nextCol * rows + row, options.length - 1));
}
if (key.return) {
if (_input === ' ') {
const selected = options[focused];
if (selected) {
onSelect(selected.value);
Expand Down Expand Up @@ -195,7 +195,7 @@ const MultiPickerMenu = <T,>({
const nextCol = col < columns - 1 ? col + 1 : 0;
setFocused(Math.min(nextCol * rows + row, options.length - 1));
}
if (_input === ' ') {
if (key.return) {
setSelected((prev) => {
const next = new Set(prev);
if (next.has(focused)) {
Expand All @@ -206,7 +206,7 @@ const MultiPickerMenu = <T,>({
return next;
});
}
if (key.return) {
if (_input === ' ') {
if (selected.size === 0) {
// Nothing toggled, select hovered
const hovered = options[focused];
Expand All @@ -228,7 +228,7 @@ const MultiPickerMenu = <T,>({
return (
<Box flexDirection="column" alignItems={centered ? 'center' : undefined}>
<PromptLabel message={message} />
<Text dimColor> (space to multi-select, enter to confirm)</Text>
<Text dimColor> (enter to multi-select, space to confirm)</Text>
<Box
flexDirection="row"
gap={4}
Expand Down
2 changes: 1 addition & 1 deletion src/ui/tui/screens/PortConflictScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const PortConflictScreen = ({ store }: PortConflictScreenProps) => {
footer={
<ConfirmationInput
message="Kill process and continue?"
confirmLabel="Kill & continue [Enter]"
confirmLabel="Kill & continue [Space]"
cancelLabel="Exit [Esc]"
onConfirm={() => {
try {
Expand Down
2 changes: 1 addition & 1 deletion src/ui/tui/screens/SettingsOverrideScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const SettingsOverrideScreen = ({
footer={
<ConfirmationInput
message="Back up to .wizard-backup and continue?"
confirmLabel="Backup & continue [Enter]"
confirmLabel="Backup & continue [Space]"
cancelLabel="Exit [Esc]"
onConfirm={() => {
const ok = store.backupAndFixSettingsOverride();
Expand Down
2 changes: 1 addition & 1 deletion src/ui/tui/screens/SkillsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export const SkillsScreen = ({ store }: SkillsScreenProps) => {
<Box marginTop={1}>
<ConfirmationInput
message="Keep the installed skills?"
confirmLabel="Keep [Enter]"
confirmLabel="Keep [Space]"
cancelLabel="Remove [Esc]"
onConfirm={handleKeep}
onCancel={() => void handleRemove()}
Expand Down
2 changes: 1 addition & 1 deletion src/ui/tui/screens/health/HealthCheckScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export const HealthCheckScreen = ({ store }: HealthCheckScreenProps) => {
) : (
<ConfirmationInput
message="Continue anyway?"
confirmLabel="Continue [Enter]"
confirmLabel="Continue [Space]"
cancelLabel={cancelLabel}
onConfirm={() => store.dismissOutage()}
onCancel={handleCancel}
Expand Down
Loading