@momoi-labs/kiso 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,6 +12,8 @@ behavioral reference where one exists.
12
12
  - [Card](card.md): Groups related content and actions with visual separation.
13
13
  - [Checkbox](checkbox.md): Toggles an option in a list or selects multiple values.
14
14
  - [ChipInput](chip-input.md): Collects several structured values in one field, each with its own options.
15
+ - [Form](form.md): Composes fields and explicit submission actions in a native form.
16
+ - [FormActions](form-actions.md): Groups form actions and optional feedback, with inline or sticky placement.
15
17
  - [FormField](form-field.md): Composes Label, a form control, HelperText, and ValidationMessage with consistent ID and ARIA wiring.
16
18
  - [HelperText](helper-text.md): Provides persistent, non-error context for a form control.
17
19
  - [IconButton](icon-button.md): Triggers a compact icon-only action with a required accessible name.
@@ -24,6 +26,7 @@ behavioral reference where one exists.
24
26
  - [Switch](switch.md): Changes one immediately applied boolean setting.
25
27
  - [Textarea](textarea.md): Collects multi-line free-form text.
26
28
  - [ThemeSelector](theme-selector.md): Chooses between following the system colour scheme, forcing light, or forcing dark.
29
+ - [AccentSelector](accent-selector.md): Chooses which accent the interface uses: violet, terracotta, teal, cobalt, or nocturne.
27
30
  - [Tooltip](tooltip.md): Adds nonessential pointer or keyboard context as progressive enhancement.
28
31
  - [ValidationMessage](validation-message.md): Explains a field-level validation error and how to fix it.
29
32
 
@@ -43,6 +46,8 @@ behavioral reference where one exists.
43
46
  - [Search](search.md): Filters visible content such as a list or table.
44
47
  - [Sparkline](sparkline.md): Draws the shape of one metric series at cell size.
45
48
  - [Stat](stat.md): Presents a named metric with optional change and context.
49
+ - [StepBar](step-bar.md): Summarises a run as one segment per step, coloured by state.
50
+ - [StepList](step-list.md): Lists a run's steps with a state, a label, a timing, and an output.
46
51
  - [Table / DataTable](table.md): Presents structured records with optional sorting, selection, filtering, and pagination.
47
52
 
48
53
  ## Navigation and structure
@@ -72,6 +77,8 @@ behavioral reference where one exists.
72
77
 
73
78
  ## Required compositions
74
79
 
80
+ - [Form](form.md) with explicit submission includes fields and [FormActions](form-actions.md).
81
+
75
82
  - [FormField](form-field.md) composes [Label](label.md) + [Input](input.md) (or another form control) + [HelperText](helper-text.md) + [ValidationMessage](validation-message.md).
76
83
  - [ApplicationShell](app-shell.md) composes [Sidebar](sidebar.md) + [Navigation](navigation.md) + [Header](header.md) + page content, or a top-bar-only frame with brand in [Header](header.md).
77
84
  - [Header](header.md) composes [Link](link.md) + [IconButton](icon-button.md) + optional [DropdownMenu](dropdown-menu.md).
