@ponchia/ui 0.2.2 → 0.3.1

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.
Files changed (48) hide show
  1. package/README.md +108 -79
  2. package/behaviors/index.d.ts +53 -0
  3. package/behaviors/index.js +745 -34
  4. package/classes/index.d.ts +216 -3
  5. package/classes/index.js +85 -10
  6. package/classes/vscode.css-custom-data.json +407 -0
  7. package/css/app.css +53 -44
  8. package/css/base.css +14 -23
  9. package/css/content.css +37 -2
  10. package/css/core.css +5 -5
  11. package/css/disclosure.css +17 -5
  12. package/css/dots.css +1 -1
  13. package/css/feedback.css +87 -2
  14. package/css/forms.css +128 -2
  15. package/css/navigation.css +16 -85
  16. package/css/overlay.css +73 -2
  17. package/css/primitives.css +100 -3
  18. package/css/site.css +295 -0
  19. package/css/table.css +59 -0
  20. package/css/tokens.css +79 -24
  21. package/dist/bronto.css +1 -1
  22. package/dist/css/app.css +1 -0
  23. package/dist/css/base.css +1 -0
  24. package/dist/css/content.css +1 -0
  25. package/dist/css/disclosure.css +1 -0
  26. package/dist/css/dots.css +1 -0
  27. package/dist/css/feedback.css +1 -0
  28. package/dist/css/fonts.css +1 -0
  29. package/dist/css/forms.css +1 -0
  30. package/dist/css/motion.css +1 -0
  31. package/dist/css/navigation.css +1 -0
  32. package/dist/css/overlay.css +1 -0
  33. package/dist/css/primitives.css +1 -0
  34. package/dist/css/site.css +1 -0
  35. package/dist/css/table.css +1 -0
  36. package/dist/css/tokens.css +1 -0
  37. package/package.json +60 -30
  38. package/shiki/nothing.json +83 -0
  39. package/tokens/index.d.ts +18 -10
  40. package/tokens/index.js +49 -16
  41. package/tokens/index.json +98 -32
  42. package/tokens/tokens.dtcg.json +241 -22
  43. package/css/cards.css +0 -336
  44. package/css/index.css +0 -5
  45. package/css/layout.css +0 -219
  46. package/css/responsive.css +0 -157
  47. package/css/typography.css +0 -139
  48. package/dist/bronto-core.css +0 -1
