@marianmeres/stuic 3.173.0 → 3.175.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/AGENTS.md +19 -4
- package/README.md +7 -3
- package/dist/components/Button/README.md +11 -10
- package/dist/components/ButtonGroupRadio/README.md +52 -23
- package/dist/components/ButtonGroupRadio/index.css +6 -2
- package/dist/components/DescriptionList/DescriptionList.svelte +270 -0
- package/dist/components/DescriptionList/DescriptionList.svelte.d.ts +127 -0
- package/dist/components/DescriptionList/README.md +254 -0
- package/dist/components/DescriptionList/index.css +264 -0
- package/dist/components/DescriptionList/index.d.ts +1 -0
- package/dist/components/DescriptionList/index.js +1 -0
- package/dist/components/PricingTable/PricingTable.svelte +8 -14
- package/dist/components/PricingTable/README.md +29 -6
- package/dist/components/PricingTable/index.css +54 -0
- package/dist/index.css +15 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/docs/conventions.md +27 -7
- package/docs/domains/components.md +51 -1
- package/docs/domains/theming.md +57 -13
- package/package.json +1 -1
package/dist/index.css
CHANGED
|
@@ -29,6 +29,20 @@ In practice:
|
|
|
29
29
|
These tokens provide a single point of control for cross-component properties.
|
|
30
30
|
Override globally: :root { --stuic-radius: 0; }
|
|
31
31
|
Override per-component: --stuic-button-radius: 9999px; (takes precedence)
|
|
32
|
+
|
|
33
|
+
NOTE on the mirrored names. The tokens below are TIER tokens, named
|
|
34
|
+
--stuic-{property}-{tier}, and they ARE declared here. Component override tokens
|
|
35
|
+
are the transposition, --stuic-{component}-{property}, and are NEVER declared --
|
|
36
|
+
they exist only as the first argument of a var() fallback at the usage site:
|
|
37
|
+
|
|
38
|
+
border-radius: var(--stuic-button-radius, var(--stuic-radius-button));
|
|
39
|
+
^ component token (3) ^ tier token (2, declared here)
|
|
40
|
+
|
|
41
|
+
So --stuic-radius-button (tier) applies to Button, SplitButton and ButtonGroupRadio,
|
|
42
|
+
while --stuic-button-radius (component) applies to Button alone. Same relationship
|
|
43
|
+
between --stuic-border-width-button and --stuic-button-border-width. "button" is the
|
|
44
|
+
only tier name that is also a component name, hence the only confusable pair -- do
|
|
45
|
+
not "fix" one into the other.
|
|
32
46
|
============================================================================ */
|
|
33
47
|
:root {
|
|
34
48
|
/* Radius: three tiers */
|
|
@@ -81,6 +95,7 @@ In practice:
|
|
|
81
95
|
@import "./components/CopyButton/index.css";
|
|
82
96
|
@import "./components/CronInput/index.css";
|
|
83
97
|
@import "./components/DataTable/index.css";
|
|
98
|
+
@import "./components/DescriptionList/index.css";
|
|
84
99
|
@import "./components/DismissibleMessage/index.css";
|
|
85
100
|
@import "./components/DropdownMenu/index.css";
|
|
86
101
|
@import "./components/EmailVerifyForm/index.css";
|
package/dist/index.d.ts
CHANGED
|
@@ -46,6 +46,7 @@ export * from "./components/ContextMenu/index.js";
|
|
|
46
46
|
export * from "./components/CopyButton/index.js";
|
|
47
47
|
export * from "./components/CronInput/index.js";
|
|
48
48
|
export * from "./components/DataTable/index.js";
|
|
49
|
+
export * from "./components/DescriptionList/index.js";
|
|
49
50
|
export * from "./components/DismissibleMessage/index.js";
|
|
50
51
|
export * from "./components/Drawer/index.js";
|
|
51
52
|
export * from "./components/DropdownMenu/index.js";
|
package/dist/index.js
CHANGED
|
@@ -52,6 +52,7 @@ export * from "./components/ContextMenu/index.js";
|
|
|
52
52
|
export * from "./components/CopyButton/index.js";
|
|
53
53
|
export * from "./components/CronInput/index.js";
|
|
54
54
|
export * from "./components/DataTable/index.js";
|
|
55
|
+
export * from "./components/DescriptionList/index.js";
|
|
55
56
|
export * from "./components/DismissibleMessage/index.js";
|
|
56
57
|
export * from "./components/Drawer/index.js";
|
|
57
58
|
export * from "./components/DropdownMenu/index.js";
|
package/docs/conventions.md
CHANGED
|
@@ -43,12 +43,14 @@ Global tokens in `src/lib/index.css` that control cross-component visual propert
|
|
|
43
43
|
/* Brutalist example — 7 lines to transform everything */
|
|
44
44
|
:root {
|
|
45
45
|
--stuic-radius: 0;
|
|
46
|
+
--stuic-radius-button: 0;
|
|
46
47
|
--stuic-radius-container: 0;
|
|
47
48
|
--stuic-shadow: none;
|
|
48
49
|
--stuic-shadow-hover: none;
|
|
49
50
|
--stuic-shadow-overlay: none;
|
|
50
51
|
--stuic-shadow-dialog: none;
|
|
51
52
|
--stuic-border-width: 0;
|
|
53
|
+
--stuic-border-width-button: 0;
|
|
52
54
|
}
|
|
53
55
|
```
|
|
54
56
|
|
|
@@ -79,16 +81,34 @@ Component CSS must reference shared tokens as **fallbacks at usage sites**, not
|
|
|
79
81
|
|
|
80
82
|
Per-component overrides (`--stuic-widget-radius: 0`) still take precedence over the shared fallback.
|
|
81
83
|
|
|
82
|
-
### Element vs Container
|
|
84
|
+
### Element vs Button vs Container
|
|
83
85
|
|
|
84
|
-
|
|
86
|
+
Three tiers of radius for natural visual hierarchy:
|
|
85
87
|
|
|
86
|
-
| Tier | Token | Default | Use for
|
|
87
|
-
| --------- | -------------------------- | ------------------ |
|
|
88
|
-
| Element | `--stuic-radius` | `var(--radius-md)` |
|
|
89
|
-
|
|
|
88
|
+
| Tier | Token | Default | Use for |
|
|
89
|
+
| --------- | -------------------------- | ------------------ | --------------------------------------------------- |
|
|
90
|
+
| Element | `--stuic-radius` | `var(--radius-md)` | Inputs, badges, list items, checkboxes, tabs |
|
|
91
|
+
| Button | `--stuic-radius-button` | `var(--radius-md)` | Buttons, split buttons, button groups |
|
|
92
|
+
| Container | `--stuic-radius-container` | `var(--radius-lg)` | Cards, modals, dropdowns, notifications, accordions |
|
|
90
93
|
|
|
91
|
-
**Rule of thumb:** if it wraps other interactive elements, it's a container.
|
|
94
|
+
**Rule of thumb:** if it wraps other interactive elements, it's a container. Buttons get
|
|
95
|
+
their own tier so a flat-input theme can still have pill buttons (and vice versa);
|
|
96
|
+
`--stuic-border-width-button` splits out the same way.
|
|
97
|
+
|
|
98
|
+
### Tier tokens vs component tokens
|
|
99
|
+
|
|
100
|
+
The two layers use mirrored names, which is easy to misread for the button tier:
|
|
101
|
+
|
|
102
|
+
| Name | Layer | Declared? | Scope |
|
|
103
|
+
| ----------------------------- | ------------------- | --------------------- | ----------------------------- |
|
|
104
|
+
| `--stuic-radius-button` | shared tier (2) | yes, in `index.css` | every button-family component |
|
|
105
|
+
| `--stuic-button-radius` | component token (3) | no, fallback arg only | `Button` only |
|
|
106
|
+
| `--stuic-border-width-button` | shared tier (2) | yes, in `index.css` | every button-family component |
|
|
107
|
+
| `--stuic-button-border-width` | component token (3) | no, fallback arg only | `Button` only |
|
|
108
|
+
|
|
109
|
+
Read it as `--stuic-{property}-{tier}` for tier tokens and `--stuic-{component}-{property}`
|
|
110
|
+
for component tokens. `button` is the only tier name that is also a component name, so it
|
|
111
|
+
is the only pair that reads as a transposition.
|
|
92
112
|
|
|
93
113
|
---
|
|
94
114
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
79 Svelte 5 component directories with consistent API patterns. All use runes-based reactivity.
|
|
6
6
|
|
|
7
7
|
## Component Categories
|
|
8
8
|
|
|
@@ -105,6 +105,7 @@
|
|
|
105
105
|
| Thc | Flexible renderer for text, HTML, components, or snippets |
|
|
106
106
|
| Card | Flexible card with image, title, footer; vertical/horizontal layout |
|
|
107
107
|
| Stat | KPI/stat card: label + value + delta with trend arrow and semantic coloring |
|
|
108
|
+
| DescriptionList | Term/value list (`<dl>`): stacked or two-column by container query, hairlines, truncation, totals |
|
|
108
109
|
| Timeline | Vertical event list on a rail: dot/icon/custom markers, inline or opposite time, alternate layout |
|
|
109
110
|
| TrendChart | Svelte wrapper for `@marianmeres/trend-chart` (subpath-only: `@marianmeres/stuic/trend-chart`) |
|
|
110
111
|
| Tree | Hierarchical tree view with keyboard nav and drag-and-drop |
|
|
@@ -970,6 +971,55 @@ Prefix: `--stuic-copy-button-*` (the surface themes via `--stuic-button-*`)
|
|
|
970
971
|
|
|
971
972
|
---
|
|
972
973
|
|
|
974
|
+
## DescriptionList
|
|
975
|
+
|
|
976
|
+
The term-and-value list — the read-only block on every detail page, drawer and back-office panel. Renders `<dl>` › `<div>` per pair › `<dt>` + `<dd>` (plus an optional second `<dd>` qualifying the value), which is what the spec provides for grouping a term with its details and what lets each row be a grid without subgrid. No ARIA is added: a `<dl>` already has list semantics. Two equal ways to feed it — `items` for flat lists, `children` for markup-heavy ones — because the CSS selects **structurally** (`dl > div > dt`, `> div > dd + dd`), so a hand-written row renders identically to a generated one. Not an editor (that is `FieldKeyValues`) and not a table.
|
|
977
|
+
|
|
978
|
+
### Exports
|
|
979
|
+
|
|
980
|
+
| Export | Kind | Description |
|
|
981
|
+
| ---------------------------- | --------- | -------------------------------------------------------------------------------------------------------- |
|
|
982
|
+
| `DescriptionList` | component | Main component |
|
|
983
|
+
| `DescriptionListProps` | type | Props type |
|
|
984
|
+
| `DescriptionListItem` | type | `{ key?, label, value?, description?, href?, title?, labelLang?, valueLang?, emphasis?, wrap?, class* }` |
|
|
985
|
+
| `DescriptionListLayout` | type | `"auto" \| "stacked" \| "columns"` |
|
|
986
|
+
| `DescriptionListColumnsFrom` | type | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` (20 / 24 / 28 / 32 / 36rem) |
|
|
987
|
+
| `DescriptionListDivide` | type | `"none" \| "inside" \| "outside"` |
|
|
988
|
+
| `DescriptionListWrap` | type | `"anywhere" \| "truncate" \| "normal"` |
|
|
989
|
+
| `DescriptionListValueAlign` | type | `"start" \| "end"` |
|
|
990
|
+
| `DescriptionListSnippetArg` | type | `{ item, index }` — argument of all three snippets |
|
|
991
|
+
|
|
992
|
+
### Key Props
|
|
993
|
+
|
|
994
|
+
| Prop | Type | Default | Description |
|
|
995
|
+
| ------------- | -------------------------------------- | ------------ | ----------------------------------------------------------------------------------- |
|
|
996
|
+
| `items` | `DescriptionListItem[]` | — | The rows, in order (label/value/description are THC) |
|
|
997
|
+
| `children` | `Snippet` | — | Rendered inside the `<dl>` _instead of_ `items` |
|
|
998
|
+
| `layout` | `"auto" \| "stacked" \| "columns"` | `"auto"` | Label over value, beside it, or the former until the list is `columnsFrom` wide |
|
|
999
|
+
| `columnsFrom` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"sm"` | The **list's own** width at which `"auto"` flips. Dropped unless `layout="auto"` |
|
|
1000
|
+
| `divide` | `"none" \| "inside" \| "outside"` | `"inside"` | n−1 rules (list in a box), n+1 (list loose on a page), or none |
|
|
1001
|
+
| `wrap` | `"anywhere" \| "truncate" \| "normal"` | `"anywhere"` | Long-value behavior; per-row override via `item.wrap` |
|
|
1002
|
+
| `valueAlign` | `"start" \| "end"` | `"start"` | `"end"` is the totals shape (pair with `--stuic-description-list-label-width: 1fr`) |
|
|
1003
|
+
| `emptyValue` | `THC` | `"—"` | Used when `value` is `undefined`/`null`/`""` — `0` is a value, not empty |
|
|
1004
|
+
|
|
1005
|
+
Snippets (all receive `{ item, index }`): `renderLabel`, `renderValue`, `renderItem` (the row `<div>` stays — it is what the grid is on). Class slots: `class`, `classItem`, `classLabel`, `classValue`, `classDescription`, each also available per item. Empty `items` with no `children` renders **nothing**, not an empty `<dl>`.
|
|
1006
|
+
|
|
1007
|
+
### Why a container query
|
|
1008
|
+
|
|
1009
|
+
`layout="auto"` makes the `<dl>` a named inline-size container (`stuic-description-list`) and flips its **rows** to a two-column grid at `columnsFrom` — an element cannot query itself. The viewport answers a different question: a 200px-wide list inside a 1400px page must stay stacked, and `sm:` would have flipped it. The breakpoint is a prop on a fixed scale (Tailwind's `@xs`…`@xl`) and not a token because `@container (min-width: var(--x))` is not valid CSS — size queries take literals. Side effect worth knowing: `container-type: inline-size` gives the list inline-axis containment, so its min-content contribution to a flex parent is zero (the list can sit beside a fixed-width element and shrink into what is left; `min-w-0` is already there in the static layouts too).
|
|
1010
|
+
|
|
1011
|
+
### Row-level contract (works in both forms)
|
|
1012
|
+
|
|
1013
|
+
`data-wrap="anywhere|truncate|normal"` and `data-emphasis` on a row `<div>` are honoured by the same selectors the data form uses, so `children` rows opt into per-row wrapping and the _Total_ look without a prop. Under `wrap="truncate"` a plain-string value auto-fills the `<dd>`'s `title` (a clipped value must stay reachable); pass `item.title` for html/component/snippet values.
|
|
1014
|
+
|
|
1015
|
+
### CSS Tokens
|
|
1016
|
+
|
|
1017
|
+
Prefix: `--stuic-description-list-*`
|
|
1018
|
+
|
|
1019
|
+
`label-width` (not declared — fallback `minmax(7rem, 10rem)` at the usage site), `gap-x`, `gap-y`, `item-padding-y`, `rule-color`, `rule-width`, `label-font-size`, `label-font-weight`, `label-text`, `value-text`, `description-font-size`, `description-text`, `label-text-emphasis`, `value-font-weight-emphasis`
|
|
1020
|
+
|
|
1021
|
+
---
|
|
1022
|
+
|
|
973
1023
|
## EmptyState
|
|
974
1024
|
|
|
975
1025
|
Icon + title + description + CTA placeholder for empty lists, tables, and search results. Centered, non-interactive; the CTA area is a snippet filled with consumer `Button`s/links. Pairs naturally with `DataTable` ("no rows") and search UIs ("no results").
|
package/docs/domains/theming.md
CHANGED
|
@@ -186,39 +186,55 @@ const css = generateThemeCss(custom, "stuic-");
|
|
|
186
186
|
|
|
187
187
|
Global tokens defined in `src/lib/index.css` that control cross-component visual properties. Override these to change the entire library's visual character:
|
|
188
188
|
|
|
189
|
-
| Token
|
|
190
|
-
|
|
|
191
|
-
| `--stuic-radius`
|
|
192
|
-
| `--stuic-radius-
|
|
193
|
-
| `--stuic-
|
|
194
|
-
| `--stuic-shadow
|
|
195
|
-
| `--stuic-shadow-
|
|
196
|
-
| `--stuic-shadow-
|
|
197
|
-
| `--stuic-
|
|
198
|
-
| `--stuic-
|
|
189
|
+
| Token | Default | Purpose |
|
|
190
|
+
| ----------------------------- | ------------------ | ----------------------------------------------------------- |
|
|
191
|
+
| `--stuic-radius` | `var(--radius-md)` | Element-level radius (inputs, badges, list items) |
|
|
192
|
+
| `--stuic-radius-button` | `var(--radius-md)` | Button-level radius (buttons, split buttons, button groups) |
|
|
193
|
+
| `--stuic-radius-container` | `var(--radius-lg)` | Container-level radius (cards, modals, dropdowns) |
|
|
194
|
+
| `--stuic-shadow` | `var(--shadow-sm)` | Default resting shadow |
|
|
195
|
+
| `--stuic-shadow-hover` | `var(--shadow-md)` | Hover/elevated shadow |
|
|
196
|
+
| `--stuic-shadow-overlay` | `var(--shadow-lg)` | Overlays (dropdowns, notifications) |
|
|
197
|
+
| `--stuic-shadow-dialog` | `var(--shadow-xl)` | Dialogs/modals |
|
|
198
|
+
| `--stuic-border-width` | `1px` | Default border width |
|
|
199
|
+
| `--stuic-border-width-button` | `1px` | Button border width (independent from general elements) |
|
|
200
|
+
| `--stuic-transition` | `150ms` | Default transition duration |
|
|
201
|
+
|
|
202
|
+
Radius and border-width come in **three tiers** — elements, buttons, containers — so a
|
|
203
|
+
theme can flatten inputs while keeping pill buttons, or vice versa. See
|
|
204
|
+
[Conventions: Element vs Button vs Container](../conventions.md#element-vs-button-vs-container).
|
|
199
205
|
|
|
200
206
|
Example — brutalist style in 7 lines:
|
|
201
207
|
|
|
202
208
|
```css
|
|
203
209
|
:root {
|
|
204
210
|
--stuic-radius: 0;
|
|
211
|
+
--stuic-radius-button: 0;
|
|
205
212
|
--stuic-radius-container: 0;
|
|
206
213
|
--stuic-shadow: none;
|
|
207
214
|
--stuic-shadow-hover: none;
|
|
208
215
|
--stuic-shadow-overlay: none;
|
|
209
216
|
--stuic-shadow-dialog: none;
|
|
210
217
|
--stuic-border-width: 0;
|
|
218
|
+
--stuic-border-width-button: 0;
|
|
211
219
|
}
|
|
212
220
|
```
|
|
213
221
|
|
|
214
|
-
Components reference these via the fallback pattern (not `:root` declarations)
|
|
222
|
+
Components reference these via the fallback pattern (not `:root` declarations) — the
|
|
223
|
+
per-component token first, the shared tier token as its fallback:
|
|
215
224
|
|
|
216
225
|
```css
|
|
217
226
|
.stuic-button {
|
|
218
|
-
border-radius: var(--stuic-button-radius, var(--stuic-radius));
|
|
227
|
+
border-radius: var(--stuic-button-radius, var(--stuic-radius-button));
|
|
228
|
+
/* ^ component token ^ shared tier token */
|
|
219
229
|
}
|
|
220
230
|
```
|
|
221
231
|
|
|
232
|
+
> **Note the mirrored names.** `--stuic-radius-button` is the shared tier token (declared
|
|
233
|
+
> in `src/lib/index.css`, applies to every button-family component);
|
|
234
|
+
> `--stuic-button-radius` is the `Button` component's own override token (never declared —
|
|
235
|
+
> it only ever appears as the first argument of a `var()` fallback). Same for
|
|
236
|
+
> `--stuic-border-width-button` vs `--stuic-button-border-width`.
|
|
237
|
+
|
|
222
238
|
---
|
|
223
239
|
|
|
224
240
|
## Component Tokens
|
|
@@ -239,7 +255,7 @@ Override per-component tokens globally:
|
|
|
239
255
|
|
|
240
256
|
```css
|
|
241
257
|
:root {
|
|
242
|
-
--stuic-button-radius: 9999px; /* Pill buttons — overrides
|
|
258
|
+
--stuic-button-radius: 9999px; /* Pill buttons — overrides --stuic-radius-button */
|
|
243
259
|
}
|
|
244
260
|
```
|
|
245
261
|
|
|
@@ -251,6 +267,34 @@ Override locally:
|
|
|
251
267
|
|
|
252
268
|
Some token sets belong to a CSS-only preset rather than to a component — e.g. `--stuic-frame-*` (ratio-locked frame / letterbox). Those are consumer **inputs** that stuic never declares; see [CSS presets](./css-presets.md).
|
|
253
269
|
|
|
270
|
+
### Pitfall: never pin a nested component's tokens inline
|
|
271
|
+
|
|
272
|
+
When a component renders another stuic component internally and wants to restyle it, the
|
|
273
|
+
opinionated values must go in the outer component's `index.css`, behind its own
|
|
274
|
+
`--stuic-{outer}-{part}-*` tokens — never into the inner component's inline `style`
|
|
275
|
+
attribute:
|
|
276
|
+
|
|
277
|
+
```svelte
|
|
278
|
+
<!-- WRONG — an inline custom property outranks every :root declaration for that
|
|
279
|
+
element and its subtree, so no theme can reach the inner component -->
|
|
280
|
+
<ButtonGroupRadio style="--stuic-button-group-radius: 9999px;" />
|
|
281
|
+
|
|
282
|
+
<!-- RIGHT — the class carries the look, and `style` stays the caller's escape hatch -->
|
|
283
|
+
<ButtonGroupRadio class="stuic-pricing-table-toggle" style={styleToggle} />
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
```css
|
|
287
|
+
.stuic-pricing-table-toggle {
|
|
288
|
+
--stuic-button-group-radius: var(--stuic-pricing-table-toggle-radius, 9999px);
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
No specificity or `@layer` trick outranks an inline declaration, so the inline form makes
|
|
293
|
+
that part of the component permanently unthemeable. `PricingTable`'s billing toggle is the
|
|
294
|
+
worked example. Note the trade: whatever the outer component declares on the element is no
|
|
295
|
+
longer reachable through the _inner_ component's global token, so document the
|
|
296
|
+
`--stuic-{outer}-*` replacement in the outer component's README.
|
|
297
|
+
|
|
254
298
|
---
|
|
255
299
|
|
|
256
300
|
## Key Files
|