@dxos/ui-theme 0.8.4-main.9be5663bfe → 0.8.4-main.abd8ff62ef
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/lib/browser/index.mjs +63 -57
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +63 -57
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/plugin/node-cjs/main.css +64 -29
- package/dist/plugin/node-cjs/main.css.map +2 -2
- package/dist/plugin/node-cjs/meta.json +1 -1
- package/dist/plugin/node-esm/main.css +64 -29
- package/dist/plugin/node-esm/main.css.map +2 -2
- package/dist/plugin/node-esm/meta.json +1 -1
- package/dist/plugin/node-esm/plugins/ThemePlugin.mjs.map +2 -2
- package/dist/types/src/Theme.stories.d.ts.map +1 -1
- package/dist/types/src/defs.d.ts +1 -1
- package/dist/types/src/defs.d.ts.map +1 -1
- package/dist/types/src/fragments/density.d.ts +1 -4
- package/dist/types/src/fragments/density.d.ts.map +1 -1
- package/dist/types/src/fragments/text.d.ts +0 -1
- package/dist/types/src/fragments/text.d.ts.map +1 -1
- package/dist/types/src/plugins/ThemePlugin.d.ts +1 -1
- package/dist/types/src/plugins/ThemePlugin.d.ts.map +1 -1
- package/dist/types/src/theme/components/card.d.ts.map +1 -1
- package/dist/types/src/theme/components/dialog.d.ts.map +1 -1
- package/dist/types/src/theme/components/icon-button.d.ts +1 -0
- package/dist/types/src/theme/components/icon-button.d.ts.map +1 -1
- package/dist/types/src/theme/components/input.d.ts +8 -8
- package/dist/types/src/theme/components/input.d.ts.map +1 -1
- package/dist/types/src/theme/components/main.d.ts.map +1 -1
- package/dist/types/src/theme/components/scroll-area.d.ts.map +1 -1
- package/dist/types/src/theme/primitives/column.d.ts +22 -5
- package/dist/types/src/theme/primitives/column.d.ts.map +1 -1
- package/dist/types/src/theme/primitives/panel.d.ts.map +1 -1
- package/dist/types/src/theme/theme.d.ts.map +1 -1
- package/dist/types/src/util/hash-styles.d.ts.map +1 -1
- package/dist/types/src/util/mx.d.ts +21 -1
- package/dist/types/src/util/mx.d.ts.map +1 -1
- package/dist/types/src/util/size.d.ts.map +1 -1
- package/dist/types/src/util/valence.d.ts +2 -2
- package/dist/types/src/util/valence.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -16
- package/src/css/components/panel.css +22 -22
- package/src/css/components/selected.css +8 -3
- package/src/css/components/selected.md +101 -0
- package/src/css/components/tag.css +3 -1
- package/src/css/layout/size.css +16 -3
- package/src/css/theme/animation.css +31 -0
- package/src/css/theme/spacing.css +6 -7
- package/src/css/utilities.css +48 -6
- package/src/fragments/AUDIT.md +0 -1
- package/src/fragments/density.ts +8 -5
- package/src/fragments/text.ts +1 -1
- package/src/main.css +36 -2
- package/src/theme/components/card.ts +4 -0
- package/src/theme/components/dialog.ts +5 -3
- package/src/theme/components/icon-button.ts +6 -3
- package/src/theme/components/input.ts +6 -6
- package/src/theme/components/message.ts +5 -5
- package/src/theme/components/popover.ts +1 -1
- package/src/theme/components/scroll-area.ts +10 -5
- package/src/theme/primitives/column.ts +44 -20
- package/src/util/mx.ts +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/ui-theme",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.abd8ff62ef",
|
|
4
4
|
"description": "A set of design system tokens to use with DXOS UI.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -27,13 +27,6 @@
|
|
|
27
27
|
"require": "./dist/plugin/node-cjs/plugins/ThemePlugin.cjs"
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
|
-
"typesVersions": {
|
|
31
|
-
"*": {
|
|
32
|
-
"plugin": [
|
|
33
|
-
"dist/types/src/plugins/ThemePlugin.d.ts"
|
|
34
|
-
]
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
30
|
"files": [
|
|
38
31
|
"dist",
|
|
39
32
|
"src"
|
|
@@ -45,28 +38,28 @@
|
|
|
45
38
|
"@radix-ui/react-slot": "1.1.2",
|
|
46
39
|
"@tailwindcss/forms": "^0.5.9",
|
|
47
40
|
"@tailwindcss/postcss": "^4.2.0",
|
|
48
|
-
"autoprefixer": "^10.
|
|
41
|
+
"autoprefixer": "^10.5.0",
|
|
49
42
|
"esbuild-style-plugin": "^1.6.1",
|
|
50
43
|
"glob": "^7.2.3",
|
|
51
44
|
"globby": "14.1.0",
|
|
52
45
|
"lodash.merge": "^4.6.2",
|
|
53
|
-
"postcss": "^8.
|
|
46
|
+
"postcss": "^8.5.12",
|
|
54
47
|
"postcss-import": "^16.1.0",
|
|
55
48
|
"postcss-nesting": "^13.0.1",
|
|
56
49
|
"tailwind-merge": "^3.5.0",
|
|
57
50
|
"tailwind-scrollbar": "^4.0.0",
|
|
58
51
|
"tailwindcss": "^4.2.0",
|
|
59
52
|
"tailwindcss-radix": "^4.0.2",
|
|
60
|
-
"@dxos/log": "0.8.4-main.
|
|
61
|
-
"@dxos/node-std": "0.8.4-main.
|
|
62
|
-
"@dxos/util": "0.8.4-main.
|
|
53
|
+
"@dxos/log": "0.8.4-main.abd8ff62ef",
|
|
54
|
+
"@dxos/node-std": "0.8.4-main.abd8ff62ef",
|
|
55
|
+
"@dxos/util": "0.8.4-main.abd8ff62ef"
|
|
63
56
|
},
|
|
64
57
|
"devDependencies": {
|
|
65
58
|
"@types/lodash.merge": "^4.6.6",
|
|
66
59
|
"@types/postcss-import": "^14.0.3",
|
|
67
|
-
"esbuild": "0.
|
|
68
|
-
"vite": "^
|
|
69
|
-
"@dxos/ui-types": "0.8.4-main.
|
|
60
|
+
"esbuild": "0.28.0",
|
|
61
|
+
"vite": "^8.0.10",
|
|
62
|
+
"@dxos/ui-types": "0.8.4-main.abd8ff62ef"
|
|
70
63
|
},
|
|
71
64
|
"peerDependencies": {
|
|
72
65
|
"react": "~19.2.3"
|
|
@@ -5,112 +5,112 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
@layer dx-components {
|
|
8
|
-
|
|
8
|
+
[data-hue='neutral'] .dx-panel,
|
|
9
9
|
.dx-panel--neutral {
|
|
10
10
|
@apply bg-neutral-surface text-neutral-surface-text border-neutral-border;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
[data-hue='red'] .dx-panel,
|
|
14
14
|
.dx-panel--red {
|
|
15
15
|
@apply bg-red-surface text-red-surface-text border-red-border;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
[data-hue='orange'] .dx-panel,
|
|
19
19
|
.dx-panel--orange {
|
|
20
20
|
@apply bg-orange-surface text-orange-surface-text border-orange-border;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
[data-hue='amber'] .dx-panel,
|
|
24
24
|
.dx-panel--amber {
|
|
25
25
|
@apply bg-amber-surface text-amber-surface-text border-amber-border;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
[data-hue='yellow'] .dx-panel,
|
|
29
29
|
.dx-panel--yellow {
|
|
30
30
|
@apply bg-yellow-surface text-yellow-surface-text border-yellow-border;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
[data-hue='lime'] .dx-panel,
|
|
34
34
|
.dx-panel--lime {
|
|
35
35
|
@apply bg-lime-surface text-lime-surface-text border-lime-border;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
[data-hue='green'] .dx-panel,
|
|
39
39
|
.dx-panel--green {
|
|
40
40
|
@apply bg-green-surface text-green-surface-text border-green-border;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
[data-hue='emerald'] .dx-panel,
|
|
44
44
|
.dx-panel--emerald {
|
|
45
45
|
@apply bg-emerald-surface text-emerald-surface-text border-emerald-border;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
[data-hue='teal'] .dx-panel,
|
|
49
49
|
.dx-panel--teal {
|
|
50
50
|
@apply bg-teal-surface text-teal-surface-text border-teal-border;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
[data-hue='cyan'] .dx-panel,
|
|
54
54
|
.dx-panel--cyan {
|
|
55
55
|
@apply bg-cyan-surface text-cyan-surface-text border-cyan-border;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
[data-hue='sky'] .dx-panel,
|
|
59
59
|
.dx-panel--sky {
|
|
60
60
|
@apply bg-sky-surface text-sky-surface-text border-sky-border;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
[data-hue='blue'] .dx-panel,
|
|
64
64
|
.dx-panel--blue {
|
|
65
65
|
@apply bg-blue-surface text-blue-surface-text border-blue-border;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
[data-hue='indigo'] .dx-panel,
|
|
69
69
|
.dx-panel--indigo {
|
|
70
70
|
@apply bg-indigo-surface text-indigo-surface-text border-indigo-border;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
[data-hue='violet'] .dx-panel,
|
|
74
74
|
.dx-panel--violet {
|
|
75
75
|
@apply bg-violet-surface text-violet-surface-text border-violet-border;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
[data-hue='purple'] .dx-panel,
|
|
79
79
|
.dx-panel--purple {
|
|
80
80
|
@apply bg-purple-surface text-purple-surface-text border-purple-border;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
[data-hue='fuchsia'] .dx-panel,
|
|
84
84
|
.dx-panel--fuchsia {
|
|
85
85
|
@apply bg-fuchsia-surface text-fuchsia-surface-text border-fuchsia-border;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
[data-hue='pink'] .dx-panel,
|
|
89
89
|
.dx-panel--pink {
|
|
90
90
|
@apply bg-pink-surface text-pink-surface-text border-pink-border;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
[data-hue='rose'] .dx-panel,
|
|
94
94
|
.dx-panel--rose {
|
|
95
95
|
@apply bg-rose-surface text-rose-surface-text border-rose-border;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
[data-hue='info'] .dx-panel,
|
|
99
99
|
.dx-panel--info {
|
|
100
100
|
@apply bg-info-surface text-info-surface-text border-info-border;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
[data-hue='success'] .dx-panel,
|
|
104
104
|
.dx-panel--success {
|
|
105
105
|
@apply bg-success-surface text-success-surface-text border-success-border;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
[data-hue='warning'] .dx-panel,
|
|
109
109
|
.dx-panel--warning {
|
|
110
110
|
@apply bg-warning-surface text-warning-surface-text border-warning-border;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
[data-hue='error'] .dx-panel,
|
|
114
114
|
.dx-panel--error {
|
|
115
115
|
@apply bg-error-surface text-error-surface-text border-error-border;
|
|
116
116
|
}
|
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Selected / Highlighted state utilities
|
|
2
|
+
* Selected / Highlighted state utilities.
|
|
3
|
+
*
|
|
4
|
+
* See `./selected.md` for the ARIA pairing grammar — every class below
|
|
5
|
+
* fires off a specific attribute and silently does nothing without it.
|
|
3
6
|
*/
|
|
4
7
|
|
|
5
8
|
@layer dx-components {
|
|
9
|
+
/* Pure visual affordance, no ARIA pair. Combine with dx-selected or dx-current. */
|
|
6
10
|
.dx-hover {
|
|
7
11
|
@apply cursor-pointer hover:bg-highlight-surface! hover:text-highlight-surface-text!;
|
|
8
12
|
}
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
/* Pairs with Radix-managed `data-highlighted`. Don't set the attribute manually. */
|
|
11
15
|
.dx-highlighted {
|
|
12
16
|
@apply data-[highlighted]:bg-highlight-surface
|
|
13
17
|
data-[highlighted]:text-highlight-surface-text
|
|
14
18
|
hover:data-[highlighted]:bg-highlight-surface-hover;
|
|
15
19
|
}
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
/* Pairs with `aria-current="true|page|…"`. Use for "you are here" navigation. */
|
|
18
22
|
.dx-current {
|
|
19
23
|
@apply dx-ring-pseudo
|
|
20
24
|
aria-[current=true]:bg-highlight-surface aria-[current=true]:text-highlight-surface-text
|
|
21
25
|
aria-[current=true]:after:ring-active-separator!;
|
|
22
26
|
}
|
|
23
27
|
|
|
28
|
+
/* Pairs with `aria-selected`. Use for listbox/option selection (master/detail). */
|
|
24
29
|
.dx-selected {
|
|
25
30
|
@apply aria-selected:bg-selected-surface
|
|
26
31
|
aria-selected:text-selected-surface-text hover:aria-selected:text-selected-surface-text
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# `dx-*` selection / navigation grammar
|
|
2
|
+
|
|
3
|
+
Companion to `selected.css`. The four selection-state utilities below are
|
|
4
|
+
each bound to a specific ARIA attribute (or `data-*`) selector. **The
|
|
5
|
+
class only fires when the matching ARIA attribute is set on the same
|
|
6
|
+
element.** Mismatches (e.g. `dx-current` paired with `aria-selected`)
|
|
7
|
+
silently render as a plain row.
|
|
8
|
+
|
|
9
|
+
| Class | Bound selector | Pair with | Use when |
|
|
10
|
+
| ---------------- | ---------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
11
|
+
| `dx-hover` | `hover:` | (no ARIA — pure visual affordance) | Always, on any clickable row. Adds the cursor + hover bg/text. |
|
|
12
|
+
| `dx-selected` | `aria-selected:` | `aria-selected={boolean}` | A row is "the chosen one" driving a master/detail panel. Listbox / option pattern. Multi-select OK. |
|
|
13
|
+
| `dx-current` | `aria-[current=true]:` | `aria-current='true'` | A row is "where you are" in a navigation set (current page, current step). At most one current per group. The CSS variant fires only on `aria-current='true'`, so use that literal even on `<a>`/nav links. |
|
|
14
|
+
| `dx-highlighted` | `data-[highlighted]:` | Radix `data-highlighted` (managed) | A Radix-managed transient highlight (menu / combobox active option). Don't set the attribute manually. |
|
|
15
|
+
|
|
16
|
+
## Rules
|
|
17
|
+
|
|
18
|
+
1. **Never combine `dx-selected` and `dx-current` on the same element**
|
|
19
|
+
unless you also set both `aria-selected` and `aria-current`. They
|
|
20
|
+
express different things (chosen vs you-are-here) and the visual
|
|
21
|
+
weight is similar enough that combining them defeats both.
|
|
22
|
+
2. **`aria-pressed`, `aria-checked`, `aria-expanded`, `aria-disabled`
|
|
23
|
+
are not selection-row attributes.** None of the `dx-*` selection
|
|
24
|
+
utilities pair with them. Toggle buttons (mute/unmute) want
|
|
25
|
+
`aria-pressed`; a selection row wants `aria-selected`.
|
|
26
|
+
3. **`aria-selected` is only valid on roles that admit it** — `option`,
|
|
27
|
+
`tab`, `gridcell`, `row`, `treeitem`, `columnheader`, `rowheader`.
|
|
28
|
+
On a plain `<button>` inside a `<ul role='listbox'>`, give the button
|
|
29
|
+
`role='option'` so assistive tech sees the attribute.
|
|
30
|
+
4. **`dx-active` does not exist.** If you see it in code it's a no-op
|
|
31
|
+
string. Use `dx-selected` (selection) or `dx-current` (navigation)
|
|
32
|
+
instead.
|
|
33
|
+
5. **Set ARIA before adding the class.** The class is inert without
|
|
34
|
+
the attribute; it's not a fallback styler. Reviewers should reject
|
|
35
|
+
PRs that add `dx-selected` without `aria-selected`.
|
|
36
|
+
|
|
37
|
+
## Canonical patterns
|
|
38
|
+
|
|
39
|
+
### Selectable row in a list (master/detail)
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
<ul role='listbox' aria-label='…'>
|
|
43
|
+
{items.map((item) => (
|
|
44
|
+
<li key={item.id} role='presentation'>
|
|
45
|
+
<button
|
|
46
|
+
type='button'
|
|
47
|
+
role='option'
|
|
48
|
+
aria-selected={item.id === selectedId}
|
|
49
|
+
className='dx-hover dx-selected'
|
|
50
|
+
onClick={() => onSelect(item.id)}
|
|
51
|
+
>
|
|
52
|
+
{item.label}
|
|
53
|
+
</button>
|
|
54
|
+
</li>
|
|
55
|
+
))}
|
|
56
|
+
</ul>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### "You are here" in a navigation list
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
<nav>
|
|
63
|
+
<ul>
|
|
64
|
+
{pages.map((page) => (
|
|
65
|
+
<li key={page.href}>
|
|
66
|
+
<a
|
|
67
|
+
href={page.href}
|
|
68
|
+
aria-current={page.href === currentHref ? 'true' : undefined}
|
|
69
|
+
className='dx-hover dx-current'
|
|
70
|
+
>
|
|
71
|
+
{page.label}
|
|
72
|
+
</a>
|
|
73
|
+
</li>
|
|
74
|
+
))}
|
|
75
|
+
</ul>
|
|
76
|
+
</nav>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Toggle button (NOT a row)
|
|
80
|
+
|
|
81
|
+
Don't reach for `dx-selected` here. Toggle buttons want their own
|
|
82
|
+
visual treatment via `aria-pressed:` variants — out of scope for this
|
|
83
|
+
file.
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
<button type='button' aria-pressed={muted} onClick={toggleMute}>
|
|
87
|
+
{muted ? 'Unmute' : 'Mute'}
|
|
88
|
+
</button>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Enforcing the grammar
|
|
92
|
+
|
|
93
|
+
A future ESLint rule could flag:
|
|
94
|
+
|
|
95
|
+
- `dx-selected` without `aria-selected` on the same element.
|
|
96
|
+
- `dx-current` without `aria-current` on the same element.
|
|
97
|
+
- `dx-active` literal anywhere.
|
|
98
|
+
|
|
99
|
+
Until that exists, reviewers and the `react-ui-list` `RowList` /
|
|
100
|
+
`CardList` containers (which set both attribute and class together)
|
|
101
|
+
are the enforcement.
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
|
|
12
12
|
.dx-tag--anchor {
|
|
13
13
|
/* NOTE: Margin offsets padding so that border is flush with text. This should only apply to anchor tags inside of Codemirror. */
|
|
14
|
-
@apply inline cursor-pointer -mx-[
|
|
14
|
+
@apply inline cursor-pointer -mx-[3px] px-[2px] py-0.5 border rounded-xs transition-colors;
|
|
15
|
+
/** TODO(burdon): Configure secondary color. */
|
|
16
|
+
@apply bg-group-surface text-sky-surface-text border-sky-border;
|
|
15
17
|
|
|
16
18
|
&:hover {
|
|
17
19
|
@apply bg-hover-surface;
|
package/src/css/layout/size.css
CHANGED
|
@@ -3,15 +3,28 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
@layer dx-components {
|
|
6
|
-
/**
|
|
7
|
-
* Registers the element as a size query container.
|
|
6
|
+
/**
|
|
7
|
+
* Registers the element as a size query container.
|
|
8
8
|
* Children can use @container queries to apply styles based on the container's dimensions (both width and height).
|
|
9
|
-
* Also enables children to use cqi units (e.g., max-w-[100cqi])
|
|
9
|
+
* Also enables children to use cqi/cqb units (e.g., max-w-[100cqi]).
|
|
10
|
+
* NOTE: `container-type: size` implies layout/size containment, which breaks CodeMirror's
|
|
11
|
+
* coordinate measurement (causes blank viewport sections during scroll until a click forces
|
|
12
|
+
* a re-measure). For editor content where only inline (width-based) queries are needed,
|
|
13
|
+
* use `.dx-inline-size-container` instead.
|
|
10
14
|
*/
|
|
11
15
|
.dx-size-container {
|
|
12
16
|
container-type: size;
|
|
13
17
|
}
|
|
14
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Inline-only size query container. Provides cqi units for children without the layout
|
|
21
|
+
* containment side-effects of `container-type: size`. Use this in CodeMirror content
|
|
22
|
+
* wrappers where size containment would break viewport measurement.
|
|
23
|
+
*/
|
|
24
|
+
.dx-inline-size-container {
|
|
25
|
+
container-type: inline-size;
|
|
26
|
+
}
|
|
27
|
+
|
|
15
28
|
/**
|
|
16
29
|
* Document width.
|
|
17
30
|
*/
|
|
@@ -227,3 +227,34 @@
|
|
|
227
227
|
}
|
|
228
228
|
--animate-blink: blink 1s step-start infinite;
|
|
229
229
|
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Shimmer (text)
|
|
233
|
+
* Sweeps a brighter band across text via mask alpha — preserves the consumer's color.
|
|
234
|
+
* Translates exactly one tile period (2× element width) per cycle so the loop seam is invisible.
|
|
235
|
+
*/
|
|
236
|
+
@keyframes shimmer-text {
|
|
237
|
+
from {
|
|
238
|
+
mask-position-x: 100%;
|
|
239
|
+
-webkit-mask-position-x: 100%;
|
|
240
|
+
}
|
|
241
|
+
to {
|
|
242
|
+
mask-position-x: -100%;
|
|
243
|
+
-webkit-mask-position-x: -100%;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Honor user reduced-motion preference for decorative animations.
|
|
249
|
+
* Functional transitions (fade/slide/toast/blink) are intentionally excluded —
|
|
250
|
+
* suppressing them would hide UI state changes.
|
|
251
|
+
*/
|
|
252
|
+
@media (prefers-reduced-motion: reduce) {
|
|
253
|
+
.animate-halo-pulse,
|
|
254
|
+
.animate-spin-slow,
|
|
255
|
+
.animate-trail,
|
|
256
|
+
.animate-trail-offset,
|
|
257
|
+
.animate-shimmer {
|
|
258
|
+
animation: none;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
@@ -9,13 +9,12 @@
|
|
|
9
9
|
/** Minimum inset from the viewport edge for floating surfaces. */
|
|
10
10
|
--spacing-screen-border: 2rem;
|
|
11
11
|
|
|
12
|
-
--spacing-popover-
|
|
12
|
+
--spacing-popover-default-width: 20rem;
|
|
13
|
+
--spacing-popover-min-width: 16rem;
|
|
13
14
|
|
|
14
15
|
--spacing-document-max-width: 50rem;
|
|
15
16
|
--spacing-document-width: calc(50rem - env(safe-area-inset-left) - env(safe-area-inset-right));
|
|
16
17
|
|
|
17
|
-
--spacing-popover-min-width: 16rem;
|
|
18
|
-
|
|
19
18
|
--spacing-card-default-width: 20rem;
|
|
20
19
|
--spacing-card-min-width: 18rem;
|
|
21
20
|
--spacing-card-max-width: 22rem;
|
|
@@ -95,7 +94,7 @@
|
|
|
95
94
|
--dx-input-fine: var(--dx-lacuna-3);
|
|
96
95
|
--dx-input-coarse: var(--dx-lacuna-4);
|
|
97
96
|
|
|
98
|
-
--dx-default-icons-size:
|
|
97
|
+
--dx-default-icons-size: 1rem; /* size=4 */
|
|
99
98
|
}
|
|
100
99
|
|
|
101
100
|
[data-grid-focus-indicator-variant='stack'] {
|
|
@@ -116,12 +115,12 @@
|
|
|
116
115
|
--dx-toolbar-size: var(--dx-rail-action); /* 40px */
|
|
117
116
|
--dx-statusbar-size: var(--dx-rail-item); /* 32px */
|
|
118
117
|
|
|
119
|
-
/** NOTE:
|
|
120
|
-
--dx-nav-sidebar-size:
|
|
118
|
+
/** NOTE: Sidebar optimized to show plank + companion with sidebar open on 16" MBP. */
|
|
119
|
+
--dx-nav-sidebar-size: 350px;
|
|
121
120
|
--dx-complementary-sidebar-size: 25rem;
|
|
122
121
|
--dx-drawer-size: 50dvh;
|
|
123
122
|
|
|
124
|
-
--dx-l0-size:
|
|
123
|
+
--dx-l0-size: 72px;
|
|
125
124
|
--dx-l0-avatar-size: 3rem;
|
|
126
125
|
--dx-l1-size: calc(var(--dx-nav-sidebar-size) - var(--dx-l0-size));
|
|
127
126
|
--dx-r0-size: var(--dx-rail-size);
|
package/src/css/utilities.css
CHANGED
|
@@ -31,17 +31,17 @@
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
34
|
+
* Container that fills the available space (extends dx-expander with overflow clipping).
|
|
35
35
|
*/
|
|
36
|
-
@utility dx-
|
|
37
|
-
@apply
|
|
36
|
+
@utility dx-container {
|
|
37
|
+
@apply dx-expander overflow-hidden;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
41
|
+
* Column that fills the available space (extends dx-expander with overflow clipping).
|
|
42
42
|
*/
|
|
43
|
-
@utility dx-
|
|
44
|
-
@apply
|
|
43
|
+
@utility dx-column {
|
|
44
|
+
@apply flex-1 min-w-0 w-full;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
@@ -74,3 +74,45 @@
|
|
|
74
74
|
@apply relative after:content-[""] after:absolute after:inset-0 after:rounded-[inherit]
|
|
75
75
|
after:pointer-events-none after:ring after:ring-inset after:ring-transparent;
|
|
76
76
|
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Shimmer text — animates opacity left → right across the contained text.
|
|
80
|
+
* See @keyframes shimmer-text in theme/animation.css for the keyframe definition.
|
|
81
|
+
* Geometry: mask-size 200% 100% with mask-repeat: repeat-x means each tile is
|
|
82
|
+
* 2× the element width; the keyframe slides mask-position-x by 200% (one full
|
|
83
|
+
* tile period), giving a seamless loop. The 5-stop gradient (0.4 → 1.0 → 0.4)
|
|
84
|
+
* produces a single bright pulse per cycle that traverses left → right during
|
|
85
|
+
* the first half, with a brief calm interval during the second half.
|
|
86
|
+
*/
|
|
87
|
+
@utility shimmer-text {
|
|
88
|
+
mask-image: linear-gradient(
|
|
89
|
+
90deg,
|
|
90
|
+
rgba(0, 0, 0, 0.4) 0%,
|
|
91
|
+
rgba(0, 0, 0, 0.4) 30%,
|
|
92
|
+
rgba(0, 0, 0, 1) 50%,
|
|
93
|
+
rgba(0, 0, 0, 0.4) 70%,
|
|
94
|
+
rgba(0, 0, 0, 0.4) 100%
|
|
95
|
+
);
|
|
96
|
+
-webkit-mask-image: linear-gradient(
|
|
97
|
+
90deg,
|
|
98
|
+
rgba(0, 0, 0, 0.4) 0%,
|
|
99
|
+
rgba(0, 0, 0, 0.4) 30%,
|
|
100
|
+
rgba(0, 0, 0, 1) 50%,
|
|
101
|
+
rgba(0, 0, 0, 0.4) 70%,
|
|
102
|
+
rgba(0, 0, 0, 0.4) 100%
|
|
103
|
+
);
|
|
104
|
+
mask-size: 200% 100%;
|
|
105
|
+
-webkit-mask-size: 200% 100%;
|
|
106
|
+
mask-repeat: repeat-x;
|
|
107
|
+
-webkit-mask-repeat: repeat-x;
|
|
108
|
+
animation: shimmer-text 2s linear infinite;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@media (prefers-reduced-motion: reduce) {
|
|
112
|
+
.shimmer-text {
|
|
113
|
+
animation: none;
|
|
114
|
+
mask-image: none;
|
|
115
|
+
-webkit-mask-image: none;
|
|
116
|
+
opacity: 0.6;
|
|
117
|
+
}
|
|
118
|
+
}
|
package/src/fragments/AUDIT.md
CHANGED
|
@@ -55,4 +55,3 @@ External packages importing fragment definitions from `ui-theme/src/fragments`.
|
|
|
55
55
|
|
|
56
56
|
- `subtleHover` from `hover.ts`
|
|
57
57
|
- `hoverableOpenControlItem`, `groupHoverControlItemWithTransition` from `hover.ts` (only 2-3 uses)
|
|
58
|
-
- `descriptionTextPrimary` from `text.ts` (only 1 use)
|
package/src/fragments/density.ts
CHANGED
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
import { type Density } from '@dxos/ui-types';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const fineBlockSize = 'min-h-[2.5rem] pointer-fine:min-h-[2rem]';
|
|
8
|
+
const coarseBlockSize = 'min-h-[2.5rem]';
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
const fineDimensions = `${fineBlockSize} px-2`;
|
|
11
|
+
const coarseDimensions = `${coarseBlockSize} px-3`;
|
|
12
12
|
|
|
13
|
-
export const
|
|
13
|
+
export const densityDimensions = (density: Density = 'fine') =>
|
|
14
|
+
density === 'fine' ? fineDimensions : coarseDimensions;
|
|
15
|
+
|
|
16
|
+
export const densityBlockSize = (density: Density = 'fine') => (density === 'fine' ? fineBlockSize : coarseBlockSize);
|
package/src/fragments/text.ts
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// TODO(burdon): Replace with Message component.
|
|
6
6
|
export const descriptionMessage = 'text-description border border-dashed border-separator rounded-sm p-4';
|
package/src/main.css
CHANGED
|
@@ -11,7 +11,17 @@
|
|
|
11
11
|
*/
|
|
12
12
|
@layer properties, theme, dx-tokens, user-tokens, base, tw-base, dx-base, components, tw-components, dx-components, utilities;
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* `source(none)` disables Tailwind 4's automatic content discovery (which
|
|
16
|
+
* scans the project root, including `publicDir`). With auto-detection on,
|
|
17
|
+
* every write to `public/icons.svg` from `vite-plugin-icons` triggers a
|
|
18
|
+
* Tailwind CSS regeneration, which invalidates `main.css` through its
|
|
19
|
+
* import graph and produces a 3–5-ping HMR storm per icon-sprite write
|
|
20
|
+
* during cold-start (icons land in tight bursts as plugin chunks stream
|
|
21
|
+
* in). Explicit `@source` directives below replace the auto-scan with a
|
|
22
|
+
* stable, source-only set.
|
|
23
|
+
*/
|
|
24
|
+
@import 'tailwindcss' source(none);
|
|
15
25
|
|
|
16
26
|
/* @theme extensions */
|
|
17
27
|
@import './css/theme/animation.css';
|
|
@@ -54,7 +64,24 @@
|
|
|
54
64
|
@import './css/integrations/tldraw.css';
|
|
55
65
|
|
|
56
66
|
/**
|
|
57
|
-
*
|
|
67
|
+
* With `source(none)` on the Tailwind import above, these are the *only*
|
|
68
|
+
* paths Tailwind scans for utility classes. Cover every workspace source
|
|
69
|
+
* directory so lazy-loaded plugin / UI / SDK chunks don't surface new
|
|
70
|
+
* utilities mid-session, and root-level HTML entrypoints (index.html,
|
|
71
|
+
* internal.html, …) are visible too.
|
|
72
|
+
*
|
|
73
|
+
* Paths are relative to this file (`packages/ui/ui-theme/src/main.css`):
|
|
74
|
+
* ../../../ → `packages/`
|
|
75
|
+
* ../../../../tools/ → `tools/`
|
|
76
|
+
*
|
|
77
|
+
* Tailwind ignores `node_modules` and common build/output dirs by default,
|
|
78
|
+
* so a broad workspace glob is safe.
|
|
79
|
+
*/
|
|
80
|
+
@source "../../../**/*.{ts,tsx,html}";
|
|
81
|
+
@source "../../../../tools/**/*.{ts,tsx,html}";
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Force-emit CSS variables for the full color palette for all:
|
|
58
85
|
* --color-{hue}-{shade}
|
|
59
86
|
* --color-{hue}-{style}
|
|
60
87
|
*/
|
|
@@ -64,6 +91,13 @@
|
|
|
64
91
|
@source inline("bg-{info,success,warning,error}-{fill,surface,surface-text,text,border}");
|
|
65
92
|
@source inline("border-{info,success,warning,error}-border");
|
|
66
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Force-emit tokens consumed by web components / .pcss files outside the
|
|
96
|
+
* Tailwind source-scan graph (e.g. lit-grid's dx-grid.pcss uses
|
|
97
|
+
* var(--color-grid-line)).
|
|
98
|
+
*/
|
|
99
|
+
@source inline("bg-grid-{surface,highlight,comment,comment-active,hover-overlay,selection-overlay,line,focus-indicator}");
|
|
100
|
+
|
|
67
101
|
/**
|
|
68
102
|
* Plugins must come after all imports.
|
|
69
103
|
*/
|
|
@@ -73,6 +73,9 @@ const cardLink: ComponentFunction<CardStyleProps> = (_props, ...etc) =>
|
|
|
73
73
|
const cardLinkLabel: ComponentFunction<CardStyleProps> = (_props, ...etc) =>
|
|
74
74
|
mx('dx-card__link-label min-w-0 flex-1 truncate', ...etc);
|
|
75
75
|
|
|
76
|
+
const cardRow: ComponentFunction<CardStyleProps> = (_, ...etc) =>
|
|
77
|
+
mx('dx-card__row col-span-3 grid grid-cols-subgrid', ...etc);
|
|
78
|
+
|
|
76
79
|
const cardIconBlock: ComponentFunction<CardStyleProps> = ({ padding }, ...etc) =>
|
|
77
80
|
mx(
|
|
78
81
|
'dx-card__icon-block grid h-[var(--dx-rail-item)] w-[var(--dx-rail-item)] place-items-center',
|
|
@@ -85,6 +88,7 @@ export const cardTheme: Theme<CardStyleProps> = {
|
|
|
85
88
|
toolbar: cardToolbar,
|
|
86
89
|
title: cardTitle,
|
|
87
90
|
content: cardContent,
|
|
91
|
+
row: cardRow,
|
|
88
92
|
heading: cardHeading,
|
|
89
93
|
text: cardText,
|
|
90
94
|
'text-span': cardTextSpan,
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { type ComponentFunction, type Elevation, type Theme } from '@dxos/ui-types';
|
|
6
6
|
|
|
7
7
|
import { mx } from '../../util';
|
|
8
|
+
import { withColumn } from '../primitives/column';
|
|
8
9
|
|
|
9
10
|
export type DialogSize = 'sm' | 'md' | 'lg' | 'xl';
|
|
10
11
|
|
|
@@ -35,12 +36,13 @@ export const dialogContent: ComponentFunction<DialogStyleProps> = ({ inOverlayLa
|
|
|
35
36
|
};
|
|
36
37
|
|
|
37
38
|
export const dialogHeader: ComponentFunction<DialogStyleProps> = (_props, ...etc) =>
|
|
38
|
-
mx('dx-dialog__header flex pb-4 items-center justify-between', ...etc);
|
|
39
|
+
mx('dx-dialog__header flex pb-4 items-center justify-between', withColumn.center(), ...etc);
|
|
39
40
|
|
|
40
|
-
export const dialogBody: ComponentFunction<DialogStyleProps> = (_props, ...etc) =>
|
|
41
|
+
export const dialogBody: ComponentFunction<DialogStyleProps> = (_props, ...etc) =>
|
|
42
|
+
mx('dx-dialog__body dx-expander', withColumn.propagate(), ...etc);
|
|
41
43
|
|
|
42
44
|
export const dialogActionBar: ComponentFunction<DialogStyleProps> = (_props, ...etc) =>
|
|
43
|
-
mx('dx-dialog__actionbar flex items-center pt-4 gap-2 dx-density-coarse', ...etc);
|
|
45
|
+
mx('dx-dialog__actionbar flex items-center pt-4 gap-2 dx-density-coarse', withColumn.center(), ...etc);
|
|
44
46
|
|
|
45
47
|
export const dialogTitle: ComponentFunction<DialogStyleProps> = ({ srOnly }, ...etc) =>
|
|
46
48
|
mx('dx-dialog__title', srOnly && 'sr-only', ...etc);
|