package/css/site.css ADDED
@@ -0,0 +1,295 @@
1
+ /* ==========================================================================
2
+ site — first-class shell for content / marketing sites.
3
+
4
+ The framework already shipped an admin shell (app.css); this is its
5
+ public-site counterpart, promoted into the typed `ui-*` contract so
6
+ every consumer stops re-hand-rolling a container + header + nav +
7
+ footer + skip-link. Nothing-flat, logical properties, the dot active
8
+ cue. Active nav state is driven by `aria-current` (no extra class).
9
+ ========================================================================== */
10
+
11
+ /* --- Container — centred reading measure + gutters --- */
12
+
13
+ .ui-container {
14
+ inline-size: 100%;
15
+ margin-inline: auto;
16
+ max-inline-size: var(--container, 72rem);
17
+ padding-inline: var(--space-md);
18
+ }
19
+
20
+ .ui-container--narrow {
21
+ max-inline-size: var(--container-narrow, 44rem);
22
+ }
23
+
24
+ /* --- Skip link — first focusable, jumps to main --- */
25
+
26
+ .ui-skiplink {
27
+ background: var(--panel-strong);
28
+ border: 1px solid var(--line-strong);
29
+ border-radius: var(--radius-md);
30
+ color: var(--text);
31
+ inset-block-start: -4rem;
32
+ inset-inline-start: var(--space-md);
33
+ padding: 0.7rem 1rem;
34
+ position: fixed;
35
+ z-index: var(--z-toast);
36
+ }
37
+
38
+ .ui-skiplink:focus {
39
+ inset-block-start: var(--space-md);
40
+ }
41
+
42
+ /* --- Header — brand · nav · actions --- */
43
+
44
+ .ui-siteheader {
45
+ align-items: center;
46
+ border-block-end: 1px solid var(--line);
47
+ display: flex;
48
+ flex-wrap: wrap;
49
+ gap: var(--space-md);
50
+ justify-content: space-between;
51
+ padding-block: var(--space-sm);
52
+ }
53
+
54
+ .ui-siteheader__brand {
55
+ align-items: center;
56
+ color: var(--text);
57
+ display: inline-flex;
58
+ font-family: var(--display);
59
+ font-size: var(--text-lg);
60
+ gap: 0.5rem;
61
+ letter-spacing: var(--tracking-wide);
62
+ text-transform: uppercase;
63
+ }
64
+
65
+ .ui-siteheader__brand::before {
66
+ background: var(--accent);
67
+ border-radius: 50%;
68
+ block-size: 0.5rem;
69
+ content: '';
70
+ flex: 0 0 auto;
71
+ inline-size: 0.5rem;
72
+ }
73
+
74
+ .ui-siteheader__actions {
75
+ align-items: center;
76
+ display: inline-flex;
77
+ gap: var(--space-xs);
78
+ }
79
+
80
+ /* --- Nav — desktop inline, dot active cue via aria-current --- */
81
+
82
+ .ui-sitenav {
83
+ display: inline-flex;
84
+ flex-wrap: wrap;
85
+ gap: 0.15rem;
86
+ }
87
+
88
+ .ui-sitenav a {
89
+ align-items: center;
90
+ border: 1px solid transparent;
91
+ border-radius: var(--radius-md);
92
+ color: var(--text-soft);
93
+ display: inline-flex;
94
+ font-family: var(--mono);
95
+ font-size: var(--text-xs);
96
+ gap: 0.45rem;
97
+ letter-spacing: var(--tracking-wide);
98
+ padding: 0.4rem 0.6rem;
99
+ text-transform: uppercase;
100
+ transition:
101
+ border-color var(--duration-fast) var(--ease-standard),
102
+ color var(--duration-fast) var(--ease-standard);
103
+ }
104
+
105
+ .ui-sitenav a::before {
106
+ background: currentColor;
107
+ border-radius: 50%;
108
+ block-size: 0.32rem;
109
+ content: '';
110
+ inline-size: 0.32rem;
111
+ opacity: 0;
112
+ transform: scale(0.5);
113
+ transition:
114
+ opacity var(--duration-fast) var(--ease-standard),
115
+ transform var(--duration-fast) var(--ease-spring);
116
+ }
117
+
118
+ .ui-sitenav a[aria-current] {
119
+ color: var(--accent-text);
120
+ }
121
+
122
+ .ui-sitenav a[aria-current]::before {
123
+ opacity: 1;
124
+ transform: scale(1);
125
+ }
126
+
127
+ @media (hover: hover) {
128
+ .ui-sitenav a:hover {
129
+ color: var(--text);
130
+ }
131
+
132
+ .ui-sitenav a:hover::before {
133
+ opacity: 1;
134
+ transform: scale(1);
135
+ }
136
+ }
137
+
138
+ /* --- Mobile menu — native <details>, no JS required --- */
139
+
140
+ .ui-sitemenu {
141
+ display: none;
142
+ position: relative;
143
+ }
144
+
145
+ .ui-sitemenu > summary {
146
+ align-items: center;
147
+ background: transparent;
148
+ border: 1px solid var(--line-strong);
149
+ border-radius: var(--radius-md);
150
+ color: var(--text);
151
+ cursor: pointer;
152
+ display: inline-flex;
153
+ font-family: var(--mono);
154
+ font-size: var(--text-xs);
155
+ font-weight: 600;
156
+ gap: 0.4rem;
157
+ letter-spacing: var(--tracking-wide);
158
+ list-style: none;
159
+ min-block-size: 2.4rem;
160
+ padding: 0.42rem 0.7rem;
161
+ text-transform: uppercase;
162
+ }
163
+
164
+ .ui-sitemenu > summary::-webkit-details-marker {
165
+ display: none;
166
+ }
167
+
168
+ .ui-sitemenu[open] > summary {
169
+ border-color: var(--accent);
170
+ color: var(--accent-text);
171
+ }
172
+
173
+ .ui-sitemenu__panel {
174
+ background: var(--panel-strong);
175
+ border: 1px solid var(--line-strong);
176
+ border-radius: var(--radius-md);
177
+ box-shadow: var(--shadow-raised);
178
+ display: grid;
179
+ gap: 0.15rem;
180
+ inset-block-start: calc(100% + 0.4rem);
181
+ inset-inline-end: 0;
182
+ min-inline-size: 12rem;
183
+ padding: 0.4rem;
184
+ position: absolute;
185
+ z-index: var(--z-overlay);
186
+ }
187
+
188
+ /* Below the breakpoint the inline nav collapses into the menu. */
189
+ @media (max-width: 720px) {
190
+ .ui-siteheader .ui-sitenav {
191
+ display: none;
192
+ }
193
+
194
+ .ui-sitemenu {
195
+ display: block;
196
+ }
197
+
198
+ .ui-sitemenu .ui-sitenav {
199
+ display: grid;
200
+ }
201
+ }
202
+
203
+ /* --- Footer --- */
204
+
205
+ .ui-sitefooter {
206
+ align-items: center;
207
+ border-block-start: 1px solid var(--line);
208
+ color: var(--text-dim);
209
+ display: flex;
210
+ flex-wrap: wrap;
211
+ font-size: var(--text-sm);
212
+ gap: var(--space-sm);
213
+ justify-content: space-between;
214
+ margin-block-start: var(--space-2xl);
215
+ padding-block: var(--space-md);
216
+ }
217
+
218
+ .ui-sitefooter__links {
219
+ display: flex;
220
+ flex-wrap: wrap;
221
+ gap: var(--space-md);
222
+ }
223
+
224
+ .ui-sitefooter__links a {
225
+ color: var(--text);
226
+ text-decoration: underline;
227
+ text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent);
228
+ text-underline-offset: 0.2rem;
229
+ transition: text-decoration-color var(--duration-fast) var(--ease-standard);
230
+ }
231
+
232
+ @media (hover: hover) {
233
+ .ui-sitefooter__links a:hover {
234
+ text-decoration-color: var(--accent);
235
+ }
236
+ }
237
+
238
+ /* --- Tags — neutral, wrapping content labels (NOT ui-chip, which is a
239
+ single interactive token). Use a <ul>. --- */
240
+
241
+ .ui-tags {
242
+ display: flex;
243
+ flex-wrap: wrap;
244
+ gap: 0.5rem;
245
+ list-style: none;
246
+ margin: 0;
247
+ padding: 0;
248
+ }
249
+
250
+ .ui-tag {
251
+ background: var(--panel-soft);
252
+ border: 1px solid var(--line);
253
+ border-radius: var(--radius-md);
254
+ color: var(--text-soft);
255
+ display: inline-flex;
256
+ font-size: var(--text-xs);
257
+ padding: 0.28rem 0.6rem;
258
+ }
259
+
260
+ .ui-tag--accent {
261
+ background: var(--accent-soft);
262
+ border-color: color-mix(in srgb, var(--accent) 42%, var(--line));
263
+ color: var(--accent-text);
264
+ }
265
+
266
+ /* --- Meta row — date · author · read-time, dot-separated --- */
267
+
268
+ .ui-meta {
269
+ align-items: center;
270
+ color: var(--text-dim);
271
+ display: flex;
272
+ flex-wrap: wrap;
273
+ font-family: var(--mono);
274
+ font-size: var(--text-2xs);
275
+ gap: 0.55rem;
276
+ letter-spacing: var(--tracking-wide);
277
+ list-style: none;
278
+ margin: 0;
279
+ padding: 0;
280
+ text-transform: uppercase;
281
+ }
282
+
283
+ .ui-meta__item {
284
+ align-items: center;
285
+ display: inline-flex;
286
+ gap: 0.55rem;
287
+ }
288
+
289
+ .ui-meta__item:not(:last-child)::after {
290
+ background: var(--line-strong);
291
+ border-radius: 50%;
292
+ block-size: 0.22rem;
293
+ content: '';
294
+ inline-size: 0.22rem;
295
+ }
package/css/table.css CHANGED
@@ -100,3 +100,62 @@
100
100
  padding: 2rem;
