@tensor_1/tokens 2.46.0 → 2.48.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 (66) hide show
  1. package/build/css/components.css +1 -1
  2. package/build/css/styles.css +1 -1
  3. package/package.json +1 -1
  4. package/styles/components/alert.css +6 -4
  5. package/styles/components/app-shell.css +40 -0
  6. package/styles/components/arrival.css +7 -1
  7. package/styles/components/attachment.css +4 -1
  8. package/styles/components/audit-log.css +29 -0
  9. package/styles/components/breadcrumbs.css +2 -0
  10. package/styles/components/busy-region.css +55 -0
  11. package/styles/components/button.css +42 -6
  12. package/styles/components/card.css +10 -0
  13. package/styles/components/change-highlight.css +58 -0
  14. package/styles/components/checkbox.css +18 -0
  15. package/styles/components/code-display.css +43 -0
  16. package/styles/components/combobox.css +4 -1
  17. package/styles/components/command-palette.css +16 -2
  18. package/styles/components/contact-card.css +17 -6
  19. package/styles/components/count.css +23 -0
  20. package/styles/components/data-workspace.css +42 -0
  21. package/styles/components/date-picker.css +14 -1
  22. package/styles/components/detail-layout.css +9 -0
  23. package/styles/components/diff-viewer.css +5 -0
  24. package/styles/components/display-preferences.css +38 -0
  25. package/styles/components/editorial-home.css +24 -2
  26. package/styles/components/flow.css +5 -0
  27. package/styles/components/heartbeat.css +8 -0
  28. package/styles/components/icon.css +14 -0
  29. package/styles/components/inline-edit.css +19 -3
  30. package/styles/components/input.css +62 -0
  31. package/styles/components/lightbox.css +13 -0
  32. package/styles/components/list.css +2 -0
  33. package/styles/components/match-review.css +40 -0
  34. package/styles/components/media.css +4 -2
  35. package/styles/components/metric-input.css +3 -1
  36. package/styles/components/modal.css +4 -0
  37. package/styles/components/page-header.css +12 -0
  38. package/styles/components/pagination.css +2 -0
  39. package/styles/components/popover.css +4 -0
  40. package/styles/components/print-layout.css +177 -0
  41. package/styles/components/progress.css +7 -0
  42. package/styles/components/qr-code.css +30 -0
  43. package/styles/components/qr-scanner.css +61 -0
  44. package/styles/components/relationship-graph.css +43 -8
  45. package/styles/components/rule-builder.css +2 -1
  46. package/styles/components/save-status.css +5 -0
  47. package/styles/components/scheduling-calendar.css +82 -1
  48. package/styles/components/search-suggest.css +2 -0
  49. package/styles/components/segmented.css +10 -1
  50. package/styles/components/select.css +11 -0
  51. package/styles/components/sidebar.css +51 -1
  52. package/styles/components/sortable-list.css +42 -0
  53. package/styles/components/spinner.css +5 -0
  54. package/styles/components/stat-tile.css +36 -12
  55. package/styles/components/states.css +5 -0
  56. package/styles/components/status-pill.css +28 -6
  57. package/styles/components/steps.css +2 -0
  58. package/styles/components/table-toolbar.css +1 -1
  59. package/styles/components/table.css +18 -5
  60. package/styles/components/tabs.css +8 -3
  61. package/styles/components/tag-input.css +21 -0
  62. package/styles/components/textarea.css +3 -0
  63. package/styles/components/toast.css +12 -0
  64. package/styles/components/tree.css +3 -1
  65. package/styles/components/view-menu.css +3 -0
  66. package/styles/motion.css +18 -0
@@ -28,12 +28,32 @@
28
28
  .uix-pill--p4 { --tone-bg: var(--uix-info-bg); --tone-fg: var(--uix-info-text); --tone-dot: var(--uix-info); }
29
29
  .uix-pill--p5 { --tone-bg: var(--uix-bg-active); --tone-fg: var(--uix-text-hushed); --tone-dot: var(--uix-text-muted); }