@@ -0,0 +1,136 @@
1
+ # AccentSelector
2
+
3
+ ## Purpose
4
+
5
+ AccentSelector chooses which accent the interface uses: violet, terracotta,
6
+ teal, cobalt, or nocturne. It is the only sanctioned control for that choice. The theme
7
+ (light, dark, system) is a separate axis with its own control,
8
+ [ThemeSelector](theme-selector.md); the two compose.
9
+
10
+ ## The five values
11
+
12
+ | Value | Meaning | `data-accent` on `<html>` |
13
+ | --- | --- | --- |
14
+ | `violet` (default) | The violet ink and fill on the warm neutrals. | Either no attribute or `data-accent="violet"`. |
15
+ | `terracotta` | Same roles, hue turned to terracotta. Neutrals unchanged. | `data-accent="terracotta"` |
16
+ | `teal` | Same roles, hue turned to teal. Neutrals unchanged. | `data-accent="teal"` |
17
+ | `cobalt` | Same roles, hue turned to cobalt. Neutrals unchanged. | `data-accent="cobalt"` |
18
+ | `nocturne` | The marketing site's palette: cool slate neutrals under the violet ink. | `data-accent="nocturne"` |
19
+
20
+ The attribute may also sit on a container, in which case only that subtree
21
+ takes the accent. A nested `data-accent="violet"` resets to the default. See
22
+ [Accents](../tokens.md#accents) for what the accent does and does not change.
23
+
24
+ An application that offers fewer accents passes the subset it supports; the
25
+ control does not have to show all five.
26
+
27
+ ## Persistence
28
+
29
+ - An explicit choice persists under the key `kiso-accent`, with the value
30
+ `violet`, `terracotta`, `teal`, `cobalt`, or `nocturne`.
31
+ - Read the stored value in a blocking inline script in `<head>`, before first
32
+ paint, and apply it as `data-accent`. Anything later flashes.
33
+ - Storage may be unavailable. Wrap reads and writes so a failure degrades to
34
+ `violet` rather than throwing.
35
+ - An application with a fixed accent does not render the control at all; it
36
+ sets the attribute once, in the document.
37
+
38
+ ## Anatomy
39
+
40
+ 1. **Row label**: the word "Accent", on the left.
41
+ 2. **Pills**: one per value, on the right, as a group. Each pill is a dot in
42
+ that accent's `primary` fill followed by the accent's name.
43
+ 3. **Preview**: below the row, one panel that shows the *selected* accent
44
+ applied: a sidebar strip with a current-item marker, a heading, a link, a
45
+ primary and a secondary button, and a selected row.
46
+
47
+ | Value | Pill | Accessible name |
48
+ | --- | --- | --- |
49
+ | `violet` | violet dot, "Violet" | "Violet" |
50
+ | `terracotta` | terracotta dot, "Terracotta" | "Terracotta" |
51
+ | `teal` | teal dot, "Teal" | "Teal" |
52
+ | `cobalt` | cobalt dot, "Cobalt" | "Cobalt" |
53
+ | `nocturne` | nocturne dot, "Nocturne" | "Nocturne" |
54
+
55
+ The pill names the accent, so no hover is needed to tell which is which. The
56
+ preview answers the choice: it is decorative and hidden from assistive
57
+ technology, because the names already carry the meaning. Each pill and the
58
+ preview carry their own `data-accent`, so their colours resolve under that
59
+ accent with no inline values.
60
+
61
+ The preview may be omitted where the row is inline chrome, such as a header
62
+ toolbar. In a settings card it is always present.
63
+
64
+ ## Layout
65
+
66
+ A configuration row directly below the Theme row in the same card, with the
67
+ preview spanning the row's width beneath it. See
68
+ [Settings](../patterns/settings.md#theme).
69
+
70
+ ```text
71
+ Theme [ ▣ ][ ☀ ][ ☾ ]
72
+ Accent (● Violet)(● Terracotta)(● Teal)(● Cobalt)(● Nocturne)
73
+ ┌──┬──────────────────────────────────┐
74
+ │ │ ▬▬▬▬▬▬ │
75
+ │▬ │ ▬▬▬ │
76
+ │ │ [primary] [secondary] │
77
+ │ │ ░░░░░░░░░░░░░░░░ selected │
78
+ └──┴──────────────────────────────────┘
79
+ ```
80
+
81
+ Narrower than 360px (a sidebar footer), the label stacks over the pills and
82
+ the pills form a two-column grid, so no name wraps mid-word.
83
+
84
+ ## Tokens
85
+
86
+ Pill: height `--size-control-xs`, radius `--radius-full`, border
87
+ `--color-border`, fill `--color-card`, text `--color-muted-foreground` at
88
+ `--type-size-label`, dot `--spacing-md` square in `--color-primary`.
89
+
90
+ Selected pill: border `--color-primary`, fill `--color-accent-surface`, text
91
+ `--color-foreground` at `--type-weight-medium`. The pill is outlined and
92
+ tinted, not filled with `--color-primary`: the fill is already on the dot,
93
+ and a solid pill would compete with the page's actual primary action.
94
+
95
+ Preview: 120px tall, border `--color-border`, radius `--radius-lg`, canvas
96
+ `--color-background`, strip `--color-sidebar`, marker and link `--color-link`,
97
+ buttons `--color-primary` and `--color-card` with `--color-border-strong`,
98
+ row `--color-selected`. Transitions on `--motion-duration-fast` /
99
+ `--motion-easing-standard`.
100
+
101
+ ## States
102
+
103
+ | State | Behavior |
104
+ | --- | --- |
105
+ | default | The offered options, exactly one selected; the preview shows it. |
106
+ | hover | Unselected pill takes `--color-accent-surface` and `--color-foreground`. |
107
+ | focus | Visible ring using `--color-ring`. Never remove it. |
108
+ | selected | Outlined and tinted pill as above, plus the accessible selected state. The preview repaints at once. |
109
+ | disabled | Not a state. The accent is always changeable where the control is shown. |
110
+
111
+ There is no loading state. The change is local and instant; do not wait on a
112
+ server round-trip to repaint, and do not show a Toast for it.
113
+
114
+ ## Accessibility
115
+
116
+ - A group of mutually exclusive options with exactly one selected, each named
117
+ by its visible text.
118
+ - The preview is `aria-hidden`; it repeats what the pill already says.
119
+ - Announce the selection, not the resulting colours.
120
+ - Every accent passes the same [AA gate](../tokens.md#aa-gate) as the default,
121
+ so the control does not need to warn about contrast.
122
+
123
+ ## When NOT to use
124
+
125
+ - A free colour picker. Kiso has five accents; a product colour that is not
126
+ one of them is a token proposal, not an option.
127
+ - A way to mark status or severity. Red, amber, and green are not accents for
128
+ that reason: a primary button in the danger hue reads as destructive.
129
+ - Per-user branding inside a single product. One accent per product, or per
130
+ product area, chosen by the product.
131
+
132
+ ## Related
133
+
134
+ - [tokens](../tokens.md#accents): what an accent changes and how it is built.
135
+ - [ThemeSelector](theme-selector.md): the other appearance row.
136
+ - [Settings](../patterns/settings.md#theme): where the row lives.
@@ -188,3 +188,9 @@ No Radix Card primitive. Structure follows shadcn
188
188
 
189
189
  Ignore shadcn's invitation to hard-code spacing utilities. Card spacing
190
190
  consumes `--spacing-md`, `--spacing-lg`, or `--spacing-xl` only.
191
+
192
+ ## Form submission
193
+
194
+ Use [FormActions](form-actions.md) for form submission controls and feedback.
195
+ It can replace CardFooter at the bottom of a form inside a Card. Do not nest
196
+ the two footers. CardFooter remains a general content-and-actions container.
@@ -0,0 +1,145 @@
1
+ # FormActions
2
+
3
+ ## Purpose
4
+
5
+ FormActions gives an explicit-submit form one place for its primary action,
6
+ secondary actions, and optional feedback. It works for sign-in, creation,
7
+ editing, and applying choices. It does not assume that submission saves a record.
8
+
9
+ ## Anatomy
10
+
11
+ 1. An action region after the form content.
12
+ 2. An optional visible message in a persistent status region.
13
+ 3. An action group with one primary Button and any secondary actions.
14
+
15
+ The message comes before the buttons in DOM order. Buttons align to the end
16
+ of the region. The layout wraps when the available width cannot hold both
17
+ message and actions. Labels and messages can wrap without horizontal scrolling.
18
+
19
+ ## React API
20
+
21
+ | Prop | Default | Meaning |
22
+ | --- | --- | --- |
23
+ | `children` | None | Consumer-provided Buttons or navigation Links. |
24
+ | `message` | None | React content rendered inside the status region. |
25
+ | `tone` | `neutral` | `neutral`, `warning`, or `danger` presentation. |
26
+ | `sticky` | `false` | Stick to the bottom of the nearest scrolling ancestor, within the form. |
27
+ | Native div props | None | Includes `className`, `style`, `ref`, and ARIA attributes. |
28
+
29
+ ```tsx
30
+ <FormActions
31
+ sticky
32
+ tone={error ? "danger" : dirty ? "warning" : "neutral"}
33
+ message={error || (dirty ? "Unsaved changes." : undefined)}
34
+ >
35
+ {dirty && <Button type="button" onClick={discard}>Discard changes</Button>}
36
+ <Button type="submit" variant="primary" disabled={saving || !dirty}>
37
+ {saving ? "Saving..." : "Save changes"}
38
+ </Button>
39
+ </FormActions>
40
+ ```
41
+
42
+ Loading indicators and `aria-busy` belong on the submitting Button. The
43
+ consumer prevents duplicate submission and decides whether cancellation is safe.
44
+ No buttons, labels, dirty tracking, or network behavior are built in.
45
+
46
+ ## Tones and messages
47
+
48
+ | Situation | Presentation |
49
+ | --- | --- |
50
+ | Initial or create | Neutral; no message required. |
51
+ | Unsaved edits | Warning with a message identifying the unsaved changes. |
52
+ | Submitting | A short progress message and loading submit Button. |
53
+ | Submission failed | Danger with a recovery message; preserve entries. |
54
+ | Saved | Neutral confirmation when the form stays open; clear dirty state. |
55
+
56
+ Tone does not encode business state. A product decides what "saved, awaiting
57
+ application" means and supplies suitable copy. FormActions does not model
58
+ machines, deployments, or synchronization. Use text to communicate meaning;
59
+ color alone is insufficient. An icon and bold lead are optional.
60
+
61
+ A new record can show Cancel and Create without a message. Discard appears
62
+ only when there are edits to discard. Avoid an always-visible "Saved" caption
63
+ that remains unchanged after editing.
64
+
65
+ ## Placement and scrolling
66
+
67
+ For page scrolling, put FormActions last inside Form and pass `sticky`.
68
+ Its bottom offset defaults to zero. When the page has outer padding, set
69
+ `inset-block-end` to the same spacing token so the floating actions respect
70
+ that inset. Cover the space below the floating bar with the page background,
71
+ including the container border, so scrolling fields do not show through the
72
+ outer padding. An offset alone does not create that visual separation.
73
+ When page scrolling moves a marked Card behind sticky actions, keep the top
74
+ marks on the Card and move both bottom corner marks to the sticky action edge.
75
+ Draw them above the inset cover so each corner retains its horizontal and
76
+ vertical tick. Do not leave
77
+ a second pair attached to the scrolling Card bottom.
78
+ For example, use `var(--spacing-xl)` for a page padded by
79
+ `--spacing-xl`, and match any responsive padding changes. The form must remain
80
+ in document flow: an ancestor with scrolling overflow changes the sticky
81
+ container.
82
+
83
+ For a bounded panel, put Form inside a height-constrained `form-scroll` region.
84
+ That region owns overflow and has no padding. Put padding on `form-body`
85
+ instead. Actions then span the container width without negative margins.
86
+ Form fills at least the panel height and pushes actions to its bottom.
87
+
88
+ ```tsx
89
+ <TabsContent value="general" className="form-scroll" style={{ height: "28rem" }}>
90
+ <Form onSubmit={save}>
91
+ <div className="form-body">{/* FormFields */}</div>
92
+ <FormActions sticky>{/* Buttons */}</FormActions>
93
+ </Form>
94
+ </TabsContent>
95
+ ```
96
+
97
+ Keep an outer Card's corner marks outside the scrolling region. Do not nest
98
+ FormActions inside CardFooter or DialogFooter; it provides its own border and
99
+ padding. CardFooter stays a general visual container without form status.
100
+
101
+ If an existing scroller must retain padding, the consumer must account for it:
102
+ set `style={{ insetBlockEnd: "calc(-1 * var(--spacing-lg))" }}` when the
103
+ scroller's bottom padding is `--spacing-lg`. Align the form with the horizontal
104
+ edges separately. Use lengths such as `0px` when supplying values to CSS math.
105
+ Prefer the unpadded composition above for new screens.
106
+
107
+ The background layers semantic tint over an opaque card surface. Scrolled
108
+ content must not show through the message or buttons. The bar stops at the
109
+ form's end; it is not fixed to the viewport across unrelated content.
110
+
111
+ ## Accessibility
112
+
113
+ Only the message region has `role="status"` and `aria-atomic="true"`. Keep it
114
+ mounted when empty so updates can be announced. Do not put these attributes
115
+ on the entire action region, and do not put interactive controls in `message`.
116
+
117
+ Buttons retain their native semantics and tab order. The primary Button has
118
+ `type="submit"`; secondary Buttons have `type="button"`. Use a Link for an
119
+ actual navigation destination. Avoid duplicate announcements from an inline
120
+ message and a Toast for the same event.
121
+
122
+ Field validation stays beside its field. Keep form-level failures visible
123
+ until the person edits or retries. Verify sticky actions at narrow widths,
124
+ zoom, and keyboard focus. Shared scroll spacing reserves room for typical
125
+ wrapped actions; consumers must increase that space for unusually tall bars.
126
+
127
+ ## Tokens
128
+
129
+ Spacing uses `--spacing-sm`, `--spacing-md`, and `--spacing-lg`. Scroll spacing
130
+ uses `--spacing-4xl`. Text uses `--type-size-label` and
131
+ `--type-weight-semibold`. The base uses `--color-card`,
132
+ `--color-card-foreground`, and `--color-border`. Warning uses
133
+ `--color-warning-surface` and `--color-warning-border`; danger uses
134
+ `--color-danger-surface` and `--color-danger-border`.
135
+
136
+ ## When not to use
137
+
138
+ Do not add submission actions to immediate preferences or automatic filters.
139
+ Do not use this component for page-wide record actions unrelated to the form,
140
+ a generic Card footer, or a toolbar for selecting table rows.
141
+
142
+ ## Radix/shadcn mapping
143
+
144
+ FormActions is a Kiso composition of native grouping, a status region, and
145
+ Buttons. It does not add a keyboard interaction model or a Radix dependency.
@@ -7,6 +7,9 @@ identification, entry, guidance, and field-level feedback so their visual and
7
7
  accessible relationships remain intact. FormField is not a primitive and does
8
8
  not replace the semantics of its children.
9
9
 
10
+ Use [Form](form.md) and [FormActions](form-actions.md) for the whole form and
11
+ its submission actions. FormField remains responsible for one control.
12
+
10
13
  ## Anatomy
11
14
 
12
15
  The canonical composition is:
@@ -0,0 +1,102 @@
1
+ # Form
2
+
3
+ ## Purpose
4
+
5
+ Form composes fields and their submission actions in a native HTML form.
6
+ Every form with explicit submission includes [FormActions](form-actions.md).
7
+ The action can sign in, create, save, search, or apply a choice.
8
+
9
+ Immediate preferences and automatic filters do not need a submit action.
10
+ Use the existing Switch and search patterns for those interactions.
11
+
12
+ ## Anatomy
13
+
14
+ 1. A native `form`, optionally named by a heading with `aria-labelledby`.
15
+ 2. A content region containing FormFields, sections, or fieldsets.
16
+ 3. FormActions after the content, with one primary submit Button and any
17
+ secondary actions the task needs.
18
+
19
+ ```tsx
20
+ <Form onSubmit={handleSubmit} aria-labelledby="project-title">
21
+ <div className="form-body">
22
+ <h2 id="project-title">Create project</h2>
23
+ <FormField label="Project name" name="name" required />
24
+ </div>
25
+ <FormActions>
26
+ <Button type="submit" variant="primary">Create project</Button>
27
+ </FormActions>
28
+ </Form>
29
+ ```
30
+
31
+ The `form-body` CSS class provides content padding and field spacing. It can
32
+ be applied to a div or fieldset. Products can instead compose content from
33
+ Cards and existing layout utilities. Form adds no padding around its actions.
34
+ Do not wrap FormActions in a padded content region or another footer.
35
+
36
+ ## React API
37
+
38
+ Form accepts native form props, including `action`, `method`, `onSubmit`,
39
+ `id`, `ref`, and ARIA attributes. It forwards them to the form element and
40
+ merges `className` with `form`.
41
+
42
+ Form does not create buttons, enforce its children at runtime, intercept
43
+ submission, select a validation library, or track values and dirty state.
44
+ The application owns those behaviors. Explicit-submit forms must follow the
45
+ composition contract even though the React component accepts arbitrary content.
46
+
47
+ ## Layouts
48
+
49
+ - Short forms keep FormActions in normal flow.
50
+ - Long forms use sticky FormActions on a page or inside a scrolling panel.
51
+ - A form in a bounded panel fills at least the panel height, so actions also
52
+ reach the panel bottom when content is short.
53
+ - A form can contain multiple Cards. A Card is not required for Form.
54
+ - In Dialog, compose DialogHeader and a Form containing its fields and
55
+ FormActions. Use `form-scroll` on the form when the dialog constrains its
56
+ height. Keep the dialog's existing focus and dismissal behavior.
57
+
58
+ See [FormActions](form-actions.md) for scroll ownership, padded containers,
59
+ responsive actions, and status announcements.
60
+
61
+ ## States and ownership
62
+
63
+ | State | Application behavior |
64
+ | --- | --- |
65
+ | Initial | Provide fields and an explicit submit action; a status message is optional. |
66
+ | Dirty | Compare current values with the last saved values. Show feedback and Discard when useful. |
67
+ | Invalid | Preserve entries, show field errors, and focus the first invalid field. |
68
+ | Submitting | Show loading on the submit Button and prevent duplicate requests. |
69
+ | Failed | Keep entries and show a recoverable message. Use field errors for field failures. |
70
+ | Saved | Update the saved baseline and clear dirty state. Confirm inline or navigate as appropriate. |
71
+
72
+ Discard restores the saved baseline. Native reset restores initial defaults,
73
+ which may differ after a successful save. Cancel leaves the task; it does not
74
+ necessarily mean Discard. The application handles navigation and any warning
75
+ needed before losing material edits.
76
+
77
+ ## Accessibility
78
+
79
+ Preserve native submit and validation behavior. Use `type="submit"` on the
80
+ primary Button and `type="button"` on other buttons. Never nest forms.
81
+ Group related controls with fieldset and legend when they share a question.
82
+ FormField continues to own label, help, and field-error associations.
83
+
84
+ DOM order is content followed by actions. Sticky placement must not obscure
85
+ focused controls or their errors; verify keyboard use and zoom in the actual
86
+ scroll container. Do not announce the whole form as a live region.
87
+
88
+ ## Tokens
89
+
90
+ `form-body` uses `--spacing-lg` padding and `--spacing-xl` gaps. Form delegates
91
+ surfaces and borders to its container, and action styling to FormActions.
92
+
93
+ ## Related contracts
94
+
95
+ - [FormField](form-field.md) for one labeled control.
96
+ - [FormActions](form-actions.md) for submission controls and feedback.
97
+ - [CRUD](../patterns/crud.md) and [Settings](../patterns/settings.md) for flows.
98
+
99
+ ## Radix/shadcn mapping
100
+
101
+ Form uses native HTML semantics. It introduces no Radix primitive or form-state
102
+ library dependency.
@@ -0,0 +1,57 @@
1
+ # StepBar
2
+
3
+ ## Purpose
4
+
5
+ StepBar summarises a run in one row: one segment per step, coloured by the
6
+ step's state. It answers "how far" and "where it stopped" at a glance, in the
7
+ places a [StepList](step-list.md) does not fit: a summary tab, a table cell,
8
+ a Toast. [Progress](meter.md) shows a continuous ratio; StepBar shows discrete
9
+ steps, so a failure is visible as a red segment in its place.
10
+
11
+ ## Anatomy
12
+
13
+ ```
14
+ StepBar (role="img", named)
15
+ └── segment (repeated, one per step)
16
+ ```
17
+
18
+ The bar is the whole component. The product places the count ("4 of 11"),
19
+ the current step's label, or the last output line beside it in its own
20
+ markup; StepBar does not render text.
21
+
22
+ ## States
23
+
24
+ Segments take the same five states as StepList: pending in
25
+ `--color-secondary`, running and done in `--color-success`, skipped hatched in
26
+ `--color-success`, failed in `--color-danger`. A running segment may show a
27
+ partial fill from `progress` (0 to 1); without it, running fills fully.
28
+
29
+ ## Sizes
30
+
31
+ One height, `--spacing-xs`. Width comes from the container. In a table cell,
32
+ give the cell a fixed width and keep the bar to one line beside the Badge;
33
+ do not add the ticker there. Hide the bar when the machine is not running and
34
+ has not failed; the Badge alone says "Stopped".
35
+
36
+ ## Accessibility
37
+
38
+ `role="img"` with a name that says the count and the current step, such as
39
+ "Create: step 4 of 11, running System packages" or
40
+ "Create: failed at step 4 of 11, System packages". The segments are
41
+ decorative. Nothing depends on colour alone.
42
+
43
+ ## Tokens and implementation
44
+
45
+ Segments use `--radius-xs` and a `--spacing-2xs` gap. The hatch for a skipped
46
+ segment reuses the existing hatch tokens. No Radix primitive.
47
+
48
+ ## When to use
49
+
50
+ - A machine's summary tab or card while an action runs or after it fails.
51
+ - A machines table, one line per row, next to the status Badge.
52
+ - A progress Toast for a run started from another screen.
53
+
54
+ ## When NOT to use
55
+
56
+ - The run's own page. Use StepList there; the bar would repeat it.
57
+ - A continuous measurement. Use Meter or Progress.
@@ -0,0 +1,86 @@
1
+ # StepList
2
+
3
+ ## Purpose
4
+
5
+ StepList shows the steps of a run a machine walks through, one row per step,
6
+ with a state, a label, and a timing. While the run goes it is the progress;
7
+ afterwards it is the account of what happened. The reader does not walk the
8
+ steps; the machine does, and the reader reads how it went.
9
+
10
+ It is not the [Pagination](pagination.md) step indicator. That one shows a
11
+ person's position in a flow they drive. StepList has a state per step, a
12
+ timing, and an output the reader may open.
13
+
14
+ ## Anatomy
15
+
16
+ ```
17
+ StepList (ordered list, labelled)
18
+ └── Step (repeated)
19
+ ├── rail: connector and mark, with a text alternative
20
+ ├── label
21
+ ├── meta (mono, muted)
22
+ └── detail (optional slot, below the row)
23
+ ```
24
+
25
+ The rail is one vertical line through every mark. Each mark is a dot; the
26
+ connector above it takes the colour of the step's state, so the line fills as
27
+ the run advances and the list is itself the progress. Nothing else measures
28
+ completion: do not add a Progress track above a StepList.
29
+
30
+ Each row is a button when the list has `onSelect`; the product then shows the
31
+ selected step's output beside the list, usually in the second [Pane](split.md)
32
+ of a Split with a [LogView](log-view.md) filling it. On a narrow viewport,
33
+ where the Split cannot fit, pass the output as the selected step's `detail`
34
+ and it renders under the row.
35
+
36
+ ## States
37
+
38
+ | State | Mark | Default meta |
39
+ | --- | --- | --- |
40
+ | pending | empty dot, muted row | none; the product passes "Not run" after a failure |
41
+ | running | dot ringed in `--color-success`, pulsing, bold label | "Running" |
42
+ | done | filled `--color-success` dot | none; the product passes the duration |
43
+ | skipped | hollow `--color-success` dot, muted label | "Not needed" |
44
+ | failed | filled `--color-danger` dot, bold label in `--color-danger` | none; the product passes the duration |
45
+
46
+ The running step is `aria-current="step"`. Five states, not a status badge's
47
+ tones: running is alive, so it is the success colour; neutral is what is not
48
+ happening; danger is what stopped the run.
49
+
50
+ The product owns which step is selected. Follow the running step by default,
51
+ keep a step the reader chose, and offer a way back to the current one.
52
+
53
+ ## Accessibility
54
+
55
+ An `ol` with an accessible name, one `li` per step. Each mark carries its
56
+ state as text (`role="img"` with the state as its name), so colour is never
57
+ the only signal. Rows that select are native buttons with `aria-pressed`;
58
+ rows that do not are plain text. The connector is decorative and hidden.
59
+ Under reduced motion the running mark does not pulse.
60
+
61
+ ### Keyboard
62
+
63
+ No custom keymap. Tab reaches each selectable row; Enter or Space selects it.
64
+
65
+ ## Tokens and implementation
66
+
67
+ Rail and marks use `--color-border-strong`, `--color-success`,
68
+ `--color-success-surface`, and `--color-danger`. Labels use
69
+ `--type-size-label`; the running and failed labels use
70
+ `--type-weight-semibold`. Meta uses `--font-mono`, `--type-size-label`, and
71
+ `--color-muted-foreground`. Rows are spaced with `--spacing-sm`; the rail
72
+ column is `--spacing-xl` wide, room for the running mark's glow. Focus uses `--color-focus`. No Radix
73
+ primitive is involved.
74
+
75
+ ## When to use
76
+
77
+ - A lifecycle action on a machine: create, update, or a bootstrap with a
78
+ known list of stages.
79
+ - An image build or a collection whose phases are known before it starts.
80
+
81
+ ## When NOT to use
82
+
83
+ - A flow the person walks through. Use Pagination's step indicator.
84
+ - A plan that is not known before it runs. Append rows as they happen, and
85
+ pair the list with an indeterminate Progress rather than a [StepBar](step-bar.md).
86
+ - A single indeterminate wait. Use Spinner.
@@ -104,11 +104,13 @@ server round-trip to repaint, and do not show a Toast for it.
104
104
  which is the default and the most common choice.
105
105
  - A theme entry buried inside a DropdownMenu as the only access point. A menu
106
106
  may mirror the control, but the setting lives in a settings row.
107
- - Any control that offers colour options beyond these three. Kiso has two
108
- themes.
107
+ - Any control that offers colour scheme options beyond these three. Kiso has
108
+ two themes. The accent is a separate axis with its own control,
109
+ [AccentSelector](accent-selector.md).
109
110
 
110
111
  ## Related
111
112
 
112
113
  - [tokens](../tokens.md) — how `light-dark()` and `color-scheme` resolve.
113
114
  - [Settings](../patterns/settings.md#theme) — where the row lives.
115
+ - [AccentSelector](accent-selector.md) — the other appearance row.
114
116
  - [Switch](switch.md) — for actual booleans.
@@ -40,3 +40,9 @@ both full timestamps; visible dates appear when the interval crosses a day. Touc
40
40
  Use existing Button, Input, and Popover tokens. Use `--spacing-xs` between
41
41
  presets and `--spacing-md` between regions. The trigger wraps long ranges;
42
42
  the popover fits the viewport. No new calendar, timezone, or date dependency.
43
+
44
+ ## Custom range form
45
+
46
+ The custom range editor composes [Form](form.md) with
47
+ [FormActions](form-actions.md). Apply range is the explicit submit action;
48
+ validation stays next to the range fields. Presets still apply immediately.
@@ -13,7 +13,7 @@ the system needs them. This is the honest roadmap for those choices.
13
13
  | **Figma Tokens Studio integration** | [Epic #2](https://github.com/momoi-labs/blueprint/issues/2) kept the token pipeline focused on its committed outputs. Tokens Studio is a Figma plugin workflow built through Style Dictionary and `@tokens-studio/sd-transforms`, not a standalone emitter. | When design-to-code synchronization through Figma becomes a real team workflow rather than a hypothetical integration. |
14
14
  | **DTCG 2025.10 Resolver module** | The multiple-context and theme Resolver considered in [epic #2](https://github.com/momoi-labs/blueprint/issues/2) is a preview draft marked “do not implement.” V1 uses an explicit, stable theme model instead. | When the Resolver module reaches stable status and Kiso has a concrete context or theme problem it would solve. |
15
15
  | **`--shadow-lg`** | The elevation scale intentionally stops at `--shadow-sm` and `--shadow-md`; [#25](https://github.com/momoi-labs/blueprint/issues/25) fixed component references without inventing a larger elevation. | When a real overlay or hierarchy cannot be expressed clearly with `--shadow-md`. Propose the token in the source, then regenerate its outputs. |
16
- | **A dedicated multi-step-flow pattern** | [#26](https://github.com/momoi-labs/blueprint/issues/26) added step indication as a Pagination variant, which satisfies the current bounded-flow need without another pattern. | When recurring multi-step flows need behavior, composition, or guidance beyond Pagination's scope. |
16
+ | **A dedicated multi-step-flow pattern** | [#26](https://github.com/momoi-labs/blueprint/issues/26) added step indication as a Pagination variant, which satisfies the current bounded-flow need without another pattern. [#98](https://github.com/momoi-labs/blueprint/issues/98) added StepList for the other case, a run a machine walks and a person reads; person-driven flows still use Pagination. | When recurring person-driven flows need behavior, composition, or guidance beyond Pagination's scope. |
17
17
  | **Additional patterns** | The pattern set from [epic #4](https://github.com/momoi-labs/blueprint/issues/4) is an intentionally lean cut of roughly 21 recurring product structures. Speculative completeness would encode guesses. | When a real product exposes a repeated structure that the current patterns cannot express without an ad-hoc solution. |
18
18
  | **Additional components** | The roughly 28-component cut from [epic #3](https://github.com/momoi-labs/blueprint/issues/3) covers the intended v1 product surface. Adding primitives in anticipation would enlarge the interface before their contracts are understood. | When a need recurs across products. Propose a component and its contract; do not invent one locally or copy one in unchanged. |
19
19
  | **Heavy governance** | A two-person lab does not need a contribution bureaucracy or design-review board. For v1, the propose-don't-copy rule in [`kiso/AGENTS.md`](../AGENTS.md) is the governance mechanism, as scoped by [epic #5](https://github.com/momoi-labs/blueprint/issues/5). | When more contributors, products, or incompatible proposals make ownership and decision-making unclear. Add only the process needed to resolve an observed coordination problem. |
@@ -31,6 +31,7 @@ The growth model below is not theory. What it has produced so far:
31
31
  | What | Evidence | Where |
32
32
  | --- | --- | --- |
33
33
  | **[ChipInput](components/chip-input.md)** | A self-hosted console had to collect a development image's dependencies: a list a person types, where every entry carries a backend, a version, and installer options. One form section per entry grew without limit and buried the list. | Added as a component contract with the segmented chip, the in-place value, and one segment per option. |
34
+ | **[StepList](components/step-list.md) and [StepBar](components/step-bar.md)** | The self-host console's Last run tab walks a machine through eleven lifecycle steps over several minutes and wrote its own list of steps with a state each, replacing a progress bar and a two-thousand-line log to search. An image build and the Host's own bootstrap were about to copy it. [#98](https://github.com/momoi-labs/blueprint/issues/98) records the evidence. | Added as two contracts: the list inside a Split with the step's LogView beside it, and the bar for a summary, a table cell, or a toast. |
34
35
  | **[Sparkline](components/sparkline.md)** | The self-host console collects metrics in-process, one sample per tick on an evenly spaced window, and needed the same shape three times over: a trend cell per application row, context under a KPI value, and one series per container. [#84](https://github.com/momoi-labs/blueprint/issues/84) records the evidence. | Added as a component contract and a Recharts-based component, single series, neutral by default, primary only for the series a tile is about. |
35
36
 
36
37
  ## Growth model: grow with real products