101
101
  text-align: center;
102
102
  }
103
+
104
+ /* --- Sortable headers (wired by initTableSort) --- */
105
+ .ui-table__sort {
106
+ align-items: center;
107
+ background: none;
108
+ border: 0;
109
+ color: inherit;
110
+ cursor: pointer;
111
+ display: flex;
112
+ font: inherit;
113
+ gap: 0.4rem;
114
+ letter-spacing: inherit;
115
+ padding: 0;
116
+ text-transform: inherit;
117
+ inline-size: 100%;
118
+ }
119
+
120
+ .ui-table__sort::after {
121
+ content: '↕';
122
+ opacity: 0.4;
123
+ }
124
+
125
+ .ui-table th[aria-sort='ascending'] .ui-table__sort::after {
126
+ content: '↑';
127
+ opacity: 1;
128
+ }
129
+
130
+ .ui-table th[aria-sort='descending'] .ui-table__sort::after {
131
+ content: '↓';
132
+ opacity: 1;
133
+ }
134
+
135
+ /* --- Row selection --- */
136
+ .ui-table__select {
137
+ inline-size: 1px; /* shrink-to-fit checkbox column */
138
+ white-space: nowrap;
139
+ }
140
+
141
+ .ui-table--selectable tbody tr[aria-selected='true'] td {
142
+ background: var(--bg-accent);
143
+ }
144
+
145
+ /* --- Bulk-action toolbar --- */
146
+ .ui-table__toolbar {
147
+ align-items: center;
148
+ border: 1px solid var(--line);
149
+ border-block-end: 0;
150
+ border-start-start-radius: var(--radius-md);
151
+ border-start-end-radius: var(--radius-md);
152
+ display: flex;
153
+ gap: var(--space-sm);
154
+ padding: var(--space-sm) var(--space-md);
155
+ }
156
+
157
+ /* --- Loading state: set aria-busy + .ui-table--loading on the wrap --- */
158
+ .ui-table--loading {
159
+ opacity: 0.6;
160
+ pointer-events: none;
161
+ }
package/css/tokens.css CHANGED
@@ -52,6 +52,54 @@
52
52
  --dot-size: 2px;