30
30
 
31
- /* outline treatment — transparent fill, tone-tinted border, tone-colored text. The border tints
32
- the tone hue (--tone-fg) at 40%; neutral/muted use the structural borders, critical reads strongest. */
33
- .uix-pill--outline { background: transparent; border: 1px solid var(--tone-line, color-mix(in srgb, var(--tone-fg) 40%, transparent)); }
34
- .uix-pill--outline.uix-pill--neutral { --tone-line: var(--uix-border-strong); }
35
- .uix-pill--outline.uix-pill--muted { --tone-line: var(--uix-border); }
36
- .uix-pill--outline.uix-pill--critical { color: var(--uix-danger-text); --tone-dot: var(--uix-danger); --tone-line: color-mix(in srgb, var(--uix-danger) 60%, transparent); }
31
+ /* in flight (HAR-1563): the same blue as info, under the name the colour policy uses */
32
+ .uix-pill--progress { --tone-bg: var(--uix-info-bg); --tone-fg: var(--uix-info-text); --tone-dot: var(--uix-info); }
33
+
34
+ /* each tone's solid, for the quiet treatments below, where the dot is the only hue (HAR-1563) */
35
+ .uix-pill--neutral, .uix-pill--muted, .uix-pill--p5 { --tone-solid: var(--uix-neutral-solid); }
36
+ /* the pale hues mix 40 % of their text role in, so a light-mode dot clears 3:1 on the surface
37
+ (success 2.54 -> 3.38, warning 2.15 -> 3.32, amber 2.94 -> 4.09) and a dark one stays calm */
38
+ .uix-pill--success, .uix-pill--sla-ok { --tone-solid: color-mix(in srgb, var(--uix-success-solid) 60%, var(--uix-success-text)); }
39
+ .uix-pill--info, .uix-pill--progress, .uix-pill--p4 { --tone-solid: var(--uix-info-solid); }
40
+ .uix-pill--warning, .uix-pill--p2 { --tone-solid: color-mix(in srgb, var(--uix-warning-solid) 60%, var(--uix-warning-text)); }
41
+ .uix-pill--p3 { --tone-solid: color-mix(in srgb, var(--uix-amber) 60%, var(--uix-amber-text)); }
42
+ .uix-pill--danger, .uix-pill--critical, .uix-pill--p1 { --tone-solid: var(--uix-danger-solid); }
43
+ .uix-pill--attention, .uix-pill--sla-at-risk { --tone-solid: var(--uix-attention-solid); }
44
+ .uix-pill--overdue, .uix-pill--sla-breached { --tone-solid: var(--uix-overdue-solid); }
45
+
46
+ /* dot treatment (HAR-1563) — for dense tables: no fill and no padding, a neutral label, and the
47
+ tone only in the dot. The label is the meaning; the dot is the glance. */
48
+ .uix-pill--dot { background: transparent; padding-inline: 0; color: var(--uix-neutral-text); }
49
+ .uix-pill--dot .uix-pill__dot { background: var(--tone-solid, var(--uix-neutral-solid)); }
50
+
51
+ /* outline treatment (HAR-1563) — a neutral hairline, a hushed label and the tone's dot. Only
52
+ critical keeps a toned border, so the one thing that needs action still stands out. */
53
+ .uix-pill--outline { background: transparent; border: 1px solid var(--uix-neutral-border); color: var(--uix-neutral-text); }
54
+ .uix-pill--outline .uix-pill__dot { background: var(--tone-solid, var(--uix-neutral-solid)); }
55
+ .uix-pill--outline.uix-pill--muted { border-color: var(--uix-border); }
56
+ .uix-pill--outline.uix-pill--critical { border-color: var(--uix-danger-solid); color: var(--uix-danger-text); }
37
57
  }
38
58
 
39
59
  /* Sizes (HAR-1614): sm for dense cells, lg for a page header. The default is unchanged. */
@@ -42,4 +62,6 @@
42
62
  .uix-pill--sm .uix-pill__dot { width: 6px; height: 6px; }
