@poodle64/ui 2026.8.7 → 2026.8.8
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.
|
@@ -50,7 +50,10 @@
|
|
|
50
50
|
* applied it as a helper class per route, so it reached four routes out of
|
|
51
51
|
* about fifteen. Which pages wore the house atmosphere was decided by which
|
|
52
52
|
* pages someone had happened to touch. `texture` is one named picture the
|
|
53
|
-
* SHELL paints once,
|
|
53
|
+
* SHELL paints once, its inks tuned by custom properties. It shipped off by
|
|
54
|
+
* default so its arrival moved nobody; it is ON by default now, because an
|
|
55
|
+
* opt-in house style is not a house style — it is a survey of who
|
|
56
|
+
* remembered. `collapsible` is on for the same reason.
|
|
54
57
|
*
|
|
55
58
|
* Everything else the surveyed apps differed on turned out to be a slot, not
|
|
56
59
|
* a variant: the brand, the identity surface, a context switcher, a banner, a
|
|
@@ -83,7 +86,7 @@
|
|
|
83
86
|
nav,
|
|
84
87
|
navLabel = 'Primary',
|
|
85
88
|
currentPath,
|
|
86
|
-
collapsible =
|
|
89
|
+
collapsible = true,
|
|
87
90
|
collapsed = $bindable(false),
|
|
88
91
|
brand,
|
|
89
92
|
brandTitle,
|
|
@@ -102,7 +105,7 @@
|
|
|
102
105
|
onToggleTheme,
|
|
103
106
|
padded = true,
|
|
104
107
|
measure = 'full',
|
|
105
|
-
texture = '
|
|
108
|
+
texture = 'grid',
|
|
106
109
|
mainClass,
|
|
107
110
|
children
|
|
108
111
|
}: {
|
|
@@ -123,7 +126,15 @@
|
|
|
123
126
|
* a component that is framework-agnostic and genuinely drivable.
|
|
124
127
|
*/
|
|
125
128
|
currentPath?: string;
|
|
126
|
-
/**
|
|
129
|
+
/**
|
|
130
|
+
* Offer an icon-only collapse toggle at the rail head, on the brand row.
|
|
131
|
+
*
|
|
132
|
+
* Defaults ON. It was opt-in while the control was being introduced, and
|
|
133
|
+
* two of nine household apps opted in — so seven rails could not be
|
|
134
|
+
* collapsed, for no reason anyone had chosen. The shell shape is not an
|
|
135
|
+
* app's to pick (operator ruling, 31/07/2026); set `false` only where a
|
|
136
|
+
* rail genuinely must not collapse.
|
|
137
|
+
*/
|
|
127
138
|
collapsible?: boolean;
|
|
128
139
|
/** Rail collapse state. Bind it to persist the choice across sessions. */
|
|
129
140
|
collapsed?: boolean;
|
|
@@ -178,12 +189,15 @@
|
|
|
178
189
|
* The house atmosphere on the content region: `grid` (a dot-grid floor
|
|
179
190
|
* plus a corner vignette) or `none`.
|
|
180
191
|
*
|
|
181
|
-
* Defaults to `
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
192
|
+
* Defaults to `grid` — the house atmosphere every app wears. It shipped
|
|
193
|
+
* as `none` so its introduction moved nobody, and the result was the drift
|
|
194
|
+
* it was built to end: five of nine apps had it, three of those through a
|
|
195
|
+
* hand-rolled `*-dotgrid` class in their own app.css under three names,
|
|
196
|
+
* two ink variables and two pitches, only one carrying the
|
|
197
|
+
* `background-attachment: local` that stops the floor sliding under the
|
|
198
|
+
* scroller. One default retires all three. The inks and the pitch are
|
|
199
|
+
* `--ds-shell-texture-*` custom properties an app retunes in one
|
|
200
|
+
* declaration; `none` turns it off.
|
|
187
201
|
*/
|
|
188
202
|
texture?: ShellTexture;
|
|
189
203
|
/** Extra classes on the scrolling content container. */
|
|
@@ -49,7 +49,10 @@
|
|
|
49
49
|
* applied it as a helper class per route, so it reached four routes out of
|
|
50
50
|
* about fifteen. Which pages wore the house atmosphere was decided by which
|
|
51
51
|
* pages someone had happened to touch. `texture` is one named picture the
|
|
52
|
-
* SHELL paints once,
|
|
52
|
+
* SHELL paints once, its inks tuned by custom properties. It shipped off by
|
|
53
|
+
* default so its arrival moved nobody; it is ON by default now, because an
|
|
54
|
+
* opt-in house style is not a house style — it is a survey of who
|
|
55
|
+
* remembered. `collapsible` is on for the same reason.
|
|
53
56
|
*
|
|
54
57
|
* Everything else the surveyed apps differed on turned out to be a slot, not
|
|
55
58
|
* a variant: the brand, the identity surface, a context switcher, a banner, a
|
|
@@ -85,7 +88,15 @@ type $$ComponentProps = {
|
|
|
85
88
|
* a component that is framework-agnostic and genuinely drivable.
|
|
86
89
|
*/
|
|
87
90
|
currentPath?: string;
|
|
88
|
-
/**
|
|
91
|
+
/**
|
|
92
|
+
* Offer an icon-only collapse toggle at the rail head, on the brand row.
|
|
93
|
+
*
|
|
94
|
+
* Defaults ON. It was opt-in while the control was being introduced, and
|
|
95
|
+
* two of nine household apps opted in — so seven rails could not be
|
|
96
|
+
* collapsed, for no reason anyone had chosen. The shell shape is not an
|
|
97
|
+
* app's to pick (operator ruling, 31/07/2026); set `false` only where a
|
|
98
|
+
* rail genuinely must not collapse.
|
|
99
|
+
*/
|
|
89
100
|
collapsible?: boolean;
|
|
90
101
|
/** Rail collapse state. Bind it to persist the choice across sessions. */
|
|
91
102
|
collapsed?: boolean;
|
|
@@ -140,12 +151,15 @@ type $$ComponentProps = {
|
|
|
140
151
|
* The house atmosphere on the content region: `grid` (a dot-grid floor
|
|
141
152
|
* plus a corner vignette) or `none`.
|
|
142
153
|
*
|
|
143
|
-
* Defaults to `
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
154
|
+
* Defaults to `grid` — the house atmosphere every app wears. It shipped
|
|
155
|
+
* as `none` so its introduction moved nobody, and the result was the drift
|
|
156
|
+
* it was built to end: five of nine apps had it, three of those through a
|
|
157
|
+
* hand-rolled `*-dotgrid` class in their own app.css under three names,
|
|
158
|
+
* two ink variables and two pitches, only one carrying the
|
|
159
|
+
* `background-attachment: local` that stops the floor sliding under the
|
|
160
|
+
* scroller. One default retires all three. The inks and the pitch are
|
|
161
|
+
* `--ds-shell-texture-*` custom properties an app retunes in one
|
|
162
|
+
* declaration; `none` turns it off.
|
|
149
163
|
*/
|
|
150
164
|
texture?: ShellTexture;
|
|
151
165
|
/** Extra classes on the scrolling content container. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poodle64/ui",
|
|
3
|
-
"version": "2026.8.
|
|
3
|
+
"version": "2026.8.8",
|
|
4
4
|
"description": "Household shared component layer: shadcn-svelte primitives (bits-ui) plus the composed page chrome every app builds its routes from, restyled by each app's @poodle64/design-tokens alias layer. One fix reaches every app.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"access": "public"
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
|
-
"dist"
|
|
13
|
+
"dist",
|
|
14
|
+
"registry"
|
|
14
15
|
],
|
|
15
16
|
"exports": {
|
|
16
17
|
"./package.json": "./package.json",
|
|
@@ -69,7 +70,9 @@
|
|
|
69
70
|
"vitest": "^4.1.10"
|
|
70
71
|
},
|
|
71
72
|
"scripts": {
|
|
72
|
-
"build": "svelte-kit sync && svelte-package && publint",
|
|
73
|
+
"build": "node scripts/generate-registry.mjs && svelte-kit sync && svelte-package && publint",
|
|
74
|
+
"registry": "node scripts/generate-registry.mjs",
|
|
75
|
+
"registry:check": "node scripts/generate-registry.mjs --check",
|
|
73
76
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
74
77
|
"test": "pnpm run build && vitest run",
|
|
75
78
|
"test:browser": "pnpm run harness:build && node harness/drive.mjs",
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"package": "@poodle64/ui",
|
|
4
|
+
"version": "2026.8.8",
|
|
5
|
+
"generatedBy": "scripts/generate-registry.mjs",
|
|
6
|
+
"source": "scripts/situations.json + package source (DO NOT EDIT the outputs by hand)",
|
|
7
|
+
"componentCount": 49,
|
|
8
|
+
"situationCount": 12
|
|
9
|
+
},
|
|
10
|
+
"situations": [
|
|
11
|
+
{
|
|
12
|
+
"key": "single-figure",
|
|
13
|
+
"title": "A single labelled figure",
|
|
14
|
+
"description": "One headline metric that earns a tile — a figure with a label, an optional unit, and the state of the thing it measures.",
|
|
15
|
+
"components": [
|
|
16
|
+
{
|
|
17
|
+
"name": "StatCard",
|
|
18
|
+
"dir": "stat-card",
|
|
19
|
+
"import": "@poodle64/ui/stat-card",
|
|
20
|
+
"props": "label, value, unit?, sub?, status?, valueTone?, icon?",
|
|
21
|
+
"insteadOf": "a Card you hand-build with a label over a big number"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"key": "compact-figures",
|
|
27
|
+
"title": "Several bare figures together",
|
|
28
|
+
"description": "A block of plain figures read at a glance — an 'at a glance' strip — where each number is too small to earn its own StatCard.",
|
|
29
|
+
"components": [
|
|
30
|
+
{
|
|
31
|
+
"name": "StatList",
|
|
32
|
+
"dir": "stat-list",
|
|
33
|
+
"import": "@poodle64/ui/stat-list",
|
|
34
|
+
"props": "items, title?, info?",
|
|
35
|
+
"insteadOf": "a hand-built <dl> or a stack of label/value <div>s"
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"key": "ranked-comparison",
|
|
41
|
+
"title": "Comparing magnitudes across rows",
|
|
42
|
+
"description": "A small ranked set of labelled bars — a per-lane usage table, a token-burn chart — where a full StatCard per row would be too heavy.",
|
|
43
|
+
"components": [
|
|
44
|
+
{
|
|
45
|
+
"name": "BarRow",
|
|
46
|
+
"dir": "bar-row",
|
|
47
|
+
"import": "@poodle64/ui/bar-row",
|
|
48
|
+
"props": "label, value, pct, color?, labelWidth?",
|
|
49
|
+
"insteadOf": "a <div> with an inline width:%% bar you style by hand"
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"key": "share-of-a-whole",
|
|
55
|
+
"title": "A share of a bounded whole",
|
|
56
|
+
"description": "A part of a fixed total — a percentage, a capacity, a rate-limit window — read as one 0–100 figure.",
|
|
57
|
+
"components": [
|
|
58
|
+
{
|
|
59
|
+
"name": "ArcGauge",
|
|
60
|
+
"dir": "arc-gauge",
|
|
61
|
+
"import": "@poodle64/ui/arc-gauge",
|
|
62
|
+
"props": "pct, tone?, size?, showLabel?, label?",
|
|
63
|
+
"insteadOf": "a hand-drawn SVG ring, or printing a bare \"72%\""
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"key": "trend-over-time",
|
|
69
|
+
"title": "A compact trend",
|
|
70
|
+
"description": "An inline time series in a row or card — a trend the eye reads at a glance, not a full Tier-1 chart.",
|
|
71
|
+
"components": [
|
|
72
|
+
{
|
|
73
|
+
"name": "Sparkline",
|
|
74
|
+
"dir": "sparkline",
|
|
75
|
+
"import": "@poodle64/ui/sparkline",
|
|
76
|
+
"props": "series, width, height, pad?",
|
|
77
|
+
"insteadOf": "a hand-built SVG polyline, or reaching for a charting library for a thumbnail"
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"key": "state-of-a-thing",
|
|
83
|
+
"title": "The state of a thing",
|
|
84
|
+
"description": "The health or status of something. One state reads as a chip; several independent states read as a dot strip.",
|
|
85
|
+
"components": [
|
|
86
|
+
{
|
|
87
|
+
"name": "StatusBadge",
|
|
88
|
+
"dir": "status-badge",
|
|
89
|
+
"import": "@poodle64/ui/status-badge",
|
|
90
|
+
"props": "status, label, pulse?",
|
|
91
|
+
"insteadOf": "a coloured <span> pill you tint by hand"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "Scorecard",
|
|
95
|
+
"dir": "scorecard",
|
|
96
|
+
"import": "@poodle64/ui/scorecard",
|
|
97
|
+
"props": "scores",
|
|
98
|
+
"insteadOf": "a hand-built row of coloured dots for several on/off/warn checks"
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"key": "entity-detail",
|
|
104
|
+
"title": "The detail of one entity",
|
|
105
|
+
"description": "The surface for a single selected record — an eyebrow, a title, its status, and a close affordance over the body.",
|
|
106
|
+
"components": [
|
|
107
|
+
{
|
|
108
|
+
"name": "DetailPanel",
|
|
109
|
+
"dir": "detail-panel",
|
|
110
|
+
"import": "@poodle64/ui/detail-panel",
|
|
111
|
+
"props": "title, eyebrow?, status?, statusLabel?, onClose?, children",
|
|
112
|
+
"insteadOf": "a Card you hand-build with an eyebrow, a title row and a close button"
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"key": "catalogue-of-like-things",
|
|
118
|
+
"title": "A catalogue of like things",
|
|
119
|
+
"description": "An index of many peer items — a responsive tile wall, or a sortable/filterable table of records.",
|
|
120
|
+
"components": [
|
|
121
|
+
{
|
|
122
|
+
"name": "TileGrid",
|
|
123
|
+
"dir": "tile-grid",
|
|
124
|
+
"import": "@poodle64/ui/tile-grid",
|
|
125
|
+
"props": "children, min?, gap?, tag?",
|
|
126
|
+
"insteadOf": "a grid with fixed sm:grid-cols-* breakpoints you maintain per page"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "DataTableTanstack",
|
|
130
|
+
"dir": "data-table-tanstack",
|
|
131
|
+
"import": "@poodle64/ui/data-table-tanstack",
|
|
132
|
+
"props": "table, selectable?, selectedId?, onSelect?, emptyMessage?",
|
|
133
|
+
"insteadOf": "a hand-built <table>, or the raw Table primitive wired to TanStack by hand"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"name": "DataTableToolbar",
|
|
137
|
+
"dir": "data-table-toolbar",
|
|
138
|
+
"import": "@poodle64/ui/data-table-toolbar",
|
|
139
|
+
"props": "searchValue, onSearch, searchPlaceholder?, chipGroups?, trailing?",
|
|
140
|
+
"insteadOf": "a hand-built search + filter-chip bar above a table"
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"key": "sectioning-card",
|
|
146
|
+
"title": "A titled section of a route",
|
|
147
|
+
"description": "The generic titled card every route reaches for — an optional header with icon, subtitle and actions over a body. The default answer to 'I need a card here'.",
|
|
148
|
+
"components": [
|
|
149
|
+
{
|
|
150
|
+
"name": "Panel",
|
|
151
|
+
"dir": "panel",
|
|
152
|
+
"import": "@poodle64/ui/panel",
|
|
153
|
+
"props": "children, title?, subtitle?, icon?, action?, pad?",
|
|
154
|
+
"insteadOf": "raw Card + CardHeader + CardTitle assembled by hand on every route"
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"key": "page-frame",
|
|
160
|
+
"title": "The frame every route shares",
|
|
161
|
+
"description": "The standing chrome — the app shell and its nav, the one page-title treatment, the persistent right-hand context column.",
|
|
162
|
+
"components": [
|
|
163
|
+
{
|
|
164
|
+
"name": "AppShell",
|
|
165
|
+
"dir": "app-shell",
|
|
166
|
+
"import": "@poodle64/ui/app-shell",
|
|
167
|
+
"props": "nav, currentPath, brandTitle?, actions?, context?, children",
|
|
168
|
+
"insteadOf": "a bespoke nav rail + header layout per app"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"name": "PageHeader",
|
|
172
|
+
"dir": "page-header",
|
|
173
|
+
"import": "@poodle64/ui/page-header",
|
|
174
|
+
"props": "title?, eyebrow?, breadcrumbs?, subtitle?, info?, actions?",
|
|
175
|
+
"insteadOf": "a hand-written <h1> and title bar (the drift gate fails this)"
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"name": "ContextColumn",
|
|
179
|
+
"dir": "context-column",
|
|
180
|
+
"import": "@poodle64/ui/context-column",
|
|
181
|
+
"props": "stats, statsTitle?, statsInfo?, detail?, ariaLabel?",
|
|
182
|
+
"insteadOf": "a hand-built right-hand <aside> with a stat card and a detail pane"
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"key": "dialog-and-overlay",
|
|
188
|
+
"title": "A dialog or overlay",
|
|
189
|
+
"description": "A modal task and the pieces around it — the dialog frame, a section within its body, a ⌘K palette, an inline (i) hint.",
|
|
190
|
+
"components": [
|
|
191
|
+
{
|
|
192
|
+
"name": "AppDialog",
|
|
193
|
+
"dir": "app-dialog",
|
|
194
|
+
"import": "@poodle64/ui/app-dialog",
|
|
195
|
+
"props": "title, open, onOpenChange?, size?, children, footer?",
|
|
196
|
+
"insteadOf": "raw Dialog.* parts assembled into a frame by hand"
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"name": "DialogSection",
|
|
200
|
+
"dir": "dialog-section",
|
|
201
|
+
"import": "@poodle64/ui/dialog-section",
|
|
202
|
+
"props": "children, label?",
|
|
203
|
+
"insteadOf": "hand-drawn dividers and section labels inside a dialog body"
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"name": "CommandPalette",
|
|
207
|
+
"dir": "command-palette",
|
|
208
|
+
"import": "@poodle64/ui/command-palette",
|
|
209
|
+
"props": "nav, open, onNavigate?",
|
|
210
|
+
"insteadOf": "a bespoke ⌘K command menu wired to raw Command.*"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"name": "InfoTip",
|
|
214
|
+
"dir": "info-tip",
|
|
215
|
+
"import": "@poodle64/ui/info-tip",
|
|
216
|
+
"props": "text, side?, children?",
|
|
217
|
+
"insteadOf": "a standing explainer banner, or a raw Tooltip you wire per use"
|
|
218
|
+
}
|
|
219
|
+
]
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"key": "empty-loading-error",
|
|
223
|
+
"title": "Empty, loading, or failed",
|
|
224
|
+
"description": "A surface with nothing to show yet, still loading, or that failed to load — the three non-happy states every data view needs.",
|
|
225
|
+
"components": [
|
|
226
|
+
{
|
|
227
|
+
"name": "EmptyState",
|
|
228
|
+
"dir": "empty-state",
|
|
229
|
+
"import": "@poodle64/ui/empty-state",
|
|
230
|
+
"props": "title, icon?, description?, action?",
|
|
231
|
+
"insteadOf": "a hand-centred 'Nothing here' message"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"name": "LoadingState",
|
|
235
|
+
"dir": "loading-state",
|
|
236
|
+
"import": "@poodle64/ui/loading-state",
|
|
237
|
+
"props": "message?",
|
|
238
|
+
"insteadOf": "a bare spinner or 'Loading…' you place by hand"
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"name": "ErrorState",
|
|
242
|
+
"dir": "error-state",
|
|
243
|
+
"import": "@poodle64/ui/error-state",
|
|
244
|
+
"props": "message, action?",
|
|
245
|
+
"insteadOf": "a hand-built error message with a retry button"
|
|
246
|
+
}
|
|
247
|
+
]
|
|
248
|
+
}
|
|
249
|
+
],
|
|
250
|
+
"primitives": [
|
|
251
|
+
{
|
|
252
|
+
"dir": "alert",
|
|
253
|
+
"import": "@poodle64/ui/alert"
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
"dir": "alert-dialog",
|
|
257
|
+
"import": "@poodle64/ui/alert-dialog"
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"dir": "avatar",
|
|
261
|
+
"import": "@poodle64/ui/avatar"
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"dir": "badge",
|
|
265
|
+
"import": "@poodle64/ui/badge"
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"dir": "button",
|
|
269
|
+
"import": "@poodle64/ui/button"
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"dir": "card",
|
|
273
|
+
"import": "@poodle64/ui/card"
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"dir": "checkbox",
|
|
277
|
+
"import": "@poodle64/ui/checkbox"
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"dir": "command",
|
|
281
|
+
"import": "@poodle64/ui/command"
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"dir": "data-table",
|
|
285
|
+
"import": "@poodle64/ui/data-table"
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"dir": "dialog",
|
|
289
|
+
"import": "@poodle64/ui/dialog"
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"dir": "dropdown-menu",
|
|
293
|
+
"import": "@poodle64/ui/dropdown-menu"
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"dir": "input",
|
|
297
|
+
"import": "@poodle64/ui/input"
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"dir": "input-group",
|
|
301
|
+
"import": "@poodle64/ui/input-group"
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
"dir": "label",
|
|
305
|
+
"import": "@poodle64/ui/label"
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
"dir": "password-input",
|
|
309
|
+
"import": "@poodle64/ui/password-input"
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"dir": "popover",
|
|
313
|
+
"import": "@poodle64/ui/popover"
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
"dir": "progress",
|
|
317
|
+
"import": "@poodle64/ui/progress"
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"dir": "select",
|
|
321
|
+
"import": "@poodle64/ui/select"
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
"dir": "separator",
|
|
325
|
+
"import": "@poodle64/ui/separator"
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"dir": "skeleton",
|
|
329
|
+
"import": "@poodle64/ui/skeleton"
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
"dir": "sonner",
|
|
333
|
+
"import": "@poodle64/ui/sonner"
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
"dir": "switch",
|
|
337
|
+
"import": "@poodle64/ui/switch"
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
"dir": "table",
|
|
341
|
+
"import": "@poodle64/ui/table"
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
"dir": "tabs",
|
|
345
|
+
"import": "@poodle64/ui/tabs"
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
"dir": "textarea",
|
|
349
|
+
"import": "@poodle64/ui/textarea"
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
"dir": "tooltip",
|
|
353
|
+
"import": "@poodle64/ui/tooltip"
|
|
354
|
+
}
|
|
355
|
+
]
|
|
356
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# @poodle64/ui — situation → component map
|
|
2
|
+
|
|
3
|
+
<!-- GENERATED by scripts/generate-registry.mjs from scripts/situations.json + package source. DO NOT EDIT. -->
|
|
4
|
+
Generated from `@poodle64/ui@2026.8.8`. 49 components, 12 situations.
|
|
5
|
+
|
|
6
|
+
**Read this before writing a `<div>`.** Find the SITUATION you are in below, then compose the component named for it — do not hand-build it from raw `Card` or utility classes. Import is `import { Name } from '<import path>'`. Props marked `?` are optional. This map is the retrieval step the [`frontend-design` skill] makes mandatory; the [CHI 2026 study] measured composing-from-a-registry at 95% design-system compliance against 71% for writing the CSS from a prose style guide.
|
|
7
|
+
|
|
8
|
+
[`frontend-design` skill]: the household rule that loads before any UI code.
|
|
9
|
+
[CHI 2026 study]: 10.1145/3772363.3798616
|
|
10
|
+
|
|
11
|
+
## A single labelled figure
|
|
12
|
+
|
|
13
|
+
_One headline metric that earns a tile — a figure with a label, an optional unit, and the state of the thing it measures._
|
|
14
|
+
|
|
15
|
+
| Component | Import | Key props | Reach for it instead of |
|
|
16
|
+
| --- | --- | --- | --- |
|
|
17
|
+
| `StatCard` | `@poodle64/ui/stat-card` | `label, value, unit?, sub?, status?, valueTone?, icon?` | a Card you hand-build with a label over a big number |
|
|
18
|
+
|
|
19
|
+
## Several bare figures together
|
|
20
|
+
|
|
21
|
+
_A block of plain figures read at a glance — an 'at a glance' strip — where each number is too small to earn its own StatCard._
|
|
22
|
+
|
|
23
|
+
| Component | Import | Key props | Reach for it instead of |
|
|
24
|
+
| --- | --- | --- | --- |
|
|
25
|
+
| `StatList` | `@poodle64/ui/stat-list` | `items, title?, info?` | a hand-built <dl> or a stack of label/value <div>s |
|
|
26
|
+
|
|
27
|
+
## Comparing magnitudes across rows
|
|
28
|
+
|
|
29
|
+
_A small ranked set of labelled bars — a per-lane usage table, a token-burn chart — where a full StatCard per row would be too heavy._
|
|
30
|
+
|
|
31
|
+
| Component | Import | Key props | Reach for it instead of |
|
|
32
|
+
| --- | --- | --- | --- |
|
|
33
|
+
| `BarRow` | `@poodle64/ui/bar-row` | `label, value, pct, color?, labelWidth?` | a <div> with an inline width:%% bar you style by hand |
|
|
34
|
+
|
|
35
|
+
## A share of a bounded whole
|
|
36
|
+
|
|
37
|
+
_A part of a fixed total — a percentage, a capacity, a rate-limit window — read as one 0–100 figure._
|
|
38
|
+
|
|
39
|
+
| Component | Import | Key props | Reach for it instead of |
|
|
40
|
+
| --- | --- | --- | --- |
|
|
41
|
+
| `ArcGauge` | `@poodle64/ui/arc-gauge` | `pct, tone?, size?, showLabel?, label?` | a hand-drawn SVG ring, or printing a bare "72%" |
|
|
42
|
+
|
|
43
|
+
## A compact trend
|
|
44
|
+
|
|
45
|
+
_An inline time series in a row or card — a trend the eye reads at a glance, not a full Tier-1 chart._
|
|
46
|
+
|
|
47
|
+
| Component | Import | Key props | Reach for it instead of |
|
|
48
|
+
| --- | --- | --- | --- |
|
|
49
|
+
| `Sparkline` | `@poodle64/ui/sparkline` | `series, width, height, pad?` | a hand-built SVG polyline, or reaching for a charting library for a thumbnail |
|
|
50
|
+
|
|
51
|
+
## The state of a thing
|
|
52
|
+
|
|
53
|
+
_The health or status of something. One state reads as a chip; several independent states read as a dot strip._
|
|
54
|
+
|
|
55
|
+
| Component | Import | Key props | Reach for it instead of |
|
|
56
|
+
| --- | --- | --- | --- |
|
|
57
|
+
| `StatusBadge` | `@poodle64/ui/status-badge` | `status, label, pulse?` | a coloured <span> pill you tint by hand |
|
|
58
|
+
| `Scorecard` | `@poodle64/ui/scorecard` | `scores` | a hand-built row of coloured dots for several on/off/warn checks |
|
|
59
|
+
|
|
60
|
+
## The detail of one entity
|
|
61
|
+
|
|
62
|
+
_The surface for a single selected record — an eyebrow, a title, its status, and a close affordance over the body._
|
|
63
|
+
|
|
64
|
+
| Component | Import | Key props | Reach for it instead of |
|
|
65
|
+
| --- | --- | --- | --- |
|
|
66
|
+
| `DetailPanel` | `@poodle64/ui/detail-panel` | `title, eyebrow?, status?, statusLabel?, onClose?, children` | a Card you hand-build with an eyebrow, a title row and a close button |
|
|
67
|
+
|
|
68
|
+
## A catalogue of like things
|
|
69
|
+
|
|
70
|
+
_An index of many peer items — a responsive tile wall, or a sortable/filterable table of records._
|
|
71
|
+
|
|
72
|
+
| Component | Import | Key props | Reach for it instead of |
|
|
73
|
+
| --- | --- | --- | --- |
|
|
74
|
+
| `TileGrid` | `@poodle64/ui/tile-grid` | `children, min?, gap?, tag?` | a grid with fixed sm:grid-cols-* breakpoints you maintain per page |
|
|
75
|
+
| `DataTableTanstack` | `@poodle64/ui/data-table-tanstack` | `table, selectable?, selectedId?, onSelect?, emptyMessage?` | a hand-built <table>, or the raw Table primitive wired to TanStack by hand |
|
|
76
|
+
| `DataTableToolbar` | `@poodle64/ui/data-table-toolbar` | `searchValue, onSearch, searchPlaceholder?, chipGroups?, trailing?` | a hand-built search + filter-chip bar above a table |
|
|
77
|
+
|
|
78
|
+
## A titled section of a route
|
|
79
|
+
|
|
80
|
+
_The generic titled card every route reaches for — an optional header with icon, subtitle and actions over a body. The default answer to 'I need a card here'._
|
|
81
|
+
|
|
82
|
+
| Component | Import | Key props | Reach for it instead of |
|
|
83
|
+
| --- | --- | --- | --- |
|
|
84
|
+
| `Panel` | `@poodle64/ui/panel` | `children, title?, subtitle?, icon?, action?, pad?` | raw Card + CardHeader + CardTitle assembled by hand on every route |
|
|
85
|
+
|
|
86
|
+
## The frame every route shares
|
|
87
|
+
|
|
88
|
+
_The standing chrome — the app shell and its nav, the one page-title treatment, the persistent right-hand context column._
|
|
89
|
+
|
|
90
|
+
| Component | Import | Key props | Reach for it instead of |
|
|
91
|
+
| --- | --- | --- | --- |
|
|
92
|
+
| `AppShell` | `@poodle64/ui/app-shell` | `nav, currentPath, brandTitle?, actions?, context?, children` | a bespoke nav rail + header layout per app |
|
|
93
|
+
| `PageHeader` | `@poodle64/ui/page-header` | `title?, eyebrow?, breadcrumbs?, subtitle?, info?, actions?` | a hand-written <h1> and title bar (the drift gate fails this) |
|
|
94
|
+
| `ContextColumn` | `@poodle64/ui/context-column` | `stats, statsTitle?, statsInfo?, detail?, ariaLabel?` | a hand-built right-hand <aside> with a stat card and a detail pane |
|
|
95
|
+
|
|
96
|
+
## A dialog or overlay
|
|
97
|
+
|
|
98
|
+
_A modal task and the pieces around it — the dialog frame, a section within its body, a ⌘K palette, an inline (i) hint._
|
|
99
|
+
|
|
100
|
+
| Component | Import | Key props | Reach for it instead of |
|
|
101
|
+
| --- | --- | --- | --- |
|
|
102
|
+
| `AppDialog` | `@poodle64/ui/app-dialog` | `title, open, onOpenChange?, size?, children, footer?` | raw Dialog.* parts assembled into a frame by hand |
|
|
103
|
+
| `DialogSection` | `@poodle64/ui/dialog-section` | `children, label?` | hand-drawn dividers and section labels inside a dialog body |
|
|
104
|
+
| `CommandPalette` | `@poodle64/ui/command-palette` | `nav, open, onNavigate?` | a bespoke ⌘K command menu wired to raw Command.* |
|
|
105
|
+
| `InfoTip` | `@poodle64/ui/info-tip` | `text, side?, children?` | a standing explainer banner, or a raw Tooltip you wire per use |
|
|
106
|
+
|
|
107
|
+
## Empty, loading, or failed
|
|
108
|
+
|
|
109
|
+
_A surface with nothing to show yet, still loading, or that failed to load — the three non-happy states every data view needs._
|
|
110
|
+
|
|
111
|
+
| Component | Import | Key props | Reach for it instead of |
|
|
112
|
+
| --- | --- | --- | --- |
|
|
113
|
+
| `EmptyState` | `@poodle64/ui/empty-state` | `title, icon?, description?, action?` | a hand-centred 'Nothing here' message |
|
|
114
|
+
| `LoadingState` | `@poodle64/ui/loading-state` | `message?` | a bare spinner or 'Loading…' you place by hand |
|
|
115
|
+
| `ErrorState` | `@poodle64/ui/error-state` | `message, action?` | a hand-built error message with a retry button |
|
|
116
|
+
|
|
117
|
+
## Primitives you already know
|
|
118
|
+
|
|
119
|
+
_Standard shadcn-svelte / bits-ui primitives — reach for them the same way; no situation lookup needed. Import each from its path below._
|
|
120
|
+
|
|
121
|
+
`@poodle64/ui/alert` · `@poodle64/ui/alert-dialog` · `@poodle64/ui/avatar` · `@poodle64/ui/badge` · `@poodle64/ui/button` · `@poodle64/ui/card` · `@poodle64/ui/checkbox` · `@poodle64/ui/command` · `@poodle64/ui/data-table` · `@poodle64/ui/dialog` · `@poodle64/ui/dropdown-menu` · `@poodle64/ui/input` · `@poodle64/ui/input-group` · `@poodle64/ui/label` · `@poodle64/ui/password-input` · `@poodle64/ui/popover` · `@poodle64/ui/progress` · `@poodle64/ui/select` · `@poodle64/ui/separator` · `@poodle64/ui/skeleton` · `@poodle64/ui/sonner` · `@poodle64/ui/switch` · `@poodle64/ui/table` · `@poodle64/ui/tabs` · `@poodle64/ui/textarea` · `@poodle64/ui/tooltip`
|
|
122
|
+
|