@ponchia/ui 0.2.1 → 0.3.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.
Files changed (48) hide show
  1. package/README.md +128 -54
  2. package/behaviors/index.d.ts +36 -0
  3. package/behaviors/index.js +321 -7
  4. package/classes/index.d.ts +228 -3
  5. package/classes/index.js +139 -4
  6. package/css/app.css +64 -64
  7. package/css/base.css +136 -24
  8. package/css/content.css +324 -0
  9. package/css/core.css +9 -5
  10. package/css/disclosure.css +323 -0
  11. package/css/dots.css +125 -8
  12. package/css/feedback.css +243 -0
  13. package/css/fonts.css +11 -0
  14. package/css/forms.css +41 -14
  15. package/css/motion.css +29 -5
  16. package/css/navigation.css +22 -86
  17. package/css/overlay.css +206 -0
  18. package/css/primitives.css +37 -18
  19. package/css/site.css +295 -0
  20. package/css/table.css +9 -9
  21. package/css/tokens.css +84 -20
  22. package/dist/bronto.css +1 -0
  23. package/dist/css/app.css +1 -0
  24. package/dist/css/base.css +1 -0
  25. package/dist/css/content.css +1 -0
  26. package/dist/css/disclosure.css +1 -0
  27. package/dist/css/dots.css +1 -0
  28. package/dist/css/feedback.css +1 -0
  29. package/dist/css/fonts.css +1 -0
  30. package/dist/css/forms.css +1 -0
  31. package/dist/css/motion.css +1 -0
  32. package/dist/css/navigation.css +1 -0
  33. package/dist/css/overlay.css +1 -0
  34. package/dist/css/primitives.css +1 -0
  35. package/dist/css/site.css +1 -0
  36. package/dist/css/table.css +1 -0
  37. package/dist/css/tokens.css +1 -0
  38. package/package.json +62 -21
  39. package/shiki/nothing.json +83 -0
  40. package/tokens/index.d.ts +18 -10
  41. package/tokens/index.js +16 -14
  42. package/tokens/index.json +32 -28
  43. package/tokens/tokens.dtcg.json +589 -0
  44. package/css/cards.css +0 -336
  45. package/css/index.css +0 -5
  46. package/css/layout.css +0 -219
  47. package/css/responsive.css +0 -157
  48. package/css/typography.css +0 -139
@@ -1,15 +1,10 @@
1
1
  /* ==========================================================================
2
- navigation — site nav, menu, theme toggle (Nothing flat, dot indicator)
3
- Class names kept stable for site-nav compatibility.
2
+ navigation — theme toggle (Nothing flat, dot-thumb switch).
3
+ Site nav/menu live in site.css as ui-sitenav / ui-sitemenu; the legacy
4
+ .site-nav / .site-menu vocabulary was removed in 0.3.0.
4
5
  ========================================================================== */
5
6
 