43
63
  .uix-pill--lg { padding: var(--uix-space-2) var(--uix-space-4); font-size: var(--uix-text-body); }
44
64
  .uix-pill--lg .uix-pill__dot { width: 9px; height: 9px; }
65
+ /* the dot treatment has no box at any size: its label lines up with the cell's other text */
66
+ .uix-pill--dot:is(.uix-pill--sm, .uix-pill--lg) { padding-inline: 0; }
45
67
  }
@@ -32,6 +32,8 @@
32
32
  .uix-steps--horizontal > .uix-step > .uix-step__text { flex: 0 0 auto; max-width: 12rem; }
33
33
  .uix-step[data-state="waiting"] .uix-step__marker { border-style: dashed; border-color: var(--uix-warning-border); color: var(--uix-warning-text); }
34
34
  .uix-step[data-state="error"] { color: var(--uix-text); }
35
+ /* the error marker is the icon set's X (HAR-1576), the size of the done check */
36
+ .uix-step__marker > .uix-icon { width: 12px; height: 12px; }
35
37
  .uix-step[data-state="error"] .uix-step__marker { background: var(--uix-danger-bg); border-color: var(--uix-danger-border); color: var(--uix-danger-text); }
36
38
  /* vertical (and horizontal below 40rem): a column, the connector a line under the marker */
37
39
  .uix-steps--vertical { flex-direction: column; gap: 0; }
@@ -60,7 +60,7 @@
60
60
  /* FilterEditor (React, HAR-1365): typed filter content inside .uix-filter-popover */
61
61
  @layer uix.components {
62
62
  .uix-filter-editor { width: min(22rem, calc(100vw - 4rem)); min-width: 0; gap: var(--uix-space-3); }
63
- .uix-filter-editor[data-kind="number"] .uix-filter-editor__row > .uix-select { flex-basis: 100%; }
63
+ .uix-filter-editor:is([data-kind="number"], [data-kind="date"]) .uix-filter-editor__row > .uix-select { flex-basis: 100%; }
64
64
  .uix-filter-editor__label { font-weight: 600; color: var(--uix-text); }
65
65
  .uix-filter-editor__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--uix-space-2); }
66
66
  .uix-filter-editor__row > .uix-input, .uix-filter-editor__row > .uix-select { flex: 1 1 8rem; min-width: 0; }
@@ -16,9 +16,14 @@
16
16
  }
17
17
  .uix-table th[data-sort] { cursor: pointer; user-select: none; }
18
18
  .uix-table th[data-sort]:hover { color: var(--uix-text); }
