@marianmeres/stuic 3.173.0 → 3.174.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 +17 -2
- 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/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 +14 -0
- package/docs/conventions.md +27 -7
- package/docs/domains/theming.md +57 -13
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -101,12 +101,27 @@ Global tokens that control cross-component visual properties. Defined in `src/li
|
|
|
101
101
|
}
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
-
**Element vs Container classification:**
|
|
104
|
+
**Element vs Button vs Container classification:**
|
|
105
105
|
|
|
106
106
|
- **Element** (`--stuic-radius`): inputs, badges, list items, checkboxes, tabs — interactive controls
|
|
107
|
-
- **Button** (`--stuic-radius-button`): buttons, button groups — allows rounded buttons even with flat elements
|
|
107
|
+
- **Button** (`--stuic-radius-button`): buttons, split buttons, button groups — allows rounded buttons even with flat elements
|
|
108
108
|
- **Container** (`--stuic-radius-container`): cards, modals, dropdowns, notifications, accordions — content wrappers
|
|
109
109
|
|
|
110
|
+
**Tier tokens vs component tokens — the mirrored names.** Tier tokens (the table above) are
|
|
111
|
+
`--stuic-{property}-{tier}` and ARE declared in `src/lib/index.css`. Component tokens are the
|
|
112
|
+
transposition, `--stuic-{component}-{property}`, and are NEVER declared — they exist only as
|
|
113
|
+
the first argument of a `var()` fallback:
|
|
114
|
+
|
|
115
|
+
```css
|
|
116
|
+
border-radius: var(--stuic-button-radius, var(--stuic-radius-button));
|
|
117
|
+
/* ^ component token (3) ^ tier token (2) */
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
So `--stuic-radius-button` applies to Button, SplitButton and ButtonGroupRadio, while
|
|
121
|
+
`--stuic-button-radius` applies to Button alone. Same for `--stuic-border-width-button` vs
|
|
122
|
+
`--stuic-button-border-width`. `button` is the only tier name that is also a component name,
|
|
123
|
+
so it is the only confusable pair — do not "fix" one into the other.
|
|
124
|
+
|
|
110
125
|
---
|
|
111
126
|
|
|
112
127
|
## Before Making Changes
|
package/README.md
CHANGED
|
@@ -57,7 +57,7 @@ STUIC uses a 4-layer CSS variable token system:
|
|
|
57
57
|
```
|
|
58
58
|
Layer 1: Theme Tokens (--stuic-color-*)
|
|
59
59
|
↓
|
|
60
|
-
Layer 2: Structural Tokens (--stuic-radius, --stuic-
|
|
60
|
+
Layer 2: Structural Tokens (--stuic-radius, --stuic-radius-button, --stuic-shadow, ...)
|
|
61
61
|
↓ (used as fallback defaults)
|
|
62
62
|
Layer 3: Component Tokens (--stuic-button-radius, --stuic-input-accent, etc.)
|
|
63
63
|
↓ (Tailwind utility class references)
|
|
@@ -87,16 +87,20 @@ Override shared structural tokens to change the entire library's visual characte
|
|
|
87
87
|
/* Brutalist — sharp, flat, borderless */
|
|
88
88
|
:root {
|
|
89
89
|
--stuic-radius: 0;
|
|
90
|
+
--stuic-radius-button: 0;
|
|
90
91
|
--stuic-radius-container: 0;
|
|
91
92
|
--stuic-shadow: none;
|
|
92
93
|
--stuic-shadow-hover: none;
|
|
93
94
|
--stuic-shadow-overlay: none;
|
|
94
95
|
--stuic-shadow-dialog: none;
|
|
95
96
|
--stuic-border-width: 0;
|
|
97
|
+
--stuic-border-width-button: 0;
|
|
96
98
|
}
|
|
97
99
|
```
|
|
98
100
|
|
|
99
|
-
Available tokens: `--stuic-radius`, `--stuic-radius-container`, `--stuic-shadow`, `--stuic-shadow-hover`, `--stuic-shadow-overlay`, `--stuic-shadow-dialog`, `--stuic-border-width`, `--stuic-transition`.
|
|
101
|
+
Available tokens: `--stuic-radius`, `--stuic-radius-button`, `--stuic-radius-container`, `--stuic-shadow`, `--stuic-shadow-hover`, `--stuic-shadow-overlay`, `--stuic-shadow-dialog`, `--stuic-border-width`, `--stuic-border-width-button`, `--stuic-transition`.
|
|
102
|
+
|
|
103
|
+
Radius and border-width come in three tiers — elements, **buttons**, containers — so you can flatten inputs while keeping pill buttons, or the reverse.
|
|
100
104
|
|
|
101
105
|
### Per-Component Customization
|
|
102
106
|
|
|
@@ -104,7 +108,7 @@ Override specific component tokens:
|
|
|
104
108
|
|
|
105
109
|
```css
|
|
106
110
|
:root {
|
|
107
|
-
--stuic-button-radius: 9999px; /* Pill buttons — overrides the shared --stuic-radius */
|
|
111
|
+
--stuic-button-radius: 9999px; /* Pill buttons — overrides the shared --stuic-radius-button */
|
|
108
112
|
--stuic-switch-accent: #10b981; /* Green switches */
|
|
109
113
|
}
|
|
110
114
|
```
|
|
@@ -174,16 +174,17 @@ Notes:
|
|
|
174
174
|
|
|
175
175
|
### Component Tokens
|
|
176
176
|
|
|
177
|
-
| Variable | Default
|
|
178
|
-
| ------------------------------ |
|
|
179
|
-
| `--stuic-button-radius` | `--radius-
|
|
180
|
-
| `--stuic-button-
|
|
181
|
-
| `--stuic-button-font-
|
|
182
|
-
| `--stuic-button-
|
|
183
|
-
| `--stuic-button-
|
|
184
|
-
| `--stuic-button-ring-
|
|
185
|
-
| `--stuic-button-
|
|
186
|
-
| `--stuic-button-raised-
|
|
177
|
+
| Variable | Default | Description |
|
|
178
|
+
| ------------------------------ | ------------------------------ | ------------------- |
|
|
179
|
+
| `--stuic-button-radius` | `--stuic-radius-button` | Border radius |
|
|
180
|
+
| `--stuic-button-border-width` | `--stuic-border-width-button` | Border width |
|
|
181
|
+
| `--stuic-button-font-family` | `--font-sans` | Font family |
|
|
182
|
+
| `--stuic-button-font-weight` | `--font-weight-medium` | Font weight |
|
|
183
|
+
| `--stuic-button-transition` | `--stuic-transition` (`150ms`) | Transition duration |
|
|
184
|
+
| `--stuic-button-ring-width` | `3px` | Focus ring width |
|
|
185
|
+
| `--stuic-button-ring-color` | `--stuic-color-ring` | Focus ring color |
|
|
186
|
+
| `--stuic-button-raised-offset` | `2px` | 3D effect offset |
|
|
187
|
+
| `--stuic-button-raised-color` | `rgb(0 0 0 / 0.8)` | 3D shadow color |
|
|
187
188
|
|
|
188
189
|
### Size Tokens
|
|
189
190
|
|
|
@@ -129,34 +129,63 @@ disable the whole group instead, use the top-level `disabled` prop.
|
|
|
129
129
|
|
|
130
130
|
## CSS Variables
|
|
131
131
|
|
|
132
|
+
All tokens below are **declared** in the component's `:root`. That means a `:root` override
|
|
133
|
+
or a `style` prop override both work, but the `var(--token, <fallback>)` fallbacks visible in
|
|
134
|
+
`index.css` never fire — the defaults are the `:root` values listed here.
|
|
135
|
+
|
|
132
136
|
### Component Tokens
|
|
133
137
|
|
|
134
|
-
| Variable | Default | Description
|
|
135
|
-
| ---------------------------------------- | ------------------------- |
|
|
136
|
-
| `--stuic-button-group-radius` | `
|
|
137
|
-
| `--stuic-button-group-padding`
|
|
138
|
-
| `--stuic-button-group-
|
|
139
|
-
| `--stuic-button-group-
|
|
140
|
-
| `--stuic-button-group-
|
|
141
|
-
| `--stuic-button-group-ring-width` | `
|
|
142
|
-
| `--stuic-button-group-ring-color` | `var(--stuic-color-ring)` | Focus ring color
|
|
143
|
-
| `--stuic-button-group-button-padding-x` | `0.75rem` | Button horizontal padding
|
|
144
|
-
| `--stuic-button-group-button-padding-y` | `0.
|
|
145
|
-
| `--stuic-button-group-button-min-height` | `2.
|
|
138
|
+
| Variable | Default | Description |
|
|
139
|
+
| ---------------------------------------- | ------------------------- | ---------------------------------------------- |
|
|
140
|
+
| `--stuic-button-group-radius` | `9999px` | Border radius for container and buttons (pill) |
|
|
141
|
+
| `--stuic-button-group-padding-x` | `4px` | Container horizontal padding |
|
|
142
|
+
| `--stuic-button-group-padding-y` | `3px` | Container vertical padding |
|
|
143
|
+
| `--stuic-button-group-gap` | `0.25rem` | Gap between buttons |
|
|
144
|
+
| `--stuic-button-group-border-width` | `1px` | Container border width |
|
|
145
|
+
| `--stuic-button-group-ring-width` | `4px` | Focus ring width |
|
|
146
|
+
| `--stuic-button-group-ring-color` | `var(--stuic-color-ring)` | Focus ring color |
|
|
147
|
+
| `--stuic-button-group-button-padding-x` | `0.75rem` | Button horizontal padding |
|
|
148
|
+
| `--stuic-button-group-button-padding-y` | `0.375rem` | Button vertical padding |
|
|
149
|
+
| `--stuic-button-group-button-min-height` | `2.25rem` | Button min height (36px) |
|
|
150
|
+
| `--stuic-button-group-transition` | `var(--stuic-transition)` | Transition duration (not declared — fallback) |
|
|
151
|
+
|
|
152
|
+
`--stuic-button-group-transition` is the one exception: it is _not_ declared, so it resolves
|
|
153
|
+
through its usage-site fallback to `--stuic-transition`.
|
|
146
154
|
|
|
147
155
|
### Color Tokens
|
|
148
156
|
|
|
149
|
-
| Variable
|
|
150
|
-
|
|
|
151
|
-
| `--stuic-button-group-bg`
|
|
152
|
-
| `--stuic-button-group-text`
|
|
153
|
-
| `--stuic-button-group-border`
|
|
154
|
-
| `--stuic-button-group-
|
|
155
|
-
| `--stuic-button-group-button-
|
|
156
|
-
| `--stuic-button-group-button-
|
|
157
|
-
| `--stuic-button-group-button-bg-
|
|
158
|
-
| `--stuic-button-group-button-text-
|
|
159
|
-
| `--stuic-button-group-button-bg-active
|
|
157
|
+
| Variable | Default | Description |
|
|
158
|
+
| ----------------------------------------------- | ----------------------------------------- | -------------------------------- |
|
|
159
|
+
| `--stuic-button-group-bg` | `var(--stuic-color-muted)` | Container background |
|
|
160
|
+
| `--stuic-button-group-text` | `var(--stuic-color-muted-foreground)` | Container text color |
|
|
161
|
+
| `--stuic-button-group-border` | `var(--stuic-input-border)` | Container border color |
|
|
162
|
+
| `--stuic-button-group-border-focus` | `var(--stuic-color-primary)` | Container border on focus-within |
|
|
163
|
+
| `--stuic-button-group-button-bg` | `transparent` | Inactive button background |
|
|
164
|
+
| `--stuic-button-group-button-text` | `var(--stuic-color-muted-foreground)` | Inactive button text |
|
|
165
|
+
| `--stuic-button-group-button-bg-hover` | `transparent` | Inactive button hover background |
|
|
166
|
+
| `--stuic-button-group-button-text-hover` | `var(--stuic-color-foreground)` | Inactive button hover text |
|
|
167
|
+
| `--stuic-button-group-button-bg-active` | `var(--stuic-color-surface-1)` | Active button background |
|
|
168
|
+
| `--stuic-button-group-button-text-active` | `var(--stuic-color-surface-1-foreground)` | Active button text |
|
|
169
|
+
| `--stuic-button-group-button-bg-active-hover` | `var(--stuic-color-surface-1)` | Active button hover background |
|
|
170
|
+
| `--stuic-button-group-button-text-active-hover` | `var(--stuic-color-surface-1-foreground)` | Active button hover text |
|
|
171
|
+
|
|
172
|
+
### Size Variants
|
|
173
|
+
|
|
174
|
+
`size` sets `data-size` on the container, which re-declares a subset of the tokens above.
|
|
175
|
+
`md` is the `:root` default; `sm` and `lg` override these:
|
|
176
|
+
|
|
177
|
+
| Token | `sm` | `md` (default) | `lg` |
|
|
178
|
+
| ---------------------------------------- | ---------- | -------------- | ---------- |
|
|
179
|
+
| `--stuic-button-group-padding-x` | `3px` | `4px` | `8px` |
|
|
180
|
+
| `--stuic-button-group-padding-y` | `2px` | `3px` | `6px` |
|
|
181
|
+
| `--stuic-button-group-gap` | `0.125rem` | `0.25rem` | `0.375rem` |
|
|
182
|
+
| `--stuic-button-group-button-padding-x` | `0.5rem` | `0.75rem` | `1rem` |
|
|
183
|
+
| `--stuic-button-group-button-padding-y` | `0.375rem` | `0.375rem` | `0.625rem` |
|
|
184
|
+
| `--stuic-button-group-button-min-height` | `2.25rem` | `2.25rem` | `3rem` |
|
|
185
|
+
| overall height | 42px | 44px | 62px |
|
|
186
|
+
|
|
187
|
+
Because the size variants declare these on the container itself, they beat the inherited
|
|
188
|
+
`:root` values — but an inline `style` on the same element still wins over both.
|
|
160
189
|
|
|
161
190
|
### Customization Examples
|
|
162
191
|
|
|
@@ -78,7 +78,9 @@
|
|
|
78
78
|
============================================================================ */
|
|
79
79
|
|
|
80
80
|
.stuic-button-group[data-size="sm"] {
|
|
81
|
-
|
|
81
|
+
/* overall height = 36px + 2×2px + 2×1px = 42px */
|
|
82
|
+
--stuic-button-group-padding-x: 3px;
|
|
83
|
+
--stuic-button-group-padding-y: 2px;
|
|
82
84
|
--stuic-button-group-gap: 0.125rem;
|
|
83
85
|
--stuic-button-group-button-padding-x: 0.5rem;
|
|
84
86
|
--stuic-button-group-button-padding-y: 0.375rem;
|
|
@@ -86,7 +88,9 @@
|
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
.stuic-button-group[data-size="lg"] {
|
|
89
|
-
|
|
91
|
+
/* overall height = 48px + 2×6px + 2×1px = 62px */
|
|
92
|
+
--stuic-button-group-padding-x: 8px;
|
|
93
|
+
--stuic-button-group-padding-y: 6px;
|
|
90
94
|
--stuic-button-group-gap: 0.375rem;
|
|
91
95
|
--stuic-button-group-button-padding-x: 1rem;
|
|
92
96
|
--stuic-button-group-button-padding-y: 0.625rem;
|
|
@@ -177,6 +177,11 @@
|
|
|
177
177
|
let _classTiers = $derived(
|
|
178
178
|
unstyled ? classTiersProp : twMerge("stuic-pricing-table-tiers", classTiersProp)
|
|
179
179
|
);
|
|
180
|
+
// The toggle's pill look lives in index.css behind --stuic-pricing-table-toggle-*
|
|
181
|
+
// tokens (an inline declaration here would outrank any :root override).
|
|
182
|
+
let _classToggle = $derived(
|
|
183
|
+
unstyled ? classToggleProp : twMerge("stuic-pricing-table-toggle", classToggleProp)
|
|
184
|
+
);
|
|
180
185
|
</script>
|
|
181
186
|
|
|
182
187
|
<div bind:this={el} class={_class} {style} {...rest}>
|
|
@@ -195,20 +200,9 @@
|
|
|
195
200
|
onButtonClick={(i) => {
|
|
196
201
|
billingPeriod = i === 0 ? "monthly" : "annual";
|
|
197
202
|
}}
|
|
198
|
-
class={
|
|
199
|
-
style=
|
|
200
|
-
|
|
201
|
-
--stuic-button-group-radius: 9999px;
|
|
202
|
-
--stuic-button-group-padding: 0.25rem;
|
|
203
|
-
--stuic-button-group-bg: var(--stuic-color-muted);
|
|
204
|
-
--stuic-button-group-border-width: 0;
|
|
205
|
-
--stuic-button-group-button-bg-active: var(--stuic-color-background);
|
|
206
|
-
--stuic-button-group-button-text-active: var(--stuic-color-foreground);
|
|
207
|
-
--stuic-button-group-button-bg-active-hover: var(--stuic-color-background);
|
|
208
|
-
--stuic-button-group-button-text-active-hover: var(--stuic-color-foreground);
|
|
209
|
-
{styleToggle ?? ''}
|
|
210
|
-
"
|
|
211
|
-
classButtonActive="shadow"
|
|
203
|
+
class={_classToggle}
|
|
204
|
+
style={styleToggle}
|
|
205
|
+
classButtonActive={unstyled ? undefined : "shadow"}
|
|
212
206
|
/>
|
|
213
207
|
{/if}
|
|
214
208
|
{/if}
|
|
@@ -161,12 +161,35 @@ A data-driven pricing tiers component for displaying plan comparisons with featu
|
|
|
161
161
|
|
|
162
162
|
### Toggle
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
164
|
+
The billing toggle is an internal `ButtonGroupRadio`. Its pill look is expressed through the
|
|
165
|
+
tokens below, so a theme can reach it from `:root` like any other part of the component:
|
|
166
|
+
|
|
167
|
+
```css
|
|
168
|
+
:root {
|
|
169
|
+
/* square toggle to match a flat theme */
|
|
170
|
+
--stuic-pricing-table-toggle-radius: var(--stuic-radius-button);
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
| Variable | Default | Description |
|
|
175
|
+
| ------------------------------------------------- | ---------------- | ------------------------------------------- |
|
|
176
|
+
| `--stuic-pricing-table-toggle-radius` | `9999px` | Track and option border radius |
|
|
177
|
+
| `--stuic-pricing-table-toggle-bg` | muted | Toggle track background |
|
|
178
|
+
| `--stuic-pricing-table-toggle-border-width` | `0` | Toggle track border width |
|
|
179
|
+
| `--stuic-pricing-table-toggle-padding-x` | `0.25rem` | Track horizontal padding around the options |
|
|
180
|
+
| `--stuic-pricing-table-toggle-padding-y` | `0.25rem` | Track vertical padding around the options |
|
|
181
|
+
| `--stuic-pricing-table-toggle-color` | muted-foreground | Inactive option text color |
|
|
182
|
+
| `--stuic-pricing-table-toggle-color-hover` | foreground | Inactive option text color on hover |
|
|
183
|
+
| `--stuic-pricing-table-toggle-bg-active` | background | Active option background |
|
|
184
|
+
| `--stuic-pricing-table-toggle-color-active` | foreground | Active option text color |
|
|
185
|
+
| `--stuic-pricing-table-toggle-bg-active-hover` | `-bg-active` | Active option background on hover |
|
|
186
|
+
| `--stuic-pricing-table-toggle-color-active-hover` | `-color-active` | Active option text color on hover |
|
|
187
|
+
|
|
188
|
+
For anything these do not cover, `styleToggle` sets inline styles on the group (including raw
|
|
189
|
+
`--stuic-button-group-*` tokens) and wins over all of the above; `classToggle` adds classes.
|
|
190
|
+
Note that `--stuic-button-group-*` set at `:root` does **not** reach the pricing toggle for the
|
|
191
|
+
properties listed above — the component declares them on the element, so use the
|
|
192
|
+
`--stuic-pricing-table-toggle-*` tokens instead.
|
|
170
193
|
|
|
171
194
|
### Typography
|
|
172
195
|
|
|
@@ -17,6 +17,60 @@
|
|
|
17
17
|
width: 100%;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/* ============================================================================
|
|
21
|
+
BILLING TOGGLE (an internal ButtonGroupRadio)
|
|
22
|
+
|
|
23
|
+
The opinionated pill look lives here rather than in the component's inline
|
|
24
|
+
`style` attribute, because an inline custom property declaration outranks any
|
|
25
|
+
`:root` declaration for that element and its subtree -- which made the toggle
|
|
26
|
+
the one part of this component a theme could not reach. Each value is a
|
|
27
|
+
never-declared `--stuic-pricing-table-toggle-*` component token, so
|
|
28
|
+
`:root { --stuic-pricing-table-toggle-radius: 0; }` works like every other
|
|
29
|
+
token here. `styleToggle` still wins over all of it (inline).
|
|
30
|
+
============================================================================ */
|
|
31
|
+
|
|
32
|
+
.stuic-pricing-table-toggle {
|
|
33
|
+
/* hug the options instead of spanning the row (the group defaults to 100%) */
|
|
34
|
+
width: auto;
|
|
35
|
+
|
|
36
|
+
--stuic-button-group-radius: var(--stuic-pricing-table-toggle-radius, 9999px);
|
|
37
|
+
--stuic-button-group-padding-x: var(--stuic-pricing-table-toggle-padding-x, 0.25rem);
|
|
38
|
+
--stuic-button-group-padding-y: var(--stuic-pricing-table-toggle-padding-y, 0.25rem);
|
|
39
|
+
--stuic-button-group-bg: var(
|
|
40
|
+
--stuic-pricing-table-toggle-bg,
|
|
41
|
+
var(--stuic-color-muted)
|
|
42
|
+
);
|
|
43
|
+
--stuic-button-group-border-width: var(--stuic-pricing-table-toggle-border-width, 0);
|
|
44
|
+
|
|
45
|
+
/* Inactive option */
|
|
46
|
+
--stuic-button-group-button-text: var(
|
|
47
|
+
--stuic-pricing-table-toggle-color,
|
|
48
|
+
var(--stuic-color-muted-foreground)
|
|
49
|
+
);
|
|
50
|
+
--stuic-button-group-button-text-hover: var(
|
|
51
|
+
--stuic-pricing-table-toggle-color-hover,
|
|
52
|
+
var(--stuic-color-foreground)
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
/* Active option (hover falls back to the resting value = no hover shift) */
|
|
56
|
+
--stuic-button-group-button-bg-active: var(
|
|
57
|
+
--stuic-pricing-table-toggle-bg-active,
|
|
58
|
+
var(--stuic-color-background)
|
|
59
|
+
);
|
|
60
|
+
--stuic-button-group-button-text-active: var(
|
|
61
|
+
--stuic-pricing-table-toggle-color-active,
|
|
62
|
+
var(--stuic-color-foreground)
|
|
63
|
+
);
|
|
64
|
+
--stuic-button-group-button-bg-active-hover: var(
|
|
65
|
+
--stuic-pricing-table-toggle-bg-active-hover,
|
|
66
|
+
var(--stuic-pricing-table-toggle-bg-active, var(--stuic-color-background))
|
|
67
|
+
);
|
|
68
|
+
--stuic-button-group-button-text-active-hover: var(
|
|
69
|
+
--stuic-pricing-table-toggle-color-active-hover,
|
|
70
|
+
var(--stuic-pricing-table-toggle-color-active, var(--stuic-color-foreground))
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
20
74
|
/* ============================================================================
|
|
21
75
|
TIERS GRID
|
|
22
76
|
============================================================================ */
|
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 */
|
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
|
|
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
|