53
53
  --dot-gap: 14px;
54
54
 
55
+ /* Stacking-context scale. Replaces scattered magic z-indexes so
56
+ consumers can reason about (and override) layering coherently.
57
+ Values match the prior literals — purely a refactor, no visual
58
+ change. */
59
+ --z-base: 0;
60
+ --z-raised: 10;
61
+ --z-sticky: 20;
62
+ --z-overlay: 30;
63
+ --z-popover: 50;
64
+ --z-toast: 60;
65
+
66
+ /* Accent ramp — a stepped family for charts / data-viz / multi-state
67
+ surfaces (the use case tokens/index.js advertises). Derived from the
68
+ single --accent knob via color-mix against the theme bg, so it
69
+ re-brands and theme-adapts automatically; no per-theme duplication. */
70
+ --accent-1: color-mix(in srgb, var(--accent) 8%, var(--bg));
71
+ --accent-2: color-mix(in srgb, var(--accent) 16%, var(--bg));
72
+ --accent-3: color-mix(in srgb, var(--accent) 32%, var(--bg));
73
+ --accent-4: color-mix(in srgb, var(--accent) 60%, var(--bg));
74
+ --accent-5: var(--accent);
75
+ --accent-6: var(--accent-strong);
76
+
77
+ /* Neutral surface ramp (low → high contrast against --bg). */
78
+ --surface-1: var(--bg);
79
+ --surface-2: var(--bg-elevated);
80
+ --surface-3: var(--panel);
81
+ --surface-4: var(--panel-soft);
82
+ --surface-5: var(--line);
83
+ --surface-6: var(--line-strong);
84
+
85
+ /* Semantic tier — stable, prefixed aliases over the (shorter,
86
+ legacy) primitive names. New consumer code should target these:
87
+ re-skinning one role no longer means chasing component internals.
88
+ The short names below stay as permanent back-compat aliases. */
89
+ --bronto-color-bg: var(--bg);
90
+ --bronto-color-surface: var(--panel);
91
+ --bronto-color-surface-raised: var(--panel-strong);
92
+ --bronto-color-border: var(--line);
93
+ --bronto-color-border-strong: var(--line-strong);
94
+ --bronto-color-text: var(--text);
95
+ --bronto-color-text-muted: var(--text-dim);
96
+ --bronto-color-action: var(--accent);
97
+ --bronto-color-on-action: var(--button-text);
98
+ --bronto-color-focus: var(--focus-ring);
99
+ --bronto-color-success: var(--success);
100
+ --bronto-color-warning: var(--warning);
101
+ --bronto-color-danger: var(--danger);
102
+
55
103
  /* Aliases kept for back-compat with existing semantic classes */
