@relements/core 0.1.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/dist/base.css +1 -0
- package/dist/behaviors/dialog.d.ts +39 -0
- package/dist/behaviors/dialog.js +1 -0
- package/dist/behaviors/dismissible.d.ts +37 -0
- package/dist/behaviors/dismissible.js +1 -0
- package/dist/behaviors/menu-button.d.ts +36 -0
- package/dist/behaviors/menu-button.js +1 -0
- package/dist/behaviors/popover.d.ts +28 -0
- package/dist/behaviors/popover.js +1 -0
- package/dist/behaviors/tabs.d.ts +37 -0
- package/dist/behaviors/tabs.js +1 -0
- package/dist/behaviors/toast.d.ts +42 -0
- package/dist/behaviors/toast.js +1 -0
- package/dist/chunk-GMICGIQW.js +149 -0
- package/dist/chunk-J4EGUBPP.js +68 -0
- package/dist/chunk-PIDPGDBZ.js +62 -0
- package/dist/chunk-PSODVT3V.js +67 -0
- package/dist/chunk-TC4TFP7Y.js +40 -0
- package/dist/chunk-ZHRJNWMH.js +174 -0
- package/dist/components/button.css +1 -0
- package/dist/components/dialog.css +1 -0
- package/dist/components/disclosure.css +1 -0
- package/dist/components/form.css +1 -0
- package/dist/components/link.css +1 -0
- package/dist/components/menu.css +1 -0
- package/dist/components/popover.css +1 -0
- package/dist/components/progress.css +1 -0
- package/dist/components/tabs.css +1 -0
- package/dist/components/toast.css +1 -0
- package/dist/elements/re-menu.d.ts +10 -0
- package/dist/elements/re-menu.js +36 -0
- package/dist/elements/re-popover.d.ts +12 -0
- package/dist/elements/re-popover.js +35 -0
- package/dist/elements/re-tabs.d.ts +20 -0
- package/dist/elements/re-tabs.js +60 -0
- package/dist/elements/re-toast.d.ts +15 -0
- package/dist/elements/re-toast.js +30 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/reset.css +1 -0
- package/dist/themes/renascent.css +1 -0
- package/dist/tokens.css +1 -0
- package/package.json +84 -0
- package/src/base.css +129 -0
- package/src/behaviors/dialog.js +106 -0
- package/src/behaviors/dismissible.js +68 -0
- package/src/behaviors/menu-button.js +199 -0
- package/src/behaviors/popover.js +103 -0
- package/src/behaviors/tabs.js +171 -0
- package/src/behaviors/toast.js +97 -0
- package/src/components/button.css +141 -0
- package/src/components/dialog.css +106 -0
- package/src/components/disclosure.css +83 -0
- package/src/components/form.css +334 -0
- package/src/components/link.css +61 -0
- package/src/components/menu.css +78 -0
- package/src/components/popover.css +50 -0
- package/src/components/progress.css +112 -0
- package/src/components/tabs.css +86 -0
- package/src/components/toast.css +87 -0
- package/src/elements/re-menu.js +54 -0
- package/src/elements/re-popover.js +59 -0
- package/src/elements/re-tabs.js +92 -0
- package/src/elements/re-toast.js +46 -0
- package/src/index.css +30 -0
- package/src/index.js +13 -0
- package/src/reset.css +103 -0
- package/src/themes/renascent.css +198 -0
- package/src/tokens.css +196 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relements form controls and field layout.
|
|
3
|
+
*
|
|
4
|
+
* One stylesheet covers all native form primitives plus the layout helpers
|
|
5
|
+
* for label/hint/error around them:
|
|
6
|
+
*
|
|
7
|
+
* .re-input — <input type="text|email|number|password|search|tel|url|date|...">
|
|
8
|
+
* .re-textarea — <textarea>
|
|
9
|
+
* .re-select — <select>
|
|
10
|
+
* .re-checkbox — <input type="checkbox">
|
|
11
|
+
* .re-radio — <input type="radio">
|
|
12
|
+
* .re-field — <label> wrapping a control + parts
|
|
13
|
+
* .re-field__label — span/label text
|
|
14
|
+
* .re-field__hint — span/p secondary text
|
|
15
|
+
* .re-field-group — wrapper for multiple related fields
|
|
16
|
+
* .re-field-group__legend — legend or span heading
|
|
17
|
+
* .re-validation-message — span/p error or success text
|
|
18
|
+
*
|
|
19
|
+
* Sizes via data-size: sm, md (default), lg
|
|
20
|
+
* Invalid via [aria-invalid="true"] OR :invalid (when interacted)
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
@layer re.components {
|
|
24
|
+
/* ============================================================
|
|
25
|
+
Shared control surface
|
|
26
|
+
============================================================ */
|
|
27
|
+
.re-input,
|
|
28
|
+
.re-textarea,
|
|
29
|
+
.re-select {
|
|
30
|
+
display: block;
|
|
31
|
+
inline-size: 100%;
|
|
32
|
+
box-sizing: border-box;
|
|
33
|
+
|
|
34
|
+
min-block-size: var(--re-control-height-md);
|
|
35
|
+
padding-inline: var(--re-control-padding-x);
|
|
36
|
+
padding-block: var(--re-control-padding-y);
|
|
37
|
+
|
|
38
|
+
font: inherit;
|
|
39
|
+
font-size: var(--re-size-text-md);
|
|
40
|
+
line-height: var(--re-line-height-normal);
|
|
41
|
+
color: var(--re-color-text);
|
|
42
|
+
background-color: var(--re-color-bg);
|
|
43
|
+
|
|
44
|
+
border: var(--re-border-default);
|
|
45
|
+
border-radius: var(--re-radius-md);
|
|
46
|
+
appearance: none;
|
|
47
|
+
|
|
48
|
+
transition:
|
|
49
|
+
border-color var(--re-duration-fast) var(--re-easing-standard),
|
|
50
|
+
box-shadow var(--re-duration-fast) var(--re-easing-standard),
|
|
51
|
+
background-color var(--re-duration-fast) var(--re-easing-standard);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.re-input::placeholder,
|
|
55
|
+
.re-textarea::placeholder {
|
|
56
|
+
color: var(--re-color-text-subtle);
|
|
57
|
+
opacity: 1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.re-input:hover,
|
|
61
|
+
.re-textarea:hover,
|
|
62
|
+
.re-select:hover {
|
|
63
|
+
border-color: var(--re-color-border-strong);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.re-input:focus-visible,
|
|
67
|
+
.re-textarea:focus-visible,
|
|
68
|
+
.re-select:focus-visible {
|
|
69
|
+
outline: none;
|
|
70
|
+
border-color: var(--re-color-focus-ring);
|
|
71
|
+
box-shadow: var(--re-shadow-focus);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Native invalid state — only after the user interacts (via :user-invalid)
|
|
75
|
+
where supported, plus an explicit hook via aria-invalid. */
|
|
76
|
+
.re-input[aria-invalid="true"],
|
|
77
|
+
.re-textarea[aria-invalid="true"],
|
|
78
|
+
.re-select[aria-invalid="true"],
|
|
79
|
+
.re-input:user-invalid,
|
|
80
|
+
.re-textarea:user-invalid,
|
|
81
|
+
.re-select:user-invalid {
|
|
82
|
+
border-color: var(--re-color-border-danger);
|
|
83
|
+
}
|
|
84
|
+
.re-input[aria-invalid="true"]:focus-visible,
|
|
85
|
+
.re-textarea[aria-invalid="true"]:focus-visible,
|
|
86
|
+
.re-select[aria-invalid="true"]:focus-visible,
|
|
87
|
+
.re-input:user-invalid:focus-visible,
|
|
88
|
+
.re-textarea:user-invalid:focus-visible,
|
|
89
|
+
.re-select:user-invalid:focus-visible {
|
|
90
|
+
box-shadow:
|
|
91
|
+
0 0 0 var(--re-focus-ring-offset) var(--re-color-bg),
|
|
92
|
+
0 0 0 calc(var(--re-focus-ring-offset) + var(--re-focus-ring-width))
|
|
93
|
+
var(--re-color-danger-500);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* Disabled */
|
|
97
|
+
.re-input:disabled,
|
|
98
|
+
.re-textarea:disabled,
|
|
99
|
+
.re-select:disabled,
|
|
100
|
+
.re-checkbox:disabled,
|
|
101
|
+
.re-radio:disabled {
|
|
102
|
+
cursor: not-allowed;
|
|
103
|
+
background-color: var(--re-color-bg-muted);
|
|
104
|
+
color: var(--re-color-text-subtle);
|
|
105
|
+
opacity: 0.7;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Sizes */
|
|
109
|
+
.re-input[data-size="sm"],
|
|
110
|
+
.re-textarea[data-size="sm"],
|
|
111
|
+
.re-select[data-size="sm"] {
|
|
112
|
+
min-block-size: var(--re-control-height-sm);
|
|
113
|
+
font-size: var(--re-size-text-sm);
|
|
114
|
+
padding-inline: var(--re-space-2);
|
|
115
|
+
}
|
|
116
|
+
.re-input[data-size="lg"],
|
|
117
|
+
.re-textarea[data-size="lg"],
|
|
118
|
+
.re-select[data-size="lg"] {
|
|
119
|
+
min-block-size: var(--re-control-height-lg);
|
|
120
|
+
font-size: var(--re-size-text-lg);
|
|
121
|
+
padding-inline: var(--re-space-4);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* ============================================================
|
|
125
|
+
Textarea
|
|
126
|
+
============================================================ */
|
|
127
|
+
.re-textarea {
|
|
128
|
+
min-block-size: calc(var(--re-control-height-md) * 2);
|
|
129
|
+
resize: vertical;
|
|
130
|
+
line-height: var(--re-line-height-relaxed);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* ============================================================
|
|
134
|
+
Select
|
|
135
|
+
============================================================ */
|
|
136
|
+
.re-select {
|
|
137
|
+
padding-inline-end: var(--re-space-8);
|
|
138
|
+
background-image:
|
|
139
|
+
linear-gradient(45deg, transparent 50%, currentColor 50%),
|
|
140
|
+
linear-gradient(135deg, currentColor 50%, transparent 50%);
|
|
141
|
+
background-position:
|
|
142
|
+
right var(--re-space-4) top 55%,
|
|
143
|
+
right calc(var(--re-space-4) - 5px) top 55%;
|
|
144
|
+
background-size:
|
|
145
|
+
5px 5px,
|
|
146
|
+
5px 5px;
|
|
147
|
+
background-repeat: no-repeat;
|
|
148
|
+
color: var(--re-color-text);
|
|
149
|
+
}
|
|
150
|
+
.re-select[multiple] {
|
|
151
|
+
background-image: none;
|
|
152
|
+
padding-inline-end: var(--re-control-padding-x);
|
|
153
|
+
min-block-size: calc(var(--re-control-height-md) * 3);
|
|
154
|
+
}
|
|
155
|
+
.re-select[multiple] option {
|
|
156
|
+
padding-block: var(--re-space-1);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* ============================================================
|
|
160
|
+
Checkbox & radio (native, styled)
|
|
161
|
+
============================================================ */
|
|
162
|
+
.re-checkbox,
|
|
163
|
+
.re-radio {
|
|
164
|
+
appearance: none;
|
|
165
|
+
-webkit-appearance: none;
|
|
166
|
+
inline-size: 1.125rem;
|
|
167
|
+
block-size: 1.125rem;
|
|
168
|
+
margin: 0;
|
|
169
|
+
padding: 0;
|
|
170
|
+
flex-shrink: 0;
|
|
171
|
+
background-color: var(--re-color-bg);
|
|
172
|
+
border: var(--re-border-width-strong) solid var(--re-color-border-strong);
|
|
173
|
+
cursor: pointer;
|
|
174
|
+
display: inline-grid;
|
|
175
|
+
place-content: center;
|
|
176
|
+
color: var(--re-color-text-on-accent);
|
|
177
|
+
transition:
|
|
178
|
+
background-color var(--re-duration-fast) var(--re-easing-standard),
|
|
179
|
+
border-color var(--re-duration-fast) var(--re-easing-standard),
|
|
180
|
+
box-shadow var(--re-duration-fast) var(--re-easing-standard);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.re-checkbox {
|
|
184
|
+
border-radius: var(--re-radius-sm);
|
|
185
|
+
}
|
|
186
|
+
.re-radio {
|
|
187
|
+
border-radius: var(--re-radius-pill);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.re-checkbox:hover,
|
|
191
|
+
.re-radio:hover {
|
|
192
|
+
border-color: var(--re-color-accent-600);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.re-checkbox:focus-visible,
|
|
196
|
+
.re-radio:focus-visible {
|
|
197
|
+
outline: none;
|
|
198
|
+
box-shadow: var(--re-shadow-focus);
|
|
199
|
+
border-color: var(--re-color-focus-ring);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* Checked state — drawn via ::before glyph so they remain native. */
|
|
203
|
+
.re-checkbox:checked,
|
|
204
|
+
.re-radio:checked {
|
|
205
|
+
background-color: var(--re-color-accent-600);
|
|
206
|
+
border-color: var(--re-color-accent-600);
|
|
207
|
+
}
|
|
208
|
+
.re-checkbox:checked::before {
|
|
209
|
+
content: "";
|
|
210
|
+
inline-size: 0.65rem;
|
|
211
|
+
block-size: 0.65rem;
|
|
212
|
+
background-color: currentColor;
|
|
213
|
+
clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0, 43% 62%);
|
|
214
|
+
}
|
|
215
|
+
.re-radio:checked::before {
|
|
216
|
+
content: "";
|
|
217
|
+
inline-size: 0.55rem;
|
|
218
|
+
block-size: 0.55rem;
|
|
219
|
+
border-radius: var(--re-radius-pill);
|
|
220
|
+
background-color: currentColor;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/* Indeterminate (checkbox) */
|
|
224
|
+
.re-checkbox:indeterminate {
|
|
225
|
+
background-color: var(--re-color-accent-600);
|
|
226
|
+
border-color: var(--re-color-accent-600);
|
|
227
|
+
}
|
|
228
|
+
.re-checkbox:indeterminate::before {
|
|
229
|
+
content: "";
|
|
230
|
+
inline-size: 0.7rem;
|
|
231
|
+
block-size: 0.18rem;
|
|
232
|
+
background-color: currentColor;
|
|
233
|
+
border-radius: var(--re-radius-sm);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/* Invalid */
|
|
237
|
+
.re-checkbox[aria-invalid="true"],
|
|
238
|
+
.re-radio[aria-invalid="true"] {
|
|
239
|
+
border-color: var(--re-color-border-danger);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/* ============================================================
|
|
243
|
+
Field (label-wrapped control)
|
|
244
|
+
============================================================ */
|
|
245
|
+
.re-field {
|
|
246
|
+
display: flex;
|
|
247
|
+
flex-direction: column;
|
|
248
|
+
gap: var(--re-space-2);
|
|
249
|
+
/* Make the field itself a focus container without changing semantics. */
|
|
250
|
+
color: var(--re-color-text);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.re-field__label {
|
|
254
|
+
font-size: var(--re-size-text-sm);
|
|
255
|
+
font-weight: var(--re-font-weight-medium);
|
|
256
|
+
color: var(--re-color-text);
|
|
257
|
+
line-height: 1.2;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.re-field__label[data-required]::after {
|
|
261
|
+
content: " *";
|
|
262
|
+
color: var(--re-color-text-danger);
|
|
263
|
+
margin-inline-start: 0.1em;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.re-field__hint {
|
|
267
|
+
font-size: var(--re-size-text-sm);
|
|
268
|
+
color: var(--re-color-text-muted);
|
|
269
|
+
line-height: var(--re-line-height-normal);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/* Checkbox / radio inline layout helper:
|
|
273
|
+
<label class="re-field re-field--inline">
|
|
274
|
+
<input type="checkbox" class="re-checkbox" />
|
|
275
|
+
<span class="re-field__label">Subscribe</span>
|
|
276
|
+
</label>
|
|
277
|
+
*/
|
|
278
|
+
.re-field--inline {
|
|
279
|
+
flex-direction: row;
|
|
280
|
+
align-items: center;
|
|
281
|
+
gap: var(--re-space-3);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* ============================================================
|
|
285
|
+
Field group (fieldset/legend or div/span pattern)
|
|
286
|
+
============================================================ */
|
|
287
|
+
.re-field-group {
|
|
288
|
+
border: 0;
|
|
289
|
+
padding: 0;
|
|
290
|
+
margin: 0;
|
|
291
|
+
display: flex;
|
|
292
|
+
flex-direction: column;
|
|
293
|
+
gap: var(--re-space-2);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.re-field-group__legend {
|
|
297
|
+
font-size: var(--re-size-text-sm);
|
|
298
|
+
font-weight: var(--re-font-weight-medium);
|
|
299
|
+
color: var(--re-color-text);
|
|
300
|
+
line-height: 1.2;
|
|
301
|
+
padding: 0;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.re-field-group[data-orientation="horizontal"] > .re-field-group__items {
|
|
305
|
+
flex-direction: row;
|
|
306
|
+
flex-wrap: wrap;
|
|
307
|
+
gap: var(--re-space-4);
|
|
308
|
+
}
|
|
309
|
+
.re-field-group__items {
|
|
310
|
+
display: flex;
|
|
311
|
+
flex-direction: column;
|
|
312
|
+
gap: var(--re-space-2);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/* ============================================================
|
|
316
|
+
Validation message
|
|
317
|
+
============================================================ */
|
|
318
|
+
.re-validation-message {
|
|
319
|
+
display: block;
|
|
320
|
+
font-size: var(--re-size-text-sm);
|
|
321
|
+
line-height: var(--re-line-height-normal);
|
|
322
|
+
color: var(--re-color-text-danger);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.re-validation-message[data-tone="success"] {
|
|
326
|
+
color: var(--re-color-success-700);
|
|
327
|
+
}
|
|
328
|
+
.re-validation-message[data-tone="hint"] {
|
|
329
|
+
color: var(--re-color-text-muted);
|
|
330
|
+
}
|
|
331
|
+
.re-validation-message[data-tone="warning"] {
|
|
332
|
+
color: var(--re-color-warning-700);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relements link.
|
|
3
|
+
*
|
|
4
|
+
* Opt-in styling for anchors. Native <a> defaults are already set by base.css;
|
|
5
|
+
* `.re-link` adds underline emphasis, hover/visited states, and explicit focus.
|
|
6
|
+
*
|
|
7
|
+
* Variants (data-variant):
|
|
8
|
+
* default — text-colored underline, accent on hover
|
|
9
|
+
* muted — muted color, default underline
|
|
10
|
+
* subtle — no underline until hover
|
|
11
|
+
* external — appends ↗ glyph hint (does not replace aria-label)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
@layer re.components {
|
|
15
|
+
.re-link {
|
|
16
|
+
color: var(--re-color-link);
|
|
17
|
+
text-decoration-line: underline;
|
|
18
|
+
text-decoration-thickness: 0.08em;
|
|
19
|
+
text-underline-offset: 0.18em;
|
|
20
|
+
text-decoration-color: currentColor;
|
|
21
|
+
border-radius: var(--re-radius-sm);
|
|
22
|
+
transition:
|
|
23
|
+
color var(--re-duration-fast) var(--re-easing-standard),
|
|
24
|
+
text-decoration-color var(--re-duration-fast) var(--re-easing-standard);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.re-link:hover {
|
|
28
|
+
color: var(--re-color-link-hover);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.re-link:visited {
|
|
32
|
+
color: var(--re-color-link-visited);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.re-link:focus-visible {
|
|
36
|
+
outline: none;
|
|
37
|
+
box-shadow: var(--re-shadow-focus);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* ---- Variants -------------------------------------------------------- */
|
|
41
|
+
.re-link[data-variant="muted"] {
|
|
42
|
+
color: var(--re-color-text-muted);
|
|
43
|
+
text-decoration-color: var(--re-color-border-strong);
|
|
44
|
+
}
|
|
45
|
+
.re-link[data-variant="muted"]:hover {
|
|
46
|
+
color: var(--re-color-text);
|
|
47
|
+
text-decoration-color: currentColor;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.re-link[data-variant="subtle"] {
|
|
51
|
+
text-decoration-line: none;
|
|
52
|
+
}
|
|
53
|
+
.re-link[data-variant="subtle"]:hover {
|
|
54
|
+
text-decoration-line: underline;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.re-link[data-variant="external"]::after {
|
|
58
|
+
content: " \2197"; /* ↗ */
|
|
59
|
+
speak: none;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relements menu / menu-button.
|
|
3
|
+
*
|
|
4
|
+
* ARIA menu-button pattern over server-rendered markup:
|
|
5
|
+
*
|
|
6
|
+
* <div class="re-menu" data-re-menu>
|
|
7
|
+
* <button class="re-menu__button" aria-haspopup="menu" aria-expanded="false" aria-controls="m-1" id="b-1">
|
|
8
|
+
* Actions
|
|
9
|
+
* </button>
|
|
10
|
+
* <div class="re-menu__panel" role="menu" id="m-1" aria-labelledby="b-1" hidden>
|
|
11
|
+
* <button role="menuitem" class="re-menu__item">Rename</button>
|
|
12
|
+
* <button role="menuitem" class="re-menu__item">Duplicate</button>
|
|
13
|
+
* <button role="menuitem" class="re-menu__item">Delete</button>
|
|
14
|
+
* </div>
|
|
15
|
+
* </div>
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
@layer re.components {
|
|
19
|
+
.re-menu {
|
|
20
|
+
position: relative;
|
|
21
|
+
display: inline-block;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.re-menu__panel {
|
|
25
|
+
position: absolute;
|
|
26
|
+
inset-block-start: calc(100% + var(--re-space-1));
|
|
27
|
+
inset-inline-start: 0;
|
|
28
|
+
min-inline-size: 12rem;
|
|
29
|
+
background-color: var(--re-color-surface);
|
|
30
|
+
border: var(--re-border-default);
|
|
31
|
+
border-radius: var(--re-radius-md);
|
|
32
|
+
box-shadow: var(--re-shadow-md);
|
|
33
|
+
padding: var(--re-space-1);
|
|
34
|
+
z-index: var(--re-z-popover);
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
gap: 1px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.re-menu__item {
|
|
41
|
+
appearance: none;
|
|
42
|
+
background: transparent;
|
|
43
|
+
border: 0;
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
font: inherit;
|
|
46
|
+
text-align: start;
|
|
47
|
+
padding: var(--re-space-2) var(--re-space-3);
|
|
48
|
+
border-radius: var(--re-radius-sm);
|
|
49
|
+
color: var(--re-color-text);
|
|
50
|
+
line-height: var(--re-line-height-normal);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.re-menu__item:hover {
|
|
54
|
+
/* bg-muted always differs from surface in both light and dark modes.
|
|
55
|
+
bg-subtle collapses to the same value as surface in dark mode,
|
|
56
|
+
making hover invisible. */
|
|
57
|
+
background-color: var(--re-color-bg-muted);
|
|
58
|
+
outline: none;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.re-menu__item:focus-visible {
|
|
62
|
+
background-color: var(--re-color-bg-muted);
|
|
63
|
+
outline: none;
|
|
64
|
+
box-shadow: inset 0 0 0 2px var(--re-color-focus-ring);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.re-menu__item[aria-disabled="true"],
|
|
68
|
+
.re-menu__item:disabled {
|
|
69
|
+
color: var(--re-color-text-subtle);
|
|
70
|
+
cursor: not-allowed;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.re-menu__separator {
|
|
74
|
+
block-size: 1px;
|
|
75
|
+
background-color: var(--re-color-border);
|
|
76
|
+
margin-block: var(--re-space-1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relements popover.
|
|
3
|
+
*
|
|
4
|
+
* Styles for elements using the native `popover` attribute (toggled via
|
|
5
|
+
* `popovertarget` buttons or showPopover()/hidePopover()) and a JS-enhanced
|
|
6
|
+
* fallback marked with [data-re-popover].
|
|
7
|
+
*
|
|
8
|
+
* <button class="re-button" popovertarget="tip">Toggle</button>
|
|
9
|
+
* <div class="re-popover" id="tip" popover>
|
|
10
|
+
* <p>Hello!</p>
|
|
11
|
+
* </div>
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
@layer re.components {
|
|
15
|
+
.re-popover {
|
|
16
|
+
margin: 0;
|
|
17
|
+
inset: auto;
|
|
18
|
+
border: var(--re-border-default);
|
|
19
|
+
border-radius: var(--re-radius-md);
|
|
20
|
+
background-color: var(--re-color-surface);
|
|
21
|
+
color: var(--re-color-text);
|
|
22
|
+
padding: var(--re-space-3) var(--re-space-4);
|
|
23
|
+
box-shadow: var(--re-shadow-md);
|
|
24
|
+
max-inline-size: 22rem;
|
|
25
|
+
line-height: var(--re-line-height-normal);
|
|
26
|
+
/* Position is anchored by consumer styles or the JS helper. */
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Override UA default popover positioning so the helper can place it. */
|
|
30
|
+
.re-popover:popover-open {
|
|
31
|
+
/* Reset to auto so JS-based positioning takes over. */
|
|
32
|
+
margin: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* Tones: tinted background + colored border; text stays at default
|
|
36
|
+
contrast. Same pattern as toast — tone is communicated via bg + border,
|
|
37
|
+
not by making the text itself hard to read. */
|
|
38
|
+
.re-popover[data-tone="info"] {
|
|
39
|
+
background-color: color-mix(in srgb, var(--re-color-accent-500) 12%, var(--re-color-surface));
|
|
40
|
+
border-color: var(--re-color-accent-500);
|
|
41
|
+
}
|
|
42
|
+
.re-popover[data-tone="warning"] {
|
|
43
|
+
background-color: color-mix(in srgb, var(--re-color-warning-500) 12%, var(--re-color-surface));
|
|
44
|
+
border-color: var(--re-color-warning-500);
|
|
45
|
+
}
|
|
46
|
+
.re-popover[data-tone="danger"] {
|
|
47
|
+
background-color: color-mix(in srgb, var(--re-color-danger-500) 12%, var(--re-color-surface));
|
|
48
|
+
border-color: var(--re-color-danger-500);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relements progress and meter.
|
|
3
|
+
*
|
|
4
|
+
* Two native indicator elements share visuals:
|
|
5
|
+
* .re-progress — <progress> for task completion (indeterminate or value/max)
|
|
6
|
+
* .re-meter — <meter> for measurement within a range (e.g., disk usage)
|
|
7
|
+
*
|
|
8
|
+
* Both are styled by tinting the native track/fill via vendor pseudo-elements
|
|
9
|
+
* plus a CSS overlay for cross-browser consistency. Native semantics, value
|
|
10
|
+
* ranges, and accessibility are preserved.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
@layer re.components {
|
|
14
|
+
.re-progress,
|
|
15
|
+
.re-meter {
|
|
16
|
+
inline-size: 100%;
|
|
17
|
+
block-size: 0.5rem;
|
|
18
|
+
appearance: none;
|
|
19
|
+
-webkit-appearance: none;
|
|
20
|
+
border: 0;
|
|
21
|
+
border-radius: var(--re-radius-pill);
|
|
22
|
+
background-color: var(--re-color-bg-muted);
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
color: var(--re-color-accent-600); /* used as fill on some engines */
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* ---- WebKit / Blink track + fill ---------------------------------- */
|
|
28
|
+
.re-progress::-webkit-progress-bar {
|
|
29
|
+
background-color: var(--re-color-bg-muted);
|
|
30
|
+
border-radius: var(--re-radius-pill);
|
|
31
|
+
}
|
|
32
|
+
.re-progress::-webkit-progress-value {
|
|
33
|
+
background-color: var(--re-color-accent-600);
|
|
34
|
+
border-radius: var(--re-radius-pill);
|
|
35
|
+
transition: inline-size var(--re-duration-normal) var(--re-easing-standard);
|
|
36
|
+
}
|
|
37
|
+
/* ---- Firefox ----------------------------------------------------- */
|
|
38
|
+
.re-progress::-moz-progress-bar {
|
|
39
|
+
background-color: var(--re-color-accent-600);
|
|
40
|
+
border-radius: var(--re-radius-pill);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Indeterminate animation */
|
|
44
|
+
.re-progress:indeterminate {
|
|
45
|
+
background:
|
|
46
|
+
linear-gradient(90deg, transparent 0%, var(--re-color-accent-300) 50%, transparent 100%)
|
|
47
|
+
no-repeat,
|
|
48
|
+
var(--re-color-bg-muted);
|
|
49
|
+
background-size:
|
|
50
|
+
40% 100%,
|
|
51
|
+
100% 100%;
|
|
52
|
+
animation: re-progress-indeterminate 1200ms linear infinite;
|
|
53
|
+
}
|
|
54
|
+
@keyframes re-progress-indeterminate {
|
|
55
|
+
0% {
|
|
56
|
+
background-position:
|
|
57
|
+
-40% 0,
|
|
58
|
+
0 0;
|
|
59
|
+
}
|
|
60
|
+
100% {
|
|
61
|
+
background-position:
|
|
62
|
+
140% 0,
|
|
63
|
+
0 0;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
@media (prefers-reduced-motion: reduce) {
|
|
67
|
+
.re-progress:indeterminate {
|
|
68
|
+
animation-duration: 0.01ms;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* ---- Meter ranges (low / optimum / high) ------------------------- */
|
|
73
|
+
/* WebKit */
|
|
74
|
+
.re-meter::-webkit-meter-bar {
|
|
75
|
+
background-color: var(--re-color-bg-muted);
|
|
76
|
+
border-radius: var(--re-radius-pill);
|
|
77
|
+
border: 0;
|
|
78
|
+
}
|
|
79
|
+
.re-meter::-webkit-meter-optimum-value {
|
|
80
|
+
background-color: var(--re-color-success-600);
|
|
81
|
+
border-radius: var(--re-radius-pill);
|
|
82
|
+
}
|
|
83
|
+
.re-meter::-webkit-meter-suboptimum-value {
|
|
84
|
+
background-color: var(--re-color-warning-600);
|
|
85
|
+
border-radius: var(--re-radius-pill);
|
|
86
|
+
}
|
|
87
|
+
.re-meter::-webkit-meter-even-less-good-value {
|
|
88
|
+
background-color: var(--re-color-danger-600);
|
|
89
|
+
border-radius: var(--re-radius-pill);
|
|
90
|
+
}
|
|
91
|
+
/* Firefox */
|
|
92
|
+
.re-meter::-moz-meter-bar {
|
|
93
|
+
background-color: var(--re-color-success-600);
|
|
94
|
+
border-radius: var(--re-radius-pill);
|
|
95
|
+
}
|
|
96
|
+
.re-meter:-moz-meter-sub-optimum::-moz-meter-bar {
|
|
97
|
+
background-color: var(--re-color-warning-600);
|
|
98
|
+
}
|
|
99
|
+
.re-meter:-moz-meter-sub-sub-optimum::-moz-meter-bar {
|
|
100
|
+
background-color: var(--re-color-danger-600);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* Sizes via data-size */
|
|
104
|
+
.re-progress[data-size="sm"],
|
|
105
|
+
.re-meter[data-size="sm"] {
|
|
106
|
+
block-size: 0.25rem;
|
|
107
|
+
}
|
|
108
|
+
.re-progress[data-size="lg"],
|
|
109
|
+
.re-meter[data-size="lg"] {
|
|
110
|
+
block-size: 0.75rem;
|
|
111
|
+
}
|
|
112
|
+
}
|