opui-css 1.2.4

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 (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +59 -0
  3. package/dist/ui.css +4417 -0
  4. package/package.json +33 -0
  5. package/src/components/accordion.css +172 -0
  6. package/src/components/alert.css +85 -0
  7. package/src/components/avatar.css +68 -0
  8. package/src/components/badge.css +101 -0
  9. package/src/components/button-group.css +69 -0
  10. package/src/components/button.css +272 -0
  11. package/src/components/card.css +82 -0
  12. package/src/components/checkbox-radio.css +123 -0
  13. package/src/components/chip.css +135 -0
  14. package/src/components/definition-list.css +65 -0
  15. package/src/components/description-list.css +0 -0
  16. package/src/components/dialog.css +61 -0
  17. package/src/components/divider.css +7 -0
  18. package/src/components/field-group.css +83 -0
  19. package/src/components/field.css +500 -0
  20. package/src/components/icon-button.css +40 -0
  21. package/src/components/link.css +21 -0
  22. package/src/components/list.css +317 -0
  23. package/src/components/progress.css +80 -0
  24. package/src/components/range.css +121 -0
  25. package/src/components/rich-text.css +210 -0
  26. package/src/components/select.css +166 -0
  27. package/src/components/snackbar.css +152 -0
  28. package/src/components/spinner.css +38 -0
  29. package/src/components/switch.css +189 -0
  30. package/src/components/tab-buttons.css +124 -0
  31. package/src/components/table.css +107 -0
  32. package/src/components/text-field.css +57 -0
  33. package/src/components/textarea.css +25 -0
  34. package/src/components/toggle-button-group.css +142 -0
  35. package/src/components/tooltip.css +94 -0
  36. package/src/components/typography.css +209 -0
  37. package/src/main.css +59 -0
  38. package/src/normalize.css +194 -0
  39. package/src/theme.css +160 -0
  40. package/src/utils.css +60 -0
@@ -0,0 +1,61 @@
1
+ @layer components.has-deps {
2
+ :where(dialog) {
3
+ margin-block-start: 15%; /* vertical alignment */
4
+ padding-block: 0;
5
+ pointer-events: none;
6
+
7
+ &::backdrop {
8
+ background-color: rgba(0, 0, 0, 0.5);
9
+ backdrop-filter: blur(5px);
10
+
11
+ @media (prefers-reduced-motion: reduce) {
12
+ backdrop-filter: none;
13
+ }
14
+ }
15
+
16
+ &:not([open]) {
17
+ display: none;
18
+ }
19
+
20
+ &[open] {
21
+ pointer-events: all;
22
+ }
23
+
24
+ .actions {
25
+ justify-content: end;
26
+ padding-inline: var(--size-3) var(--size-1);
27
+ }
28
+
29
+ /* Animation */
30
+ /* There's no close animation, intentionally */
31
+ opacity: 0;
32
+
33
+ &[open] {
34
+ opacity: 1;
35
+ transition:
36
+ display 0.2s allow-discrete,
37
+ margin-block-start 0.3s var(--ease-1),
38
+ overlay 0.2s allow-discrete,
39
+ opacity 0.2s var(--ease-out-1);
40
+
41
+ @starting-style {
42
+ opacity: 0;
43
+ }
44
+ }
45
+
46
+ @media (prefers-reduced-motion: no-preference) {
47
+ margin-block-start: 17%;
48
+ &[open] {
49
+ margin-block-start: 15%;
50
+
51
+ @starting-style {
52
+ margin-block-start: 17%;
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ :where(html:has(dialog[open])) {
59
+ overflow: hidden;
60
+ }
61
+ }
@@ -0,0 +1,7 @@
1
+ @layer components.base {
2
+ :where(hr) {
3
+ background-color: var(--border-color);
4
+ block-size: var(--border-size-1);
5
+ margin-block: var(--size-fluid-3);
6
+ }
7
+ }
@@ -0,0 +1,83 @@
1
+ @layer components.has-deps {
2
+ /* Common styling for checkbox, radio and switch groups */
3
+ :where(fieldset.field-group) {
4
+ border: 0;
5
+ border-radius: 0;
6
+ gap: 0;
7
+ padding: 0;
8
+ z-index: 1;
9
+
10
+ legend {
11
+ color: var(--text-color-2);
12
+ padding: 0 1ex 0 0;
13
+ }
14
+
15
+ /* Disabled */
16
+ &[disabled] {
17
+ cursor: not-allowed;
18
+ opacity: 0.64;
19
+ user-select: none;
20
+
21
+ input {
22
+ cursor: not-allowed;
23
+ }
24
+ }
25
+
26
+ /* Validation */
27
+ &.error {
28
+ legend,
29
+ .supporting-text {
30
+ color: var(--color-9);
31
+ }
32
+ }
33
+
34
+ /* Required */
35
+ &:has([required]) {
36
+ &:not(:has(input:where([type="radio"], [type="checkbox"]):checked)) {
37
+ legend {
38
+ position: relative;
39
+
40
+ &::after {
41
+ color: var(--red);
42
+ content: "*";
43
+ inset: 0 -0.25ex auto auto;
44
+ position: absolute;
45
+ }
46
+ }
47
+ }
48
+ }
49
+ :where(.radio, .checkbox, .switch) .label:after {
50
+ display: none;
51
+ }
52
+
53
+ /* Supporting text */
54
+ .supporting-text {
55
+ color: var(--text-color-2);
56
+ font-size: var(--font-size-xs);
57
+ line-height: 1.5;
58
+ z-index: 1;
59
+ }
60
+
61
+ /* Fields */
62
+ .fields {
63
+ display: flex;
64
+ flex-direction: column;
65
+ gap: var(--size-2);
66
+
67
+ * ~ & {
68
+ padding: var(--size-2) 0;
69
+ }
70
+ }
71
+
72
+ :last-child {
73
+ padding-block-end: 0;
74
+ }
75
+
76
+ /* Directions */
77
+ &.row {
78
+ .fields {
79
+ flex-direction: row;
80
+ }
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,500 @@
1
+ @layer components.has-deps {
2
+ /*
3
+ - Common styling for input, textarea and select
4
+ - Form related styles such as: label, supporting text, error handling
5
+ */
6
+ :where(.field) {
7
+ --_accent-color: var(--primary);
8
+ --_bg-color: var(--surface-default);
9
+ --_border-color: var(--field-border-color);
10
+ --_field-padding-block: 0.75rem;
11
+ --_field-padding-inline: var(--size-2);
12
+ --_filled-border-color: var(--text-color-1);
13
+ --_height: var(--field-size);
14
+ --_label-color: var(--text-color-2);
15
+ --_supporting-text-color: var(--text-color-2);
16
+
17
+ contain: layout;
18
+ display: inline-grid;
19
+ position: relative;
20
+
21
+ /* Input/Select base */
22
+ & input,
23
+ & textarea,
24
+ & select {
25
+ background-color: var(--_bg-color);
26
+ block-size: var(--_height);
27
+ border-radius: var(--field-border-radius);
28
+ border: var(--field-border-width) solid var(--_border-color);
29
+ color: var(--text-color-1);
30
+ font-family: var(--font-sans);
31
+ font-size: var(--font-size-1);
32
+ grid-column: 1/-1;
33
+ grid-row: 1;
34
+ inline-size: 100%;
35
+ line-height: var(--font-lineheight-1);
36
+ min-inline-size: 0;
37
+ padding: var(--_field-padding-block) var(--_field-padding-inline);
38
+
39
+ @media (prefers-reduced-motion: no-preference) {
40
+ transition:
41
+ border-color 0.2s cubic-bezier(0.4, 0, 0.2, 1),
42
+ padding-block 0.2s var(--ease-3);
43
+ }
44
+ }
45
+
46
+ /* Required/Invalid */
47
+ &:has(
48
+ :not(:placeholder-shown):invalid,
49
+ :where(
50
+ :placeholder-shown,
51
+ option[value=""]:not(:checked),
52
+ option:checked:not([value=""])
53
+ ):required
54
+ ) {
55
+ .label:after {
56
+ color: var(--red);
57
+ content: "*";
58
+ margin: -0.25em auto auto 0.25em;
59
+ }
60
+ }
61
+
62
+ /* File */
63
+ &:has(input[type="file"]) {
64
+ cursor: pointer;
65
+
66
+ input {
67
+ align-self: flex-start;
68
+ block-size: var(--_height);
69
+ box-shadow: none;
70
+ color: var(--text-color-1);
71
+ cursor: inherit;
72
+ max-inline-size: 100%;
73
+ padding: 0;
74
+ transition: font-size 0.2s var(--ease-3);
75
+
76
+ &::-webkit-file-upload-button,
77
+ &::file-selector-button {
78
+ background-color: var(--surface-tonal);
79
+ border: none;
80
+ block-size: calc(100% - var(--size-2) * 2);
81
+ border-radius: var(--field-border-radius);
82
+ cursor: pointer;
83
+ margin-inline-end: 1ex;
84
+ margin-block-start: var(--size-2);
85
+ margin-inline-start: var(--size-2);
86
+ }
87
+ }
88
+
89
+ /* Variants */
90
+ &.filled {
91
+ input {
92
+ &::-webkit-file-upload-button,
93
+ &::file-selector-button {
94
+ background-color: var(--surface-default);
95
+ block-size: calc(100% - var(--size-2) * 2);
96
+ border-radius: var(--field-border-radius);
97
+ cursor: pointer;
98
+ margin-block-start: var(--size-2);
99
+ }
100
+ }
101
+ }
102
+
103
+ /* Sizes */
104
+ &.small {
105
+ input {
106
+ font-size: var(--font-size-sm);
107
+ &::-webkit-file-upload-button,
108
+ &::file-selector-button {
109
+ block-size: calc(100% - var(--size-2));
110
+ margin-block-start: var(--size-1);
111
+ }
112
+ }
113
+ }
114
+ }
115
+
116
+ /* Autosuggest */
117
+ &:has(input[list]) {
118
+ .label {
119
+ /* Make sure chevron is visible */
120
+ inline-size: calc(100% - var(--size-6));
121
+ }
122
+ }
123
+
124
+ /* Select */
125
+ &:has(select) {
126
+ .label {
127
+ /* Make sure chevron is visible */
128
+ inline-size: calc(100% - var(--size-6));
129
+ }
130
+ }
131
+
132
+ /* Experimental Select */
133
+ &:has(select button) {
134
+ select {
135
+ padding: 0;
136
+
137
+ button {
138
+ outline: 0;
139
+ padding: var(--_field-padding-block) var(--size-8)
140
+ var(--_field-padding-block) var(--_field-padding-inline);
141
+ }
142
+ }
143
+ }
144
+
145
+ /* Non-experimental Select */
146
+ &:has(select):not(:has(button)) {
147
+ select {
148
+ padding: var(--_field-padding-block) var(--size-8)
149
+ var(--_field-padding-block) var(--_field-padding-inline);
150
+ }
151
+ }
152
+
153
+ /* Input - color */
154
+ &:has(input[type="color"]) {
155
+ input {
156
+ appearance: none;
157
+ background: none;
158
+ block-size: var(--_height);
159
+ overflow: hidden;
160
+ padding: 0;
161
+
162
+ &::-webkit-color-swatch {
163
+ border: none;
164
+ }
165
+
166
+ &::-webkit-color-swatch-wrapper {
167
+ padding: 0;
168
+ }
169
+ }
170
+
171
+ .label {
172
+ border: 1px solid var(--field-border-color);
173
+ inline-size: fit-content;
174
+ margin-inline-start: var(--size-2);
175
+ }
176
+ }
177
+
178
+ /* Textarea */
179
+ &:has(textarea) {
180
+ .label {
181
+ align-self: start;
182
+ margin-block-start: var(--_field-padding-block);
183
+ }
184
+ }
185
+
186
+ /*
187
+ * Variant: Outlined
188
+ */
189
+ &:not(.filled) {
190
+ /* Element states */
191
+ &:hover {
192
+ &:not(.error) {
193
+ :where(input, textarea, select) {
194
+ --_border-color: var(--text-color-1);
195
+ }
196
+ }
197
+ }
198
+ }
199
+
200
+ &:not(.filled):focus-within {
201
+ & input,
202
+ & textarea,
203
+ & select {
204
+ border-color: var(--_accent-color);
205
+ outline-offset: -2px;
206
+ outline: 2px solid var(--_accent-color);
207
+ }
208
+ }
209
+
210
+ /* Label */
211
+ .label {
212
+ align-self: center;
213
+ background-color: var(--_bg-color);
214
+ border-radius: var(--field-border-radius);
215
+ color: var(--_label-color);
216
+ border-radius: var(--radius-1);
217
+ display: inline-flex;
218
+ font-size: var(--font-size-md);
219
+ grid-column: 1/-1;
220
+ grid-row: 1;
221
+ inline-size: calc(100% - (var(--field-border-width) * 2));
222
+ margin-inline-start: var(--field-border-width);
223
+ padding-inline: var(--_field-padding-inline);
224
+ pointer-events: none;
225
+ z-index: 1;
226
+
227
+ @media (prefers-reduced-motion: no-preference) {
228
+ transition:
229
+ border-color 0.2s var(--ease-3),
230
+ font-size 0.2s var(--ease-3),
231
+ inline-size 0.05s var(--ease-3),
232
+ margin 0.2s var(--ease-3),
233
+ padding-inline 0.2s var(--ease-3);
234
+ }
235
+ }
236
+
237
+ /*
238
+ * Label transitions
239
+ * Triggered by:
240
+ * - focus
241
+ * - filled form fields (except color inputs)
242
+ * - non-empty select options
243
+ */
244
+ &:focus-within,
245
+ &:has(:where(input:not([type="color"]), textarea):not(:placeholder-shown)),
246
+ &:has(option[value=""]:not(:checked)),
247
+ &:has(option:checked:not([value=""])) {
248
+ .label {
249
+ border-color: transparent;
250
+ color: var(--_accent-color);
251
+ font-size: 0.75rem;
252
+ inline-size: max-content;
253
+ letter-spacing: 0.15px;
254
+ line-height: 1.15;
255
+ margin-block-start: -2.7rem;
256
+ margin-inline-start: var(--_field-padding-inline);
257
+ padding-inline: 0.125rem;
258
+ }
259
+
260
+ /* Neutral label color reset */
261
+ &:not(:focus-within):not(.error) {
262
+ .label {
263
+ color: var(--text-color-2);
264
+ }
265
+ }
266
+
267
+ &:has(textarea) {
268
+ .label {
269
+ margin-block-start: -0.35rem;
270
+ }
271
+
272
+ &.small {
273
+ .label {
274
+ align-self: start;
275
+ margin-block-start: var(--_field-padding-block);
276
+ }
277
+ }
278
+ }
279
+ }
280
+
281
+ /* Supporting text */
282
+ .supporting-text {
283
+ color: var(--_supporting-text-color);
284
+ font-size: var(--font-size-xs);
285
+ grid-row: 3;
286
+ line-height: 1.5;
287
+ margin-inline-start: var(--field-border-width);
288
+ padding-inline: var(--_field-padding-inline);
289
+ z-index: 1;
290
+ }
291
+
292
+ /* Auto-fit */
293
+ &.auto-fit {
294
+ inline-size: auto;
295
+ :where(& input, & textarea) {
296
+ field-sizing: content;
297
+ }
298
+ }
299
+
300
+ /* Validation */
301
+ &.error {
302
+ --_accent-color: var(--color-9);
303
+ --_border-color: var(--color-9);
304
+ --_filled-border-color: var(--color-9);
305
+ --_label-color: var(--color-9);
306
+ --_supporting-text-color: var(--color-9);
307
+ }
308
+
309
+ /*
310
+ * Variant: Filled
311
+ */
312
+ &.filled {
313
+ --_bg-color: var(--surface-tonal);
314
+ *:focus-visible {
315
+ outline: 0;
316
+ }
317
+
318
+ /* Base style */
319
+ & input,
320
+ & textarea,
321
+ & select {
322
+ border-block-end-color: var(--_filled-border-color);
323
+ border-block-start-color: transparent;
324
+ border-inline-color: transparent;
325
+ border-radius: 0;
326
+ }
327
+
328
+ & input[type="color"] {
329
+ border-inline: none;
330
+ }
331
+
332
+ /* Bottom line */
333
+ &::before {
334
+ background-color: var(--_filled-border-color);
335
+ block-size: calc(var(--field-border-width) + 1px);
336
+ content: "";
337
+ inline-size: 100%;
338
+ margin-block-end: calc(-1 * (var(--field-border-width) * 2));
339
+ transform: scaleX(0);
340
+ translate: 0 calc(-1 * (var(--field-border-width) * 2));
341
+ z-index: 1;
342
+
343
+ @media (prefers-reduced-motion: no-preference) {
344
+ transition:
345
+ transform 0.3s var(--ease-3),
346
+ translate 0.2s var(--ease-3);
347
+ }
348
+ }
349
+
350
+ /* Label */
351
+ .label {
352
+ background-color: var(--_bg-color);
353
+ }
354
+
355
+ &:not(:has([disabled], :has(input[type="color"]))) {
356
+ /* Hover */
357
+ &:hover {
358
+ --_bg-color: light-dark(
359
+ oklch(from var(--surface-tonal) calc(l * 0.93) c h),
360
+ oklch(from var(--surface-tonal) calc(l * 1.1) c h)
361
+ );
362
+ }
363
+ }
364
+
365
+ /*
366
+ * Label transitions
367
+ * Triggered by:
368
+ * - focus
369
+ * - filled form fields (except color inputs)
370
+ * - non-empty select options
371
+ */
372
+ &:has(.label) {
373
+ &:focus-within,
374
+ &:has(
375
+ :where(input:not(:where([type="color"])), textarea):not(
376
+ :placeholder-shown
377
+ )
378
+ ),
379
+ &:has(option[value=""]:not(:checked)),
380
+ &:has(option:checked:not([value=""])) {
381
+ :where(input, textarea) {
382
+ padding-block: calc(var(--_field-padding-block) * 1.7)
383
+ calc(var(--_field-padding-block) * 0.3);
384
+ }
385
+
386
+ select > button,
387
+ select:not(:has(button)) {
388
+ padding-block: calc(var(--_field-padding-block) * 1.7)
389
+ calc(var(--_field-padding-block) * 0.3);
390
+ }
391
+
392
+ .label {
393
+ margin-block-start: calc(-1 * var(--size-5));
394
+ margin-inline-start: calc(var(--_field-padding-inline) / 2);
395
+ padding-inline: calc(var(--_field-padding-inline) / 2);
396
+ }
397
+
398
+ &:has(textarea) {
399
+ .label {
400
+ margin-block-start: var(--size-1);
401
+ }
402
+ }
403
+ }
404
+ }
405
+
406
+ /* Element states */
407
+ &:hover {
408
+ &::before {
409
+ transform: scaleX(1);
410
+ }
411
+ }
412
+ &:focus-within {
413
+ & input,
414
+ & textarea,
415
+ & select {
416
+ border-block-end-color: var(--_accent-color);
417
+ }
418
+
419
+ &::before {
420
+ background-color: var(--_accent-color);
421
+ transform: scaleX(1) translateX(0px);
422
+ }
423
+ }
424
+ }
425
+
426
+ /* Disabled */
427
+ &:where(:has([disabled])) {
428
+ &::before {
429
+ display: none;
430
+ }
431
+ :where(input, textarea, select) {
432
+ cursor: not-allowed;
433
+ opacity: 0.7;
434
+
435
+ * {
436
+ pointer-events: none;
437
+ }
438
+ }
439
+ }
440
+
441
+ /* Read-only */
442
+ &:where(:has([readonly])) {
443
+ &::before {
444
+ display: none;
445
+ }
446
+ :where(input, textarea, select) {
447
+ cursor: not-allowed;
448
+
449
+ * {
450
+ pointer-events: none;
451
+ }
452
+ }
453
+ }
454
+
455
+ /* Sizes */
456
+ &.small {
457
+ --_field-padding-block: var(--size-2);
458
+ --_height: var(--field-size-small);
459
+
460
+ &:has(input[type="color"]) {
461
+ .label {
462
+ line-height: 1.5;
463
+ }
464
+ }
465
+
466
+ &:has(textarea) {
467
+ .label {
468
+ align-self: center;
469
+ margin-block-start: unset;
470
+ }
471
+ }
472
+
473
+ /*
474
+ * Label transitions
475
+ * Triggered by:
476
+ * - focus
477
+ * - filled form fields (except color inputs)
478
+ * - non-empty select options
479
+ */
480
+ &:focus-within,
481
+ &:has(
482
+ :where(input:not([type="color"]), textarea):not(:placeholder-shown)
483
+ ),
484
+ &:has(option[value=""]:not(:checked)),
485
+ &:has(option:checked:not([value=""])) {
486
+ .label {
487
+ margin-block-start: -2.2rem;
488
+ margin-inline-start: var(--size-1);
489
+ padding-inline: var(--size-1);
490
+ }
491
+
492
+ &:not(.filled):has(textarea) {
493
+ .label {
494
+ margin-block-start: -0.35rem;
495
+ }
496
+ }
497
+ }
498
+ }
499
+ }
500
+ }
@@ -0,0 +1,40 @@
1
+ @layer components.base {
2
+ :where(.icon-button) {
3
+ --_text-color: inherit;
4
+
5
+ align-items: center;
6
+ aspect-ratio: 1;
7
+ background-color: transparent;
8
+ border: 0;
9
+ border-radius: var(--radius-round);
10
+ display: inline-flex;
11
+ inline-size: var(--size-6);
12
+ justify-content: center;
13
+ padding: 0;
14
+ transform-style: preserve-3d;
15
+
16
+ &:where([disabled]) {
17
+ color: light-dark(rgb(0, 0, 0/0.3), rgb(255, 255, 255/0.26));
18
+ cursor: not-allowed;
19
+ opacity: 0.64;
20
+ }
21
+
22
+ svg {
23
+ max-inline-size: var(--size-5);
24
+ pointer-events: none;
25
+ }
26
+
27
+ /* Ripple effect, utils > index.css */
28
+ &::before {
29
+ --highlight-size: 130%;
30
+ }
31
+
32
+ /* Size */
33
+ &.small {
34
+ inline-size: var(--size-4);
35
+ svg {
36
+ max-inline-size: var(--size-4);
37
+ }
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,21 @@
1
+ @layer components.base {
2
+ :where(.link) {
3
+ color: var(--primary);
4
+ cursor: pointer;
5
+ font-weight: 700;
6
+ text-decoration: underline;
7
+ text-decoration-color: var(--primary);
8
+ text-underline-offset: 2px;
9
+
10
+ &[href] {
11
+ &:hover,
12
+ &:focus-visible {
13
+ color: var(--primary-light);
14
+ }
15
+ }
16
+
17
+ @supports (-moz-appearance: none) {
18
+ text-underline-offset: 2px;
19
+ }
20
+ }
21
+ }