19
- .uix-table th[data-sort]::after { content: " ↕"; opacity: .35; }
20
- .uix-table th[aria-sort="ascending"]::after { content: " ↑"; opacity: 1; color: var(--uix-accent); }
21
- .uix-table th[aria-sort="descending"]::after { content: " ↓"; opacity: 1; color: var(--uix-accent); }
19
+ /* sort arrows: Lucide arrow-up-down / arrow-up / arrow-down through a mask in currentColor, so they
20
+ match the icon set and follow the theme (HAR-1576; scripts/glyph-mask.mjs prints the urls) */
21
+ .uix-table th[data-sort]::after {
22
+ content: ""; display: inline-block; width: 1em; height: 1em; margin-inline-start: var(--uix-space-1); vertical-align: -.15em;
23
+ background: currentColor; opacity: .35; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m21 16-4 4-4-4'/%3E%3Cpath d='M17 20V4'/%3E%3Cpath d='m3 8 4-4 4 4'/%3E%3Cpath d='M7 4v16'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m21 16-4 4-4-4'/%3E%3Cpath d='M17 20V4'/%3E%3Cpath d='m3 8 4-4 4 4'/%3E%3Cpath d='M7 4v16'/%3E%3C/svg%3E") center / contain no-repeat;
24
+ }
25
+ .uix-table th[aria-sort="ascending"]::after { opacity: 1; color: var(--uix-accent); -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 7-7 7 7'/%3E%3Cpath d='M12 19V5'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 7-7 7 7'/%3E%3Cpath d='M12 19V5'/%3E%3C/svg%3E"); }
26
+ .uix-table th[aria-sort="descending"]::after { opacity: 1; color: var(--uix-accent); -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 5v14'/%3E%3Cpath d='m19 12-7 7-7-7'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 5v14'/%3E%3Cpath d='m19 12-7 7-7-7'/%3E%3C/svg%3E"); }
22
27
  /* multi-column sort ordinal (⇧+click adds a secondary key) */
23
28
  .uix-table th[data-sort-order]::before { content: attr(data-sort-order); display: inline-block; margin-right: var(--uix-space-1); font-size: var(--uix-text-eyebrow); font-variant-numeric: tabular-nums; color: var(--uix-accent); }
24
29
 
@@ -67,6 +72,9 @@
67
72
  .uix-table--pinned-col th:first-child, .uix-table--pinned-col td:first-child { position: sticky; left: 0; z-index: var(--uix-z-raised); box-shadow: 1px 0 0 var(--uix-border); }
68
73
  .uix-table--pinned-actions th:last-child, .uix-table--pinned-actions td:last-child { position: sticky; right: 0; z-index: var(--uix-z-raised); box-shadow: -1px 0 0 var(--uix-border); }
69
74
  .uix-table--pinned-col thead th:first-child, .uix-table--pinned-actions thead th:last-child { z-index: var(--uix-z-sticky); background: var(--uix-surface); }
75
+ /* The dividers mark where rows scroll under a frozen column: a React TableWrap that measured no
76
+ sideways overflow (data-overflow="false") draws none. Without the measurement they stay. */
77
+ .uix-table-wrap[data-overflow="false"] :is(.uix-table--pinned-col :is(th, td):first-child, .uix-table--pinned-actions :is(th, td):last-child) { box-shadow: none; }
70
78
  /* A pinned cell paints its row's state itself and must be opaque, or the cells scrolling
71
79
  under it show through. The dark pinned/selected tints are translucent, so they are layered
72
80
  over the surface the row sits on rather than painted bare. */
@@ -102,6 +110,8 @@
102
110
  /* ── cell content vocabulary — a fixed set of renderers keeps tables consistent ── */
103
111
  .uix-cell-strong { font-weight: 600; }
104
112
  .uix-cell-sub { display: block; font-size: var(--uix-text-meta); color: var(--uix-text-muted); }
113
+ /* read-back codes, references and times: digits line up down the column (HAR-1815) */
114
+ .uix-cell-sub--tabular { font-variant-numeric: tabular-nums; }
105
115
  .uix-cell-mono { font-family: var(--uix-font-mono); font-size: var(--uix-text-meta); }
106
116
 
107
117
  /* ── id cell — the canonical row click-through (row → peek, ↗ → full record) ───── */
@@ -127,7 +137,9 @@
127
137
  .uix-table tbody tr:focus-within .uix-id-cell__arrow { opacity: 1; }
128
138
 
129
139
  /* ── selection column + select-all ────────────────────────────────────────────── */
130
- .uix-table th.uix-table__selcol, .uix-table td.uix-table__selcell { width: 44px; padding-left: var(--uix-space-3); padding-right: 0; text-align: center; }
140
+ /* --uix-selcol-w: the selection column's width, for a column frozen right after it. */
141
+ .uix-table { --uix-selcol-w: 44px; }
142
+ .uix-table th.uix-table__selcol, .uix-table td.uix-table__selcell { width: var(--uix-selcol-w); padding-left: var(--uix-space-3); padding-right: 0; text-align: center; }
131
143
 
132
144
  /* contextual bulk-action bar — appears when >=1 row is selected */
133
145
  .uix-bulkbar {
@@ -138,7 +150,8 @@
138
150
  animation: uix-bulkbar-in var(--uix-dur) var(--uix-ease-out);
139
151
  }
140
152
  .uix-bulkbar[hidden] { display: none; }
141
- .uix-bulkbar__count { font-size: var(--uix-text-meta); font-weight: 600; color: var(--uix-accent); font-variant-numeric: tabular-nums; }
153
+ /* --uix-accent-text, not --uix-accent: the plain accent on the accent tint is 3.4:1 in dark (HAR-1388 specimen) */
154
+ .uix-bulkbar__count { font-size: var(--uix-text-meta); font-weight: 600; color: var(--uix-accent-text); font-variant-numeric: tabular-nums; }
142
155
  .uix-bulkbar__spacer { flex: 1; }
143
156
  @keyframes uix-bulkbar-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
144
157
  @media (prefers-reduced-motion: reduce) { .uix-bulkbar { animation: none; } }
@@ -1,14 +1,16 @@
1
1
  /* uix tabs — line / enclosed / pill. Depends only on --uix-* tokens. */
2
2
  @layer uix.components {
3
- .uix-tabs { display: flex; gap: var(--uix-space-1); }
3
+ /* tabs that do not fit wrap onto another row (overflow="wrap", the default; HAR-1754) rather
4
+ than squeezing every label; no tab is wider than its row, so one long label wraps inside it */
5
+ .uix-tabs { display: flex; flex-wrap: wrap; gap: var(--uix-space-1); }
4
6
  .uix-tab {
5
7
  border: 0; background: transparent; font: inherit; font-size: var(--uix-text-body); font-weight: 500;
6
8
  color: var(--uix-text-hushed); padding: var(--uix-space-3) var(--uix-space-3); cursor: pointer; position: relative;
7
9
  /* long or translated labels wrap (two lines at the 16rem cap) instead of truncating */
8
- white-space: normal; max-width: 16rem; text-align: start;
10
+ white-space: normal; max-width: min(16rem, 100%); overflow-wrap: anywhere; text-align: start;
9
11
  transition: color var(--uix-dur-fast) var(--uix-ease-out), background-color var(--uix-dur-fast) var(--uix-ease-out);
10
12
  }
11
- .uix-tab:hover { color: var(--uix-text); }
13
+ @media (hover: hover) { .uix-tab:hover { color: var(--uix-text); } }
12
14
  .uix-tab[aria-selected="true"] { color: var(--uix-text); }
13
15
  .uix-tab:focus-visible { outline: 2px solid var(--uix-ring); outline-offset: -2px; border-radius: var(--uix-radius-sm); }
14
16
 
@@ -20,6 +22,9 @@
20
22
  transform: scaleX(0); transition: transform var(--uix-dur) var(--uix-ease-out);
21
23
  }
22
24
  .uix-tabs--line .uix-tab[aria-selected="true"]::after { transform: scaleX(1); }
25
+ /* arrow keys switch tabs many times a minute: the underline moves at once (no slide) while the
26
+ keyboard is in the row; a pointer choice keeps the short slide */
27
+ .uix-tabs--line:has(.uix-tab:focus-visible) .uix-tab::after { transition: none; }
23
28
 
24
29
  /* enclosed */
25
30
  .uix-tabs--enclosed { gap: 0; border-bottom: 1px solid var(--uix-border); }
@@ -25,3 +25,24 @@
25
25
  .uix-tag__remove:active { background: color-mix(in srgb, var(--uix-text) 26%, transparent); }
26
26
  .uix-tag__remove:focus-visible { outline: 2px solid var(--uix-ring); outline-offset: 1px; }
27
27
  }
28
+
29
+ /* TagInput (React, HAR-1377): the field, its refusal line and the suggestion list (a top-layer
30
+ popup styled as Select's). */
31
+ @layer uix.components {
32
+ .uix-taginput-field { display: grid; gap: var(--uix-space-1); min-width: 0; }
33
+ /* the chips' list wrapper is not a box of its own: the chips sit in the field's wrapping row */
34
+ .uix-taginput__tags { display: contents; }
35
+ .uix-taginput[data-invalid] { border-color: var(--uix-danger); }
36
+ .uix-taginput[data-invalid]:focus-within { box-shadow: 0 0 0 3px var(--uix-danger-bg); }
37
+ /* disabled: the subtle surface and no × buttons; the tags stay readable (no opacity on the text) */
38
+ .uix-taginput[data-disabled] { background: var(--uix-bg-subtle); cursor: not-allowed; }
39
+ .uix-taginput__field::placeholder { color: var(--uix-text-muted); }
40
+ .uix-taginput__field:disabled { cursor: not-allowed; }
41
+ /* a long tag wraps inside its chip instead of widening the field */
42
+ .uix-taginput .uix-tag { max-width: 100%; min-width: 0; overflow-wrap: anywhere; }
43
+ .uix-taginput__message { min-width: 0; overflow-wrap: anywhere; }
44
+ .uix-taginput__popup { max-width: min(28rem, calc(100vw - 2 * var(--uix-space-4))); }
45
+ /* a suggestion is "selected" while it is the active one (selection follows the keys): the row tint
46
+ shows that; the chosen-value look of a select (accent, bold) does not apply */
47
+ .uix-taginput__popup .uix-listbox__option[aria-selected="true"] { color: var(--uix-text); font-weight: 400; }
48
+ }
@@ -12,4 +12,7 @@
12
12
  .uix-textarea:focus { outline: none; border-color: var(--uix-ring); box-shadow: 0 0 0 3px var(--uix-brand-muted); }
13
13
  .uix-textarea:disabled { opacity: .55; background: var(--uix-bg-subtle); }
14
14
  .uix-textarea[aria-invalid="true"] { border-color: var(--uix-danger); }
15
+ /* lg: the public-page size beside Input lg (HAR-1812): its type and side padding; the 84 px
16
+ floor already clears the 44 px target, and it still grows with rows and the handle */
17
+ .uix-textarea--lg { padding: var(--uix-space-3) var(--uix-space-4); font-size: var(--uix-text-h3); }
15
18
  }