6
- .site-menu {
7
- display: none;
8
- position: relative;
9
- }
10
-
11
- .site-menu__toggle,
12
- .theme-toggle__button {
7
+ .ui-themetoggle__button {
13
8
  align-items: center;
14
9
  background: transparent;
15
10
  border: 1px solid var(--line-strong);
@@ -21,9 +16,10 @@
21
16
  font-size: var(--text-xs);
22
17
  font-weight: 600;
23
18
  gap: 0.4rem;
19
+ justify-content: center;
24
20
  letter-spacing: var(--tracking-wide);
25
- list-style: none;
26
- min-height: 2rem;
21
+ min-block-size: 2rem;
22
+ min-inline-size: 7rem;
27
23
  padding: 0.42rem 0.66rem;
28
24
  text-transform: uppercase;
29
25
  transition:
@@ -33,114 +29,54 @@
33
29
  white-space: nowrap;
34
30
  }
35
31
 
36
- .theme-toggle__button {
37
- justify-content: center;
38
- min-width: 7rem;
39
- }
40
-
41
- .site-menu__toggle::-webkit-details-marker {
42
- display: none;
43
- }
44
-
45
- .site-menu[open] .site-menu__toggle,
46
- .site-menu__toggle:hover,
47
- .theme-toggle__button:hover {
32
+ .ui-themetoggle__button:hover {
48
33
  border-color: var(--accent);
49
- color: var(--accent);
34
+ color: var(--accent-text);
50
35
  }
51
36
 
52
- .theme-toggle__prefix {
37
+ .ui-themetoggle__prefix {
53
38
  color: var(--text-dim);
54
39
  }
55
40
 
56
- .theme-toggle__label {
41
+ .ui-themetoggle__label {
57
42
  color: var(--text);
58
43
  font-weight: 700;
59
44
  }
60
45
 
61
- .theme-toggle__track {
46
+ .ui-themetoggle__track {
62
47
  background: var(--panel-soft);
63
48
  border: 1px solid var(--line-strong);
64
49
  border-radius: var(--radius-pill);
65
50
  display: inline-flex;
66
- height: 0.8rem;
51
+ block-size: 0.8rem;
67
52
  padding: 0.12rem;
68
- width: 1.5rem;
53
+ inline-size: 1.5rem;
69
54
  }
70
55
 
71
- .theme-toggle__thumb {
56
+ .ui-themetoggle__thumb {
72
57
  background: var(--text-dim);
73
58
  border-radius: 50%;
74
59
  display: block;
75
- height: 100%;
60
+ block-size: 100%;
76
61
  transform: translateX(0);
77
62
  transition:
78
63
  background-color var(--duration-fast) var(--ease-standard),
79
64
  transform var(--duration-fast) var(--ease-spring);
80
- width: 0.56rem;
65
+ inline-size: 0.56rem;
81
66
  }
82
67
 
83
- [data-theme='dark'] .theme-toggle__thumb {
68
+ [data-theme='dark'] .ui-themetoggle__thumb {
84
69
  background: var(--accent);
85
70
  transform: translateX(0.6rem);
86
71
  }
87
72
 
88
- .site-nav {
89
- display: inline-flex;
90
- gap: 0.15rem;
91
- }
92
-
93
- .site-nav a {
94
- align-items: center;
95
- border: 1px solid transparent;
96
- border-radius: var(--radius-md);
97
- color: var(--text-soft);
98
- display: inline-flex;
99
- font-family: var(--mono);
100
- font-size: var(--text-xs);
101
- gap: 0.45rem;
102
- letter-spacing: var(--tracking-wide);
103
- padding: 0.4rem 0.6rem;
104
- position: relative;
105
- text-transform: uppercase;
106
- transition:
107
- border-color var(--duration-fast) var(--ease-standard),
108
- background-color var(--duration-fast) var(--ease-standard),
109
- color var(--duration-fast) var(--ease-standard);
110
- }
111
-
112
- /* Leading dot is the active/hover indicator — Nothing glyph cue. */
113
- .site-nav a::before {
114
- background: currentColor;
115
- border-radius: 50%;
116
- content: '';
117
- height: 0.32rem;
118
- opacity: 0;
119
- transform: scale(0.5);
120
- transition:
121
- opacity var(--duration-fast) var(--ease-standard),
122
- transform var(--duration-fast) var(--ease-spring);
123
- width: 0.32rem;
124
- }
125
-
126
- .site-nav a:hover,
127
- .site-nav a.is-active {
128
- color: var(--text);
129
- }
130
-
131
- .site-nav a.is-active {
132
- color: var(--accent);
133
- }
134
-
135
- .site-nav a:hover::before,
136
- .site-nav a.is-active::before {
137
- opacity: 1;
138
- transform: scale(1);
73
+ [dir='rtl'][data-theme='dark'] .ui-themetoggle__thumb,
74
+ [dir='rtl'] [data-theme='dark'] .ui-themetoggle__thumb {
75
+ transform: translateX(-0.6rem);
139
76
  }
140
77
 
141
78
  @media (hover: hover) {
142
- .site-menu__toggle:active,
143
- .theme-toggle__button:active {
79
+ .ui-themetoggle__button:active {
144
80
  transform: translateY(1px);
145
81
  }
146
82
  }
@@ -0,0 +1,206 @@
1
+ /* ==========================================================================
2
+ overlay — modal / drawer / dropdown menu
3
+ Built on native <dialog> and <details> so the framework stays
4
+ CSS-first; the optional initDialog behavior only adds open/close glue.
5
+ ========================================================================== */
6
+
7
+ /* --- Modal — style the native <dialog> --- */
8
+
9
+ .ui-modal {
10
+ background: var(--panel-strong);
11
+ border: 1px solid var(--line-strong);
12
+ border-radius: var(--radius-lg);
13
+ box-shadow: var(--shadow-raised);
14
+ color: var(--text);
15
+ margin: auto;
16
+ max-block-size: min(85vh, 44rem);
17
+ max-inline-size: min(32rem, calc(100vw - 2rem));
18
+ overflow: hidden;
19
+ padding: 0;
20
+ inline-size: 100%;
21
+ }
22
+
23
+ .ui-modal::backdrop {
24
+ backdrop-filter: blur(2px);
25
+ background: color-mix(in srgb, var(--bg) 70%, transparent);
26
+ }
27
+
28
+ .ui-modal[open] {
29
+ animation: uiToastIn var(--duration-base) var(--ease-spring) both;
30
+ display: grid;
31
+ grid-template-rows: auto 1fr auto;
32
+ }
33
+
34
+ .ui-modal__head {
35
+ align-items: flex-start;
36
+ border-block-end: 1px solid var(--line);
37
+ display: flex;
38
+ gap: var(--space-sm);
39
+ justify-content: space-between;
40
+ padding: var(--space-md);
41
+ }
42
+
43
+ .ui-modal__title {
44
+ color: var(--text);
45
+ font-family: var(--display);
46
+ font-size: var(--text-lg);
47
+ letter-spacing: var(--tracking-wide);
48
+ margin: 0;
49
+ text-transform: uppercase;
50
+ }
51
+
52
+ .ui-modal__body {
53
+ overflow-y: auto;
54
+ padding: var(--space-md);
55
+ }
56
+
57
+ .ui-modal__foot {
58
+ border-block-start: 1px solid var(--line);
59
+ display: flex;
60
+ flex-wrap: wrap;
61
+ gap: var(--space-xs);
62
+ justify-content: flex-end;
63
+ padding: var(--space-md);
64
+ }
65
+
66
+ .ui-modal__close {
67
+ background: transparent;
68
+ border: 1px solid var(--line-strong);
69
+ border-radius: var(--radius-md);
70
+ color: var(--text);
71
+ cursor: pointer;
72
+ flex: 0 0 auto;
73
+ font-family: var(--mono);
74
+ line-height: 1;
75
+ padding: 0.34rem 0.5rem;
76
+ }
77
+
78
+ /* Drawer — full-height panel slid in from the inline-end edge
79
+ (right in LTR, left in RTL). */
80
+ .ui-modal--drawer {
81
+ block-size: 100vh;
82
+ margin: 0;
83
+ margin-inline-start: auto;
84
+ max-block-size: 100vh;
85
+ max-inline-size: min(26rem, 100vw);
86
+ border-radius: 0;
87
+ border-width: 0;
88
+ border-inline-start-width: 1px;
89
+ }
90
+
91
+ @media (hover: hover) {
92
+ .ui-modal__close:hover {
93
+ border-color: var(--accent);
94
+ color: var(--accent-text);
95
+ }
96
+ }
97
+
98
+ /* --- Dropdown menu — pairs with native <details> --- */
99
+
100
+ /* The positioned host for a <details> dropdown: .ui-menu is absolute, so
101
+ its <details> wrapper must establish a containing block. (Replaces the
102
+ role the legacy .site-menu wrapper served, now a first-class ui-*.) */
103
+ .ui-menu-host {
104
+ display: inline-block;
105
+ position: relative;
106
+ }
107
+
108
+ .ui-menu {
109
+ background: var(--panel-strong);
110
+ border: 1px solid var(--line-strong);
111
+ border-radius: var(--radius-md);
112
+ box-shadow: var(--shadow-raised);
113
+ display: grid;
114
+ gap: 1px;
115
+ min-inline-size: 11rem;
116
+ padding: 0.3rem;
117
+ position: absolute;
118
+ inset-inline-end: 0;
119
+ inset-block-start: calc(100% + 0.4rem);
120
+ z-index: 30;
121
+ }
122
+
123
+ .ui-menu__label {
124
+ color: var(--text-dim);
125
+ font-family: var(--mono);
126
+ font-size: var(--text-2xs);
127
+ letter-spacing: var(--tracking-wide);
128
+ padding: 0.45rem 0.55rem 0.2rem;
129
+ text-transform: uppercase;
130
+ }
131
+
132
+ .ui-menu__item {
133
+ align-items: center;
134
+ background: transparent;
135
+ border: 0;
136
+ border-radius: var(--radius-sm);
137
+ color: var(--text-soft);
138
+ cursor: pointer;
139
+ display: flex;
140
+ font-family: var(--mono);
141
+ font-size: var(--text-sm);
142
+ gap: 0.5rem;
143
+ padding: 0.5rem 0.55rem;
144
+ text-align: start;
145
+ inline-size: 100%;
146
+ }
147
+
148
+ .ui-menu__item::before {
149
+ background: currentColor;
150
+ border-radius: 50%;
151
+ content: '';
152
+ block-size: 0.3rem;
153
+ opacity: 0.4;
154
+ inline-size: 0.3rem;
155
+ }
156
+
157
+ .ui-menu__sep {
158
+ background: var(--line);
159
+ border: 0;
160
+ block-size: 1px;
161
+ margin: 0.2rem 0;
162
+ }
163
+
164
+ @media (hover: hover) {
165
+ .ui-menu__item:hover {
166
+ background: var(--bg-accent);
167
+ color: var(--text);
168
+ }
169
+
170
+ .ui-menu__item:hover::before {
171
+ opacity: 1;
172
+ }
173
+ }
174
+
175
+ /* --- Mobile: modal becomes a bottom sheet, drawer goes full-width --- */
176
+
177
+ @media (max-width: 560px) {
178
+ .ui-modal {
179
+ border-radius: var(--radius-lg) var(--radius-lg) 0 0;
180
+ margin: auto auto 0;
181
+ max-block-size: 88vh;
182
+ max-inline-size: 100vw;
183
+ inline-size: 100vw;
184
+ }
185
+
186
+ .ui-modal--drawer {
187
+ border-radius: 0;
188
+ border-width: 1px 0 0;
189
+ block-size: 88vh;
190
+ margin: auto 0 0;
191
+ max-block-size: 88vh;
192
+ max-inline-size: 100vw;
193
+ inline-size: 100vw;
194
+ }
195
+
196
+ .ui-menu {
197
+ inset-inline: 0;
198
+ min-inline-size: 0;
199
+ }
200
+ }
201
+
202
+ @media (prefers-reduced-motion: reduce) {
203
+ .ui-modal[open] {
204
+ animation: none;
205
+ }
206
+ }
@@ -69,14 +69,16 @@
69
69
 
70
70
  .ui-divider {
71
71
  border: 0;
72
- border-top: 1px solid var(--line);
72
+ border-block-start: 1px solid var(--line);
73
73
  margin: 0;
74
74
  }
75
75
 
76
76
  /* --- Eyebrow / section label — dot-matrix face --- */
77
77
 
78
78
  .ui-eyebrow {
79
- color: var(--accent);
79
+ /* accent-strong, not accent: this is small bold text and must clear
80
+ WCAG AA 4.5:1 on the soft/tinted surfaces eyebrows sit on too. */
81
+ color: var(--accent-text);
80
82
  font-family: var(--display);
81
83
  font-size: var(--text-xs);
82
84
  font-weight: 700;
@@ -106,8 +108,8 @@
106
108
  justify-content: center;
107
109
  letter-spacing: var(--tracking-wide);
108
110
  line-height: 1;
109
- min-height: 2.4rem;
110
- min-width: 2.4rem;
111
+ min-block-size: 2.4rem;
112
+ min-inline-size: 2.4rem;
111
113
  padding: 0.66rem 1rem;
112
114
  text-transform: uppercase;
113
115
  transition:
@@ -137,7 +139,7 @@
137
139
 
138
140
  .ui-button--icon {
139
141
  aspect-ratio: 1;
140
- min-width: 2.4rem;
142
+ min-inline-size: 2.4rem;
141
143
  padding: 0;
142
144
  }
143
145
 
@@ -172,13 +174,13 @@
172
174
  }
173
175
 
174
176
  .ui-link--arrow::after {
175
- border-right: 1px solid currentColor;
176
- border-top: 1px solid currentColor;
177
+ border-inline-end: 1px solid currentColor;
178
+ border-block-start: 1px solid currentColor;
177
179
  content: '';
178
- height: 0.42rem;
180
+ block-size: 0.42rem;
179
181
  transform: rotate(45deg);
180
182
  transition: transform var(--duration-fast) var(--ease-standard);
181
- width: 0.42rem;
183
+ inline-size: 0.42rem;
182
184
  }
183
185
 
184
186
  /* --- Chip / tag --- */
@@ -195,14 +197,16 @@
195
197
  gap: 0.36rem;
196
198
  letter-spacing: var(--tracking-wide);
197
199
  line-height: 1;
198
- min-height: 1.7rem;
200
+ min-block-size: 1.7rem;
199
201
  padding: 0.32rem 0.55rem;
200
202
  text-transform: uppercase;
201
203
  }
202
204
 
203
205
  .ui-chip--accent {
206
+ /* accent-strong, not accent: chip text is small uppercase mono and must
207
+ clear WCAG AA 4.5:1 — same rule as .ui-eyebrow above. */
208
+ color: var(--accent-text);
204
209
  border-color: var(--accent);
205
- color: var(--accent);
206
210
  }
207
211
 
208
212
  /* --- Badge / status pill --- */
@@ -224,28 +228,26 @@
224
228
  text-transform: uppercase;
225
229
  }
226
230
 
231
+ /* Tone rides the border + tint; text stays the high-contrast neutral
232
+ (the soft tint can't carry 4.5:1 small-bold tone-on-tone — WCAG). */
227
233
  .ui-badge--accent {
228
234
  background: var(--accent-soft);
229
235
  border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
230
- color: var(--accent);
231
236
  }
232
237
 
233
238
  .ui-badge--success {
234
239
  background: var(--success-soft);
235
240
  border-color: color-mix(in srgb, var(--success) 40%, var(--line));
236
- color: var(--success);
237
241
  }
238
242
 
239
243
  .ui-badge--warning {
240
244
  background: var(--warning-soft);
241
245
  border-color: color-mix(in srgb, var(--warning) 40%, var(--line));
242
- color: var(--warning);
243
246
  }
244
247
 
245
248
  .ui-badge--danger {
246
249
  background: var(--danger-soft);
247
250
  border-color: color-mix(in srgb, var(--danger) 40%, var(--line));
248
- color: var(--danger);
249
251
  }
250
252
 
251
253
  /* --- Key/value list --- */
@@ -257,10 +259,10 @@
257
259
  }
258
260
 
259
261
  .ui-key-value div {
260
- border-top: 1px solid var(--line);
262
+ border-block-start: 1px solid var(--line);
261
263
  display: grid;
262
264
  gap: 0.16rem;
263
- padding-top: 0.6rem;
265
+ padding-block-start: 0.6rem;
264
266
  }
265
267
 
266
268
  .ui-key-value dt {
@@ -307,7 +309,7 @@
307
309
  }
308
310
 
309
311
  .ui-link:hover {
310
- color: var(--accent);
312
+ color: var(--accent-text);
311
313
  text-decoration-color: var(--accent);
312
314
  }
313
315
 
@@ -315,7 +317,24 @@
315
317
  transform: translateX(0.14rem) rotate(45deg);
316
318
  }
317
319
 
320
+ [dir='rtl'] .ui-link--arrow:hover::after {
321
+ transform: translateX(-0.14rem) rotate(45deg);
322
+ }
323
+
318
324
  .ui-chip--accent:hover {
319
325
  background: var(--accent-soft);
320
326
  }
321
327
  }
328
+
329
+ /* --- Touch: comfortable hit targets on coarse pointers --- */
330
+
331
+ @media (pointer: coarse) {
332
+ .ui-button {
333
+ min-block-size: 2.9rem;
334
+ min-inline-size: 2.9rem;
335
+ }
336
+
337
+ .ui-button--icon {
338
+ min-inline-size: 2.9rem;
339
+ }
340
+ }