56
104
  --surface: var(--panel);
57
105
  --surface-raised: var(--panel-strong);
@@ -80,21 +128,26 @@
80
128
  --text-dim: #686863;
81
129
  --accent: #d71921;
82
130
  --accent-strong: color-mix(in srgb, var(--accent) 83%, #000);
131
+ --accent-text: var(--accent-strong);
83
132
  --accent-soft: color-mix(in srgb, var(--accent) 10%, transparent);
84
133
  --success: #2f7d4f;
85
- --success-soft: rgba(47, 125, 79, 0.12);
134
+ --success-soft: rgb(47, 125, 79, 0.12);
86
135
  --warning: #806414;
87
- --warning-soft: rgba(128, 100, 20, 0.13);
136
+ --warning-soft: rgb(128, 100, 20, 0.13);
88
137
  --orange: #a85f32;
89
- --orange-soft: rgba(168, 95, 50, 0.13);
138
+ --orange-soft: rgb(168, 95, 50, 0.13);
90
139
  --danger: #c01622;
91
- --danger-soft: rgba(192, 22, 34, 0.1);
92
- --code-bg: rgba(10, 10, 10, 0.05);
140
+ --danger-soft: rgb(192, 22, 34, 0.1);
141
+ --code-bg: rgb(10, 10, 10, 0.05);
93
142
  --button-text: #ffffff;
94
- --field-dot: rgba(10, 10, 10, 0.16);
95
- --field-dot-hot: rgba(10, 10, 10, 0.4);
143
+ --field-dot: rgb(10, 10, 10, 0.16);
144
+ --field-dot-hot: rgb(10, 10, 10, 0.4);
96
145
  --field-dot-accent: color-mix(in srgb, var(--accent) 78%, transparent);
97
- --focus-ring: color-mix(in srgb, var(--accent) 50%, transparent);
146
+
147
+ /* Solid by default: this token drives every focus outline, so it must
148
+ clear the 3:1 non-text contrast minimum. Override per theme/subtree
149
+ to tune the ring without touching --accent. */
150
+ --focus-ring: var(--accent);
98
151
  --shadow: none;
99
152
  --shadow-raised: 0 0 0 1px var(--line-strong);
100
153
  }
@@ -126,21 +179,22 @@
126
179
  --text-dim: #858585;
127
180
  --accent: #ff3b41;
128
181
  --accent-strong: color-mix(in srgb, var(--accent) 84%, #fff);
182
+ --accent-text: var(--accent-strong);
129
183
  --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
130
184
  --success: #4ec27e;
131
- --success-soft: rgba(78, 194, 126, 0.14);
185
+ --success-soft: rgb(78, 194, 126, 0.14);
132
186
  --warning: #d8bd72;
133
- --warning-soft: rgba(216, 189, 114, 0.14);
187
+ --warning-soft: rgb(216, 189, 114, 0.14);
134
188
  --orange: #d08c5b;
135
- --orange-soft: rgba(208, 140, 91, 0.15);
189
+ --orange-soft: rgb(208, 140, 91, 0.15);
136
190
  --danger: #ff4d54;
137
- --danger-soft: rgba(255, 77, 84, 0.15);
138
- --code-bg: rgba(255, 255, 255, 0.05);
191
+ --danger-soft: rgb(255, 77, 84, 0.15);
192
+ --code-bg: rgb(255, 255, 255, 0.05);
139
193
  --button-text: #000000;
140
- --field-dot: rgba(242, 242, 242, 0.14);
141
- --field-dot-hot: rgba(242, 242, 242, 0.36);
194
+ --field-dot: rgb(242, 242, 242, 0.14);
195
+ --field-dot-hot: rgb(242, 242, 242, 0.36);
142
196
  --field-dot-accent: color-mix(in srgb, var(--accent) 82%, transparent);
143
- --focus-ring: color-mix(in srgb, var(--accent) 55%, transparent);
197
+ --focus-ring: var(--accent);
144
198
  --shadow: none;
145
199
  --shadow-raised: 0 0 0 1px var(--line-strong);
146
200
  }
@@ -162,21 +216,22 @@
162
216
  --text-dim: #858585;
163
217
  --accent: #ff3b41;
164
218
  --accent-strong: color-mix(in srgb, var(--accent) 84%, #fff);
219
+ --accent-text: var(--accent-strong);
165
220
  --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
166
221
  --success: #4ec27e;
167
- --success-soft: rgba(78, 194, 126, 0.14);
222
+ --success-soft: rgb(78, 194, 126, 0.14);
168
223
  --warning: #d8bd72;
169
- --warning-soft: rgba(216, 189, 114, 0.14);
224
+ --warning-soft: rgb(216, 189, 114, 0.14);
170
225
  --orange: #d08c5b;
171
- --orange-soft: rgba(208, 140, 91, 0.15);
226
+ --orange-soft: rgb(208, 140, 91, 0.15);
172
227
  --danger: #ff4d54;
173
- --danger-soft: rgba(255, 77, 84, 0.15);
174
- --code-bg: rgba(255, 255, 255, 0.05);
228
+ --danger-soft: rgb(255, 77, 84, 0.15);
229
+ --code-bg: rgb(255, 255, 255, 0.05);
175
230
  --button-text: #000000;
176
- --field-dot: rgba(242, 242, 242, 0.14);
177
- --field-dot-hot: rgba(242, 242, 242, 0.36);
231
+ --field-dot: rgb(242, 242, 242, 0.14);
232
+ --field-dot-hot: rgb(242, 242, 242, 0.36);
178
233
  --field-dot-accent: color-mix(in srgb, var(--accent) 82%, transparent);
179
- --focus-ring: color-mix(in srgb, var(--accent) 55%, transparent);
234
+ --focus-ring: var(--accent);
180
235
  --shadow: none;
181
236
  --shadow-raised: 0 0 0 1px var(--line-strong);
182
237
  }