@@ -19,6 +19,9 @@
19
19
  .uix-toast__title { font-weight: 600; font-size: var(--uix-text-body); }
20
20
  .uix-toast__msg { font-size: var(--uix-text-meta); color: var(--uix-text-muted); }
21
21
  .uix-toast__close { border: 0; background: transparent; color: var(--uix-text-muted); cursor: pointer; padding: var(--uix-space-1) var(--uix-space-2); border-radius: var(--uix-radius-xs); }
22
+ /* the × is the icon set's X (HAR-1576), centred in a 24 px target */
23
+ .uix-toast__close { display: inline-grid; place-items: center; min-width: 24px; min-height: 24px; padding: var(--uix-space-1); }
24
+ .uix-toast__close > .uix-icon { width: var(--uix-icon-sm); height: var(--uix-icon-sm); }
22
25
  .uix-toast__close:hover { background: var(--uix-bg-hover); color: var(--uix-text); }
23
26
  .uix-toast--success .uix-toast__icon { color: var(--uix-success); }
24
27
  .uix-toast--danger .uix-toast__icon { color: var(--uix-danger); }
@@ -40,3 +43,12 @@
40
43
  .uix-toaster[data-position$="start"] { left: var(--uix-space-4); right: auto; }
41
44
  .uix-toaster[data-position$="center"] { left: 50%; right: auto; transform: translateX(-50%); }
