@momoi-labs/kiso 0.1.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.
- package/LICENSE +21 -0
- package/README.md +63 -0
- package/kiso/AGENTS.md +50 -0
- package/kiso/README.md +62 -0
- package/kiso/docs/accessibility.md +87 -0
- package/kiso/docs/brand.md +95 -0
- package/kiso/docs/components/README.md +58 -0
- package/kiso/docs/components/alert.md +158 -0
- package/kiso/docs/components/badge.md +135 -0
- package/kiso/docs/components/breadcrumb.md +66 -0
- package/kiso/docs/components/button.md +168 -0
- package/kiso/docs/components/card.md +154 -0
- package/kiso/docs/components/checkbox.md +91 -0
- package/kiso/docs/components/command-palette.md +165 -0
- package/kiso/docs/components/drawer.md +79 -0
- package/kiso/docs/components/dropdown-menu.md +178 -0
- package/kiso/docs/components/empty-state.md +142 -0
- package/kiso/docs/components/form-field.md +115 -0
- package/kiso/docs/components/header.md +79 -0
- package/kiso/docs/components/helper-text.md +86 -0
- package/kiso/docs/components/icon-button.md +161 -0
- package/kiso/docs/components/input.md +99 -0
- package/kiso/docs/components/label.md +88 -0
- package/kiso/docs/components/link.md +152 -0
- package/kiso/docs/components/modal-dialog.md +82 -0
- package/kiso/docs/components/navigation.md +68 -0
- package/kiso/docs/components/page-header.md +70 -0
- package/kiso/docs/components/pagination.md +129 -0
- package/kiso/docs/components/popover.md +74 -0
- package/kiso/docs/components/search.md +147 -0
- package/kiso/docs/components/select.md +105 -0
- package/kiso/docs/components/sidebar.md +74 -0
- package/kiso/docs/components/skeleton.md +140 -0
- package/kiso/docs/components/spinner.md +125 -0
- package/kiso/docs/components/switch.md +92 -0
- package/kiso/docs/components/table.md +255 -0
- package/kiso/docs/components/tabs.md +69 -0
- package/kiso/docs/components/textarea.md +91 -0
- package/kiso/docs/components/toast.md +80 -0
- package/kiso/docs/components/tooltip.md +162 -0
- package/kiso/docs/components/validation-message.md +96 -0
- package/kiso/docs/data-interfaces.md +309 -0
- package/kiso/docs/evolution.md +35 -0
- package/kiso/docs/patterns/README.md +40 -0
- package/kiso/docs/patterns/application-shell.md +106 -0
- package/kiso/docs/patterns/command-palette.md +142 -0
- package/kiso/docs/patterns/confirmations.md +158 -0
- package/kiso/docs/patterns/crud.md +139 -0
- package/kiso/docs/patterns/dashboard.md +102 -0
- package/kiso/docs/patterns/destructive-actions.md +137 -0
- package/kiso/docs/patterns/developer-oriented-interfaces.md +162 -0
- package/kiso/docs/patterns/empty-states.md +76 -0
- package/kiso/docs/patterns/errors.md +93 -0
- package/kiso/docs/patterns/filtering.md +147 -0
- package/kiso/docs/patterns/keyboard-shortcuts.md +155 -0
- package/kiso/docs/patterns/large-data-tables.md +182 -0
- package/kiso/docs/patterns/list-detail.md +118 -0
- package/kiso/docs/patterns/loading.md +80 -0
- package/kiso/docs/patterns/login-authentication.md +101 -0
- package/kiso/docs/patterns/onboarding.md +94 -0
- package/kiso/docs/patterns/pagination.md +121 -0
- package/kiso/docs/patterns/permission-denied.md +84 -0
- package/kiso/docs/patterns/search.md +150 -0
- package/kiso/docs/patterns/settings.md +100 -0
- package/kiso/docs/patterns/sorting.md +121 -0
- package/kiso/docs/principles.md +122 -0
- package/kiso/docs/tokens.md +95 -0
- package/kiso/docs/voice-and-tone.md +154 -0
- package/package.json +42 -0
- package/tokens/build/tokens.css +143 -0
- package/tokens/build/tokens.d.ts +160 -0
- package/tokens/build/tokens.json +88 -0
- package/tokens/build/tokens.scss +89 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Command palette
|
|
2
|
+
|
|
3
|
+
Keyboard-driven global navigation and actions. This pattern composes the
|
|
4
|
+
[CommandPalette](../components/command-palette.md) component as the app-wide
|
|
5
|
+
"do or go anywhere" surface, invoked by a documented shortcut, filtering
|
|
6
|
+
commands and destinations as the person types.
|
|
7
|
+
|
|
8
|
+
User story #23.
|
|
9
|
+
|
|
10
|
+
## Purpose
|
|
11
|
+
|
|
12
|
+
The command palette lets a person run frequent actions and jump to destinations
|
|
13
|
+
without hunting through menus: open a query editor, jump to a replica, switch
|
|
14
|
+
project, run a saved action. It is keyboard-first, invoked by a shortcut, and
|
|
15
|
+
filters a command list as the person types.
|
|
16
|
+
|
|
17
|
+
It is **not** list [Search](search.md) (which filters content in view) and not
|
|
18
|
+
a [DropdownMenu](../components/dropdown-menu.md) (which is contextual to one
|
|
19
|
+
trigger). The palette is global.
|
|
20
|
+
|
|
21
|
+
## Component composition
|
|
22
|
+
|
|
23
|
+
| Region | Compose with | Role |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| Overlay | [CommandPalette](../components/command-palette.md) dialog surface | Modal or non-modal elevated panel |
|
|
26
|
+
| Filter input | CommandPalette Input (autofocused) | Filters commands as the person types |
|
|
27
|
+
| Command list | CommandPalette List with Groups + Items | Actions and destinations, grouped |
|
|
28
|
+
| Empty | CommandPalette in-palette empty message | "No commands match 'xyz'" — not page-level EmptyState |
|
|
29
|
+
| Footer hints | optional keyboard legend | Reminds the person of `Enter`, `↑↓`, `Esc` |
|
|
30
|
+
| Explicit trigger | [Button](../components/button.md) or [IconButton](../components/icon-button.md) in [Header](../components/header.md) | Opens the same palette for non-keyboard users |
|
|
31
|
+
|
|
32
|
+
## Flow
|
|
33
|
+
|
|
34
|
+
1. Person presses `⌘K` (macOS) / `Ctrl+K` (Windows/Linux), or activates the
|
|
35
|
+
explicit trigger in the header.
|
|
36
|
+
2. The palette opens; focus moves to the Input. The list shows all commands
|
|
37
|
+
(or a default group).
|
|
38
|
+
3. Person types. The list filters as they type (search-as-you-type).
|
|
39
|
+
4. Person navigates with `↑` / `↓` across groups; the highlighted item is the
|
|
40
|
+
active descendant.
|
|
41
|
+
5. Person activates with `Enter` (or click). The command runs or navigation
|
|
42
|
+
occurs, and the palette closes.
|
|
43
|
+
6. `Escape` closes without activating. Focus returns to the previously focused
|
|
44
|
+
element (or the trigger).
|
|
45
|
+
|
|
46
|
+
If the chosen command is a [destructive action](destructive-actions.md), the
|
|
47
|
+
palette closes and a [confirmation](confirmations.md) dialog opens — the palette
|
|
48
|
+
is acceleration, not a bypass for the gate.
|
|
49
|
+
|
|
50
|
+
## States
|
|
51
|
+
|
|
52
|
+
| State | Behavior |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| closed | Palette not in tree (or inert). Shortcut and explicit trigger available. |
|
|
55
|
+
| open | Input focused; list visible; focus trapped within the palette (if modal). |
|
|
56
|
+
| filtering | List updates as the person types. Active descendant resets to the first match. |
|
|
57
|
+
| no matches | In-palette empty message: "No commands match 'xyz'". Not the page-level [EmptyState](../components/empty-state.md). |
|
|
58
|
+
| loading | Optional [Spinner](../components/spinner.md) in the list while command providers resolve. Input stays usable. `aria-busy` on the list. |
|
|
59
|
+
| error | Provider failure: short in-palette message or [Alert](../components/alert.md) pattern inside the panel. Do not fail silently to an empty list that looks like "no matches". |
|
|
60
|
+
|
|
61
|
+
## Layout sketch
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
┌──────────────────────────────────────────────┐
|
|
65
|
+
│ ⌘K Type a command or destination… │
|
|
66
|
+
├──────────────────────────────────────────────┤
|
|
67
|
+
│ Navigation │
|
|
68
|
+
│ ▸ Queries │
|
|
69
|
+
│ Replicas │
|
|
70
|
+
│ Settings │
|
|
71
|
+
│ Replicas │
|
|
72
|
+
│ ▸ Open prod-eu │
|
|
73
|
+
│ Open staging │
|
|
74
|
+
│ Open analytics │
|
|
75
|
+
│ Actions │
|
|
76
|
+
│ ▸ New query │
|
|
77
|
+
│ Switch project │
|
|
78
|
+
│ Refresh all replicas │
|
|
79
|
+
├──────────────────────────────────────────────┤
|
|
80
|
+
│ ↑↓ navigate ↵ run esc close │
|
|
81
|
+
└──────────────────────────────────────────────┘
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The palette is centered or top-anchored, elevated (`--color-elevated-surface`,
|
|
85
|
+
`--shadow-sm`, `--radius-lg`). The active (highlighted) item uses a quiet
|
|
86
|
+
`--color-surface` or `--color-primary` indicator — not a filled primary row.
|
|
87
|
+
|
|
88
|
+
## Rules
|
|
89
|
+
|
|
90
|
+
- **Invocation:** default `⌘K` / `Ctrl+K`, documented in product chrome. Do
|
|
91
|
+
not bind list [Search](search.md) fields to this shortcut.
|
|
92
|
+
- **One app-level palette.** Do not ship separate palettes per page unless the
|
|
93
|
+
product truly scopes commands. Default is one palette with groups
|
|
94
|
+
(Navigation, Replicas, Actions, Settings).
|
|
95
|
+
- **Commands vs destinations.** Both live in the palette. Destinations navigate
|
|
96
|
+
(open a route); commands run an action (new query, switch project). Group
|
|
97
|
+
them so the person can scan.
|
|
98
|
+
- **Shortcut hints** in items are decorative unless they document real bindings.
|
|
99
|
+
If an item shows `⌘N`, that binding must work even when the palette is closed.
|
|
100
|
+
- **Destructive commands still confirm.** A "Delete replica" command closes the
|
|
101
|
+
palette and opens a [confirmation](confirmations.md) dialog — it does not
|
|
102
|
+
delete on `Enter` from the palette.
|
|
103
|
+
- **Discoverability:** the palette is acceleration, not the only path. Critical
|
|
104
|
+
actions still need a visible control somewhere (header, page action, row
|
|
105
|
+
menu). Do not hide a primary action only in the palette.
|
|
106
|
+
- **Explicit trigger:** provide a [Button](../components/button.md) or
|
|
107
|
+
[IconButton](../components/icon-button.md) in the
|
|
108
|
+
[Header](../components/header.md) ("Search commands…") that opens the same
|
|
109
|
+
palette, so non-keyboard users can reach it.
|
|
110
|
+
- Do not use the palette for form data entry. It is not a form.
|
|
111
|
+
|
|
112
|
+
## Accessibility
|
|
113
|
+
|
|
114
|
+
- Prefer a modal dialog pattern (`role="dialog"`, `aria-modal="true"`) with
|
|
115
|
+
an accessible name ("Command palette").
|
|
116
|
+
- Input has a visible or programmatically associated label.
|
|
117
|
+
- List uses `role="listbox"` (or cmdk's list semantics) with items as options;
|
|
118
|
+
the active item is exposed via `aria-activedescendant` on the Input — do not
|
|
119
|
+
invent a broken tab-per-item list.
|
|
120
|
+
- Focus moves to the Input on open; on close, focus returns to the previously
|
|
121
|
+
focused element (or the trigger).
|
|
122
|
+
- `Escape` closes without running a command.
|
|
123
|
+
- Reduced motion: no gratuitous entrance animation beyond token durations.
|
|
124
|
+
|
|
125
|
+
### Keyboard
|
|
126
|
+
|
|
127
|
+
| Key | Action |
|
|
128
|
+
| --- | --- |
|
|
129
|
+
| `⌘K` / `Ctrl+K` | Toggle open/close. |
|
|
130
|
+
| Printable keys | Filter commands (input focused). |
|
|
131
|
+
| `↑` / `↓` | Move highlight through items (and across groups). |
|
|
132
|
+
| `Enter` | Activate highlighted item. |
|
|
133
|
+
| `Escape` | Close without activating. |
|
|
134
|
+
| `Tab` | Stays within the palette (focus trap) while open; do not tab into the page behind a modal palette. |
|
|
135
|
+
|
|
136
|
+
## Related patterns
|
|
137
|
+
|
|
138
|
+
- [Search](search.md) — filters content in view; the palette is global actions.
|
|
139
|
+
- [Keyboard shortcuts](keyboard-shortcuts.md) — the palette's `⌘K` is one
|
|
140
|
+
shortcut; this pattern covers the rest.
|
|
141
|
+
- [Destructive actions](destructive-actions.md) — palette commands that are
|
|
142
|
+
destructive still confirm.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Confirmations
|
|
2
|
+
|
|
3
|
+
Explain risk and require explicit acknowledgment before a consequential action.
|
|
4
|
+
This pattern is the dialog spec for any confirmation — destructive or not —
|
|
5
|
+
covering copy structure, focus, and the acknowledgment model. Destructive
|
|
6
|
+
actions ([destructive-actions](destructive-actions.md)) always use this pattern;
|
|
7
|
+
not every confirmation is destructive.
|
|
8
|
+
|
|
9
|
+
User story #12.
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
|
|
13
|
+
A confirmation interrupts the person before an action whose consequence is
|
|
14
|
+
non-obvious, delayed, or hard to reverse: disconnect a live connection, apply a
|
|
15
|
+
config change to production, revoke access, overwrite a resource. The
|
|
16
|
+
confirmation makes the consequence explicit and requires a deliberate choice.
|
|
17
|
+
|
|
18
|
+
It is not a courtesy "are you sure?" for routine actions. Over-confirming
|
|
19
|
+
trains the person to click through without reading; reserve confirmations for
|
|
20
|
+
genuine risk.
|
|
21
|
+
|
|
22
|
+
## Component composition
|
|
23
|
+
|
|
24
|
+
| Region | Compose with | Role |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| Dialog | [Modal / Dialog](../components/modal-dialog.md) | Blocks the page; focused task |
|
|
27
|
+
| Title | Dialog Title | Names the action in product language ("Disconnect 'staging-db'?") |
|
|
28
|
+
| Consequence | Dialog Description | What will happen, in plain language |
|
|
29
|
+
| Confirm action | [Button](../components/button.md) — variant matches stakes | Commits the action |
|
|
30
|
+
| Cancel action | [Button](../components/button.md) `default` or `ghost` | Closes without committing; always available |
|
|
31
|
+
| Acknowledgment (high-stakes) | [Checkbox](../components/checkbox.md) or type-to-confirm [Input](../components/input.md) | Required before confirm is enabled |
|
|
32
|
+
| Progress | [Spinner](../components/spinner.md) inside confirm Button | While the action is in flight |
|
|
33
|
+
|
|
34
|
+
## Flow
|
|
35
|
+
|
|
36
|
+
1. Person activates a trigger that opens the confirmation.
|
|
37
|
+
2. [Modal / Dialog](../components/modal-dialog.md) opens with focus on the first
|
|
38
|
+
meaningful element (usually Cancel).
|
|
39
|
+
3. The dialog states the action and its consequence. For high-stakes actions, an
|
|
40
|
+
acknowledgment step (checkbox or type-to-confirm) gates the confirm Button.
|
|
41
|
+
4. Person confirms or cancels.
|
|
42
|
+
- **Cancel** / `Escape` / overlay click (when safe): dialog closes, focus
|
|
43
|
+
returns to trigger, nothing changes.
|
|
44
|
+
- **Confirm**: Button enters loading; action runs.
|
|
45
|
+
5. On success, dialog closes and feedback follows ([Toast](../components/toast.md)
|
|
46
|
+
for brief confirmation, navigation if the context changed). On failure,
|
|
47
|
+
error [Alert](../components/alert.md) inside the dialog with recovery.
|
|
48
|
+
|
|
49
|
+
## States
|
|
50
|
+
|
|
51
|
+
| State | Behavior |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| closed | Trigger available. |
|
|
54
|
+
| open | Page inert; focus trapped. Cancel available; confirm available or gated. |
|
|
55
|
+
| gated | High-stakes: confirm Button disabled until acknowledgment complete (checkbox checked, or typed name matches). |
|
|
56
|
+
| submitting | Confirm Button loading ([Spinner](../components/spinner.md), `aria-busy`). Cancel available unless uninterruptible. |
|
|
57
|
+
| error | Recoverable error as [Alert](../components/alert.md) inside dialog; dialog stays open. |
|
|
58
|
+
| success | Dialog closes; [Toast](../components/toast.md) or navigation. |
|
|
59
|
+
|
|
60
|
+
## Copy structure
|
|
61
|
+
|
|
62
|
+
Confirmation copy follows [voice-and-tone](../voice-and-tone.md):
|
|
63
|
+
|
|
64
|
+
- **Title:** Name the action and the object. "Disconnect 'staging-db'?" — not
|
|
65
|
+
"Warning" or "Confirm".
|
|
66
|
+
- **Consequence:** What will happen, in one or two sentences. State the
|
|
67
|
+
irreversibility or side effect directly: "Active queries will be
|
|
68
|
+
terminated." Do not say "Are you absolutely sure?" — state the fact.
|
|
69
|
+
- **Match weight to stakes.** A low-stakes action (leave a draft unsaved) gets
|
|
70
|
+
a neutral dialog. A high-stakes action (drop database) gets type-to-confirm.
|
|
71
|
+
Do not wrap a low-stakes action in danger color, and do not under-state a
|
|
72
|
+
high-stakes one.
|
|
73
|
+
|
|
74
|
+
Anti-patterns (from voice-and-tone):
|
|
75
|
+
- "Are you absolutely sure?"
|
|
76
|
+
- "Oops! Are you sure you want to..."
|
|
77
|
+
- Danger color on a low-stakes confirmation.
|
|
78
|
+
- No consequence stated, only "Confirm / Cancel".
|
|
79
|
+
|
|
80
|
+
## Layout sketch
|
|
81
|
+
|
|
82
|
+
### Standard confirmation
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
┌──────────────────────────────────────────┐
|
|
86
|
+
│ Disconnect "staging-db"? │
|
|
87
|
+
│ │
|
|
88
|
+
│ Active queries to this database will be │
|
|
89
|
+
│ terminated. The connection can be │
|
|
90
|
+
│ re-established later. │
|
|
91
|
+
│ │
|
|
92
|
+
│ [Cancel] [Disconnect] │
|
|
93
|
+
└──────────────────────────────────────────┘
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### High-stakes (type-to-confirm)
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
┌──────────────────────────────────────────┐
|
|
100
|
+
│ Drop database "production"? │
|
|
101
|
+
│ │
|
|
102
|
+
│ All tables, data, and replicas in this │
|
|
103
|
+
│ database will be permanently deleted. │
|
|
104
|
+
│ This cannot be undone. │
|
|
105
|
+
│ │
|
|
106
|
+
│ Type the database name to confirm: │
|
|
107
|
+
│ [production ] │
|
|
108
|
+
│ │
|
|
109
|
+
│ [Cancel] [Drop database] │
|
|
110
|
+
└──────────────────────────────────────────┘
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`Drop database` stays disabled until "production" is typed exactly. The
|
|
114
|
+
confirm Button is the only destructive-styled control.
|
|
115
|
+
|
|
116
|
+
## Rules
|
|
117
|
+
|
|
118
|
+
- Confirm only when there is genuine consequence. Routine saves, toggles, and
|
|
119
|
+
navigation do not need confirmation; over-confirmation trains click-through.
|
|
120
|
+
- State the consequence, not a question. "Active queries will be terminated"
|
|
121
|
+
beats "Are you sure you want to disconnect?"
|
|
122
|
+
- The confirm Button's variant matches the stakes:
|
|
123
|
+
- Destructive (delete, drop, purge) → `destructive` variant.
|
|
124
|
+
- Consequential but not destructive (disconnect, revoke, apply to production)
|
|
125
|
+
→ `default` variant, possibly with a warning tone in the copy.
|
|
126
|
+
- Low-stakes (discard draft) → `default`.
|
|
127
|
+
- Cancel is always available and is the safe default. Prefer focusing Cancel on
|
|
128
|
+
open.
|
|
129
|
+
- High-stakes actions use acknowledgment:
|
|
130
|
+
- **Checkbox:** "I understand this cannot be undone" — for actions where the
|
|
131
|
+
person must consciously accept irreversibility.
|
|
132
|
+
- **Type-to-confirm:** type the exact resource name — for the highest-stakes
|
|
133
|
+
actions (drop database, delete workspace). Reserve sparingly; overuse makes
|
|
134
|
+
it friction without safety.
|
|
135
|
+
- Do not use [Toast](../components/toast.md) as a confirmation. Toast is
|
|
136
|
+
transient and cannot require a decision. If a decision is needed, it is a
|
|
137
|
+
dialog.
|
|
138
|
+
- Do not auto-confirm after a timeout. The person must explicitly choose.
|
|
139
|
+
|
|
140
|
+
## Accessibility
|
|
141
|
+
|
|
142
|
+
- Dialog: `role="dialog"`, `aria-modal="true"`, `aria-labelledby`,
|
|
143
|
+
`aria-describedby` (consequence).
|
|
144
|
+
- Focus to first meaningful element on open (usually Cancel). `Tab` /
|
|
145
|
+
`Shift+Tab` cycle inside; `Escape` closes when safe.
|
|
146
|
+
- Confirm Button accessible name includes the action: "Disconnect", "Drop
|
|
147
|
+
database" — not "Confirm".
|
|
148
|
+
- Gated confirm: the disabled Button has an accessible explanation ("Type the
|
|
149
|
+
database name to enable Drop database"). The acknowledgment
|
|
150
|
+
[Checkbox](../components/checkbox.md) or [Input](../components/input.md) has a
|
|
151
|
+
[Label](../components/label.md).
|
|
152
|
+
- On error, move focus to the error [Alert](../components/alert.md) so the
|
|
153
|
+
person lands on the recovery path.
|
|
154
|
+
|
|
155
|
+
## Related patterns
|
|
156
|
+
|
|
157
|
+
- [Destructive actions](destructive-actions.md) — the specific gate for
|
|
158
|
+
irreversible actions; always uses this confirmation spec.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# CRUD
|
|
2
|
+
|
|
3
|
+
Create, read/update, and delete flows for a single entity type. Covers form
|
|
4
|
+
layout, validation, and the create / edit / delete states without inventing
|
|
5
|
+
one-off form kits.
|
|
6
|
+
|
|
7
|
+
User stories #9 and #10.
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
Make every Momoi resource editable the same way: labeled fields, predictable
|
|
12
|
+
primary/secondary actions, field-level validation, and clear success or failure
|
|
13
|
+
feedback. This layout pattern places create/edit surfaces and delete entry
|
|
14
|
+
points; confirmation copy and acknowledgment for irreversible deletes are
|
|
15
|
+
specified separately and must still run before destruction.
|
|
16
|
+
|
|
17
|
+
## Component composition
|
|
18
|
+
|
|
19
|
+
| Concern | Compose with | Role |
|
|
20
|
+
| --- | --- | --- |
|
|
21
|
+
| Page framing | [PageHeader](../components/page-header.md) | Title ("New connection", "Edit connection"); optional cancel secondary action |
|
|
22
|
+
| Fields | [FormField](../components/form-field.md) | Each field = [Label](../components/label.md) + control ([Input](../components/input.md), [Textarea](../components/textarea.md), [Select](../components/select.md), [Checkbox](../components/checkbox.md), …) + optional [HelperText](../components/helper-text.md) + [ValidationMessage](../components/validation-message.md) |
|
|
23
|
+
| Grouping | [Card](../components/card.md) or section headings | Related field groups (connection, credentials, advanced) |
|
|
24
|
+
| Primary actions | [Button](../components/button.md) | Save / Create (primary); Cancel (secondary/ghost) |
|
|
25
|
+
| Overlays | [Modal / Dialog](../components/modal-dialog.md) or [Drawer](../components/drawer.md) | Compact create/edit; Drawer preferred on small viewports for the same task |
|
|
26
|
+
| Inline errors | [ValidationMessage](../components/validation-message.md) on FormField | Field-level recovery; page [Alert](../components/alert.md) is for non-field failures |
|
|
27
|
+
| Form / load errors | [Alert](../components/alert.md) | Submit or load failures that are not field-local (what / why / now) |
|
|
28
|
+
| Success | [Toast](../components/toast.md) | Brief "Saved" / "Created"; do not rely on Toast alone for blocking failures |
|
|
29
|
+
| Delete entry | Button or [DropdownMenu](../components/dropdown-menu.md) item | Opens confirmation flow; danger styling on the destructive control |
|
|
30
|
+
| Read context | [Badge](../components/badge.md), [Tabs](../components/tabs.md) | Status and sections on edit/detail surfaces |
|
|
31
|
+
| Shell | [Application shell](application-shell.md) | Authenticated framing |
|
|
32
|
+
|
|
33
|
+
Tokens: form surfaces `--color-surface`, canvas `--color-background`, borders
|
|
34
|
+
`--color-border`, text `--color-foreground` / `--color-muted-foreground`,
|
|
35
|
+
invalid fields and ValidationMessage use `--color-danger`, focus
|
|
36
|
+
`--color-focus`, destructive Buttons use `--color-danger` per the Button
|
|
37
|
+
contract.
|
|
38
|
+
|
|
39
|
+
## Flow
|
|
40
|
+
|
|
41
|
+
### Create
|
|
42
|
+
|
|
43
|
+
1. Person activates Create from PageHeader or EmptyState.
|
|
44
|
+
2. Open full-page form, Modal, or Drawer with empty FormFields.
|
|
45
|
+
3. Person submits; invalid fields show ValidationMessage and receive focus on
|
|
46
|
+
the first error.
|
|
47
|
+
4. On success: Toast (optional), navigate to the new entity's detail or list
|
|
48
|
+
selection; close overlay if used.
|
|
49
|
+
5. On failure: keep the form open; Alert for non-field errors; preserve input.
|
|
50
|
+
|
|
51
|
+
### Edit
|
|
52
|
+
|
|
53
|
+
1. Person opens Edit from list-detail actions or a detail PageHeader.
|
|
54
|
+
2. Form loads current values; read-only identifiers stay visible but not
|
|
55
|
+
editable when the API forbids changes.
|
|
56
|
+
3. Save enables when the form is dirty (product may also allow explicit Save
|
|
57
|
+
always — be consistent within a product).
|
|
58
|
+
4. Validation and error handling match Create.
|
|
59
|
+
5. Cancel discards unsaved changes (confirm only if dirty and loss is material).
|
|
60
|
+
|
|
61
|
+
### Delete
|
|
62
|
+
|
|
63
|
+
1. Person chooses Delete from entity actions.
|
|
64
|
+
2. An explicit confirmation step runs before destruction (Modal/Dialog with
|
|
65
|
+
clear consequences); this layout requires that step, not its microcopy.
|
|
66
|
+
3. On success: Toast or list refresh; navigate away from a deleted detail.
|
|
67
|
+
4. On failure: Alert with recovery; entity remains.
|
|
68
|
+
|
|
69
|
+
Prefer Modal/Drawer for short create/edit. Use a full main-page form when the
|
|
70
|
+
field set is long, multi-section, or needs side-by-side reference content.
|
|
71
|
+
|
|
72
|
+
## States
|
|
73
|
+
|
|
74
|
+
| State | Behavior |
|
|
75
|
+
| --- | --- |
|
|
76
|
+
| loading (edit) | Skeleton for known field layout inside the form surface; do not flash empty Inputs. |
|
|
77
|
+
| empty (create from empty collection) | EmptyState on the list offers Create; CRUD form is the next step — do not reinvent empty handling inside the form. |
|
|
78
|
+
| invalid | ValidationMessage per field; first invalid control focused; do not clear other fields. |
|
|
79
|
+
| submitting | Primary Button loading (Spinner in Button); prevent double submit; Cancel remains available when safe. |
|
|
80
|
+
| error (load) | Alert in the form region (what / why / now); offer retry; Cancel/back remains. |
|
|
81
|
+
| error (submit) | Field errors via ValidationMessage; server/business errors via Alert; form stays open with values preserved. |
|
|
82
|
+
| success | Toast or inline success only as confirmation; navigate or refresh per flow above. |
|
|
83
|
+
|
|
84
|
+
## Layout sketch
|
|
85
|
+
|
|
86
|
+
Full-page create/edit:
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
┌──────────────────────────────────────────────────────────────────────┐
|
|
90
|
+
│ PageHeader: Edit connection [Cancel] [Save] │
|
|
91
|
+
├──────────────────────────────────────────────────────────────────────┤
|
|
92
|
+
│ Alert (only if submit/load error — what / why / now) │
|
|
93
|
+
│ │
|
|
94
|
+
│ Card: Connection │
|
|
95
|
+
│ FormField Name │
|
|
96
|
+
│ FormField Host │
|
|
97
|
+
│ FormField Port │
|
|
98
|
+
│ │
|
|
99
|
+
│ Card: Credentials │
|
|
100
|
+
│ FormField User │
|
|
101
|
+
│ FormField Password │
|
|
102
|
+
│ FormField SSL [Select] │
|
|
103
|
+
│ │
|
|
104
|
+
│ [Cancel] [Save] │
|
|
105
|
+
└──────────────────────────────────────────────────────────────────────┘
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Modal create (compact):
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
┌─────────────────────────────────┐
|
|
112
|
+
│ New connection [✕] │
|
|
113
|
+
│ │
|
|
114
|
+
│ FormField Name │
|
|
115
|
+
│ FormField Host │
|
|
116
|
+
│ FormField Port │
|
|
117
|
+
│ │
|
|
118
|
+
│ [Cancel] [Create] │
|
|
119
|
+
└─────────────────────────────────┘
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## When to use
|
|
123
|
+
|
|
124
|
+
- Any resource with create and/or edit forms.
|
|
125
|
+
- Delete entry points on list rows or detail headers.
|
|
126
|
+
|
|
127
|
+
## When NOT to use
|
|
128
|
+
|
|
129
|
+
- Immediate boolean preferences without a Save affordance — prefer Switch
|
|
130
|
+
inside [Settings](settings.md).
|
|
131
|
+
- Bulk multi-entity editors — extend list-detail selection + confirmed bulk
|
|
132
|
+
actions instead of a single CRUD form.
|
|
133
|
+
|
|
134
|
+
## Related patterns
|
|
135
|
+
|
|
136
|
+
- [List-detail](list-detail.md) — where Create and row actions usually live.
|
|
137
|
+
List EmptyState still follows the canonical rule: do not reinvent search,
|
|
138
|
+
filters, pagination, or empty state on the way into Create.
|
|
139
|
+
- [Settings](settings.md) — preference forms with explicit save sections.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Dashboard
|
|
2
|
+
|
|
3
|
+
A scan-first overview of several related metrics or summaries on one page.
|
|
4
|
+
Widgets share density and hierarchy rules; the page is not a junk drawer of
|
|
5
|
+
unrelated Cards.
|
|
6
|
+
|
|
7
|
+
User story #30.
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
Orient the person quickly: what needs attention, what is healthy, and where to
|
|
12
|
+
go next. Dashboards summarize; deep investigation happens in list-detail,
|
|
13
|
+
tables, or dedicated tool routes.
|
|
14
|
+
|
|
15
|
+
## Component composition
|
|
16
|
+
|
|
17
|
+
| Region | Compose with | Role |
|
|
18
|
+
| --- | --- | --- |
|
|
19
|
+
| Page framing | [PageHeader](../components/page-header.md) | Dashboard title; optional time-range or environment [Select](../components/select.md); optional refresh [IconButton](../components/icon-button.md) / [Button](../components/button.md) |
|
|
20
|
+
| Widget unit | [Card](../components/card.md) | One concern per Card (metric cluster, short table, status list) |
|
|
21
|
+
| Status | [Badge](../components/badge.md) | Compact health/severity labels inside Cards |
|
|
22
|
+
| Dense lists | [Table / DataTable](../components/table.md) | Short "needs attention" tables — still compose Search/EmptyState/Pagination only when those behaviors are truly present |
|
|
23
|
+
| Alerts | [Alert](../components/alert.md) | Page-level degraded conditions that outrank widgets |
|
|
24
|
+
| Navigation out | [Link](../components/link.md) | "View all" from a widget into list-detail or a tool |
|
|
25
|
+
| Shell | [Application shell](application-shell.md) | Header + Sidebar + main |
|
|
26
|
+
|
|
27
|
+
**Canonical rule (when a widget is a list):** A list screen must not reinvent
|
|
28
|
+
search, filters, pagination, and empty state. A dashboard widget that embeds a
|
|
29
|
+
mini-list still uses EmptyState and Table composition — it does not invent a
|
|
30
|
+
third list pattern.
|
|
31
|
+
|
|
32
|
+
Tokens: page canvas `--color-background`, widgets `--color-surface` with
|
|
33
|
+
`--color-border`, titles `--color-foreground`, supporting
|
|
34
|
+
`--color-muted-foreground`, emphasis `--color-primary`, status via Badge
|
|
35
|
+
semantic colors, focus `--color-focus`. Prefer quiet surfaces and strong
|
|
36
|
+
hierarchy ([principles](../principles.md)).
|
|
37
|
+
|
|
38
|
+
Charts are out of scope for this epic; when charts exist later, they sit inside
|
|
39
|
+
Card like any other widget payload.
|
|
40
|
+
|
|
41
|
+
## Flow
|
|
42
|
+
|
|
43
|
+
1. Person opens Overview / Dashboard from Sidebar.
|
|
44
|
+
2. PageHeader establishes scope (product area, optional range/environment).
|
|
45
|
+
3. Widgets load independently when possible so one slow tile does not block the
|
|
46
|
+
whole page.
|
|
47
|
+
4. Person scans Badges and summary numbers, then follows a Link into a deeper
|
|
48
|
+
list-detail or tool view.
|
|
49
|
+
5. Refresh updates widget data without remounting the application shell.
|
|
50
|
+
|
|
51
|
+
Keep widget count deliberate. If a Card has no job beyond decoration, remove
|
|
52
|
+
it.
|
|
53
|
+
|
|
54
|
+
## States
|
|
55
|
+
|
|
56
|
+
| State | Behavior |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| loading | Per-widget Skeleton that preserves Card size; PageHeader stays. Avoid a single full-page Spinner unless the dashboard has no known layout yet. |
|
|
59
|
+
| empty (no data in a widget) | EmptyState inside that Card only ("No failing checks") with optional Link; other widgets remain. |
|
|
60
|
+
| empty (product not configured) | One page-level [EmptyState](../components/empty-state.md) with a clear next action instead of a grid of hollow Cards. |
|
|
61
|
+
| error (one widget) | Alert or error content inside that Card with retry; siblings keep working. |
|
|
62
|
+
| error (page) | Alert under PageHeader (what / why / now); widgets may still show last-known content if labeled stale. |
|
|
63
|
+
|
|
64
|
+
## Layout sketch
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
┌──────────────────────────────────────────────────────────────────────┐
|
|
68
|
+
│ PageHeader: Overview [Environment▾] [Refresh] │
|
|
69
|
+
├──────────────────────────────────────────────────────────────────────┤
|
|
70
|
+
│ Alert (optional page-level condition) │
|
|
71
|
+
│ │
|
|
72
|
+
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────────────────────┐│
|
|
73
|
+
│ │ Card: Health │ │ Card: Lag │ │ Card: Connections ││
|
|
74
|
+
│ │ [Badge ok] │ │ 18 ms │ │ active 12 · idle 3 ││
|
|
75
|
+
│ │ 4 / 4 up │ │ p95 │ │ [View connections →] ││
|
|
76
|
+
│ └───────────────┘ └───────────────┘ └───────────────────────────────┘│
|
|
77
|
+
│ │
|
|
78
|
+
│ ┌──────────────────────────────────────────────────────────────────┐ │
|
|
79
|
+
│ │ Card: Needs attention │ │
|
|
80
|
+
│ │ Table: Name | Issue | Since │ │
|
|
81
|
+
│ │ … short rows … │ │
|
|
82
|
+
│ │ EmptyState if none │ │
|
|
83
|
+
│ └──────────────────────────────────────────────────────────────────┘ │
|
|
84
|
+
└──────────────────────────────────────────────────────────────────────┘
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## When to use
|
|
88
|
+
|
|
89
|
+
- Product home / overview routes.
|
|
90
|
+
- Operator glance surfaces that link into deeper tools.
|
|
91
|
+
|
|
92
|
+
## When NOT to use
|
|
93
|
+
|
|
94
|
+
- The primary working surface for one entity — use [List-detail](list-detail.md).
|
|
95
|
+
- Long configuration forms — use [Settings](settings.md) or [CRUD](crud.md).
|
|
96
|
+
- A single full-height operational table — use list-detail / DataTable, not a
|
|
97
|
+
one-widget "dashboard".
|
|
98
|
+
|
|
99
|
+
## Related patterns
|
|
100
|
+
|
|
101
|
+
- [Application shell](application-shell.md)
|
|
102
|
+
- [List-detail](list-detail.md) — drill-down target for "View all"
|