42
45
  }
46
+
47
+ /* the in-app reduced-motion preference (HAR-1372, <html data-motion="reduce">): the same fades */
48
+ @layer uix.components {
49
+ @media (prefers-reduced-motion: no-preference) {
50
+ :root[data-motion="reduce"] .uix-toast { animation: uix-fade-in var(--uix-dur) var(--uix-ease-out) !important; }
51
+ :root[data-motion="reduce"] .uix-toast[data-leaving] { animation: uix-toast-fade-out var(--uix-dur-exit) var(--uix-ease-out) forwards !important; }
52
+ }
53
+ }
54
+
@@ -3,7 +3,9 @@
3
3
  selection, and collapse styling all key off the item, not the row (UIX-FIX-04). */
4
4
  @layer uix.components {
5
5
  .uix-tree, .uix-tree ul { list-style: none; margin: 0; padding: 0; }
6
- .uix-tree__group { padding-left: var(--uix-tree-indent-step, var(--uix-space-5)); }
6
+ /* scoped under .uix-tree so it beats the `.uix-tree ul` reset above: unscoped, that reset won and
7
+ no level was indented (seen while checking HAR-1828's org chart) */
8
+ .uix-tree .uix-tree__group { padding-left: var(--uix-tree-indent-step, var(--uix-space-5)); }
7
9
  /* TENSOR RX-125 (UIX-08): the indent stops growing past level 4 — a guide line
8
10
  marks the depth instead, so deep nodes keep room for their names. */
9
11
  .uix-tree__group .uix-tree__group .uix-tree__group .uix-tree__group .uix-tree__group {
@@ -75,5 +75,8 @@
75
75
  .uix-saved-views__actions:has([aria-expanded="true"]) { opacity: 1; }
76
76
  .uix-saved-views__pin { display: grid; place-items: center; width: 28px; height: 28px; border: 0; border-radius: var(--uix-radius-sm); background: transparent; color: var(--uix-text-muted); cursor: pointer; }
77
77
  .uix-saved-views__pin:is(:hover, :focus-visible), .uix-saved-views__pin[data-on] { color: var(--uix-warning-text); background: var(--uix-bg-hover); }
78
+ /* the pin is the icon set's Star (HAR-1576): an outline, filled while pinned, so the state is a shape too */
79
+ .uix-saved-views__pin > .uix-icon { width: var(--uix-icon-sm); height: var(--uix-icon-sm); }
80
+ .uix-saved-views__pin[data-on] > .uix-icon { fill: currentColor; }
78
81
  .uix-saved-views__footer { border-top: 1px solid var(--uix-border); margin-top: var(--uix-space-1); padding: var(--uix-space-2); }
79
82
  }
package/styles/motion.css CHANGED
@@ -22,6 +22,21 @@
22
22
  }
23
23
  }
24
24
 
25
+ /* The in-app preference (HAR-1372): <html data-motion="reduce">, written by useDisplayPreferences and
26
+ displayPreferencesScript, applies the same policy for a person who has not set it in the OS. With the OS
27
+ setting on, the block above already applies. Components that swap a loop for a pulse mirror their
28
+ reduced rule the same way. */
29
+ @media (prefers-reduced-motion: no-preference) {
30
+ :root[data-motion="reduce"] *, :root[data-motion="reduce"] *::before, :root[data-motion="reduce"] *::after {
31
+ transition-property: opacity, color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, visibility, overlay, display !important;
32
+ transition-behavior: allow-discrete !important;
33
+ /* motion-allow: ends product keyframes at once while still firing animationend (the same policy as above) */
34
+ animation-duration: .001ms !important;
35
+ animation-iteration-count: 1 !important;
36
+ scroll-behavior: auto !important;
37
+ }
38
+ }
39
+
25
40
  /* Keyframes (cascade-neutral). */
26
41
  @keyframes uix-fade-in { from { opacity: 0; } to { opacity: 1; } }
27
42
  @keyframes uix-pop-in {
@@ -43,6 +58,9 @@
43
58
  /* the entrance helpers keep their fade and lose their travel */
44
59
  .uix-anim-fade, .uix-anim-pop, .uix-anim-up { animation: uix-fade-in var(--uix-dur) var(--uix-ease-out) !important; }
45
60
  }
61
+ @media (prefers-reduced-motion: no-preference) {
62
+ :root[data-motion="reduce"] :is(.uix-anim-fade, .uix-anim-pop, .uix-anim-up) { animation: uix-fade-in var(--uix-dur) var(--uix-ease-out) !important; }
63
+ }
46
64
 
47
65
  /* Hover-lift affordance for interactive cards/tiles. Gated so touch devices don't get a stuck hover.
48
66
  The shadow steps; only the lift animates (box-shadow is never animated). */