@tensor_1/tokens 2.5.0 → 2.7.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/README.md +26 -0
- package/build/css/components.css +64 -11
- package/build/css/styles.css +64 -11
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -56,9 +56,35 @@ The following CSS primitives (and their `@tensor_1/react` wrappers) are the inte
|
|
|
56
56
|
| Primitive | CSS file | Key `--uix-*` tokens |
|
|
57
57
|
|---|---|---|
|
|
58
58
|
| Row selection | `table.css` `tr[aria-selected]` | `--uix-row-selected-bg` |
|
|
59
|
+
| Table column sizing | `table.css` `.uix-col--w-*` / `--flex` / `--truncate` / `--num` · `<Table fixed>` | `--uix-col-w-xs…xl`, `--uix-col-title-min` |
|
|
60
|
+
| Selection bulk bar | `table.css` `.uix-bulkbar` · `<BulkBar>` | `--uix-brand-muted`, `--uix-accent` |
|
|
61
|
+
| Row hover actions / kebab | `table.css` `.uix-table__actions` / `.uix-rowact` · `<RowActions>` / `<RowAction>` | `--uix-bg-active`, `--uix-text-muted` |
|
|
62
|
+
| Expandable row detail | `table.css` `.uix-table__detail` / `.uix-kv` · `<ExpandToggle>` | `--uix-bg-subtle` |
|
|
63
|
+
| Inline cell edit | `table.css` `.uix-cell-edit` | `--uix-ring`, `--uix-success` |
|
|
64
|
+
| Column resize grip | `table.css` `.uix-table__resize` | `--uix-accent` |
|
|
65
|
+
| Search-match highlight | `table.css` `.uix-mark` · `<Mark>` / `<Highlighted>` | `--uix-warning-bg`, `--uix-warning` |
|
|
66
|
+
| Cell content vocabulary | `table.css` `.uix-cell-strong` / `-sub` / `-mono` · `<CellStrong>` / `<CellSub>` | `--uix-text-muted`, `--uix-font-mono` |
|
|
67
|
+
| Responsive table ladder | `table.css` `.uix-table--priority` / `--cards` | `--uix-border`, `--uix-surface`, `--uix-shadow-sm` |
|
|
68
|
+
| Record compare view | `table.css` `.uix-compare` | `--uix-border`, `--uix-surface`, `--uix-bg-subtle` |
|
|
59
69
|
| Utilization / threshold bar | `meter.css` · `<Meter>` | `--uix-attention`, `--uix-overdue`, `--uix-warning`, `--uix-danger` |
|
|
60
70
|
| Triage inbox | `inbox.css` · `<Inbox>` / `<InboxItem>` | `--uix-brand-muted`, `--uix-accent` (accent stripe) |
|
|
61
71
|
| Status + SLA + priority pill | `status-pill.css` · `<StatusPill>` | `--uix-sla-ok/at-risk/breached`, `--uix-p1`…`--uix-p5`, `--uix-attention`, `--uix-overdue` |
|
|
62
72
|
| Entity detail related-panels | `<DetailLayout>` (`@tensor_1/react`) | `--uix-surface`, `--uix-border` |
|
|
73
|
+
| App-shell nav width tiers | `app-shell.css` `.uix-shell[data-nav="full\|rail\|hidden"]` · `<AppShell nav>` | `--uix-sidebar-w`, `--uix-sidebar-w-rail` |
|
|
74
|
+
| Shell focus / full-bleed | `app-shell.css` `.uix-shell[data-focus]` / `.uix-shell__main--bleed` · `<AppShell focus mainBleed>` | `--uix-z-overlay`, `--uix-space-7` |
|
|
75
|
+
| Table logic engine | `@tensor_1/react` `table-engine` (multiSort / applyFilters / searchRows / serializeView / virtualWindow / selection) | — behaviour primitive; keeps vanilla + React grids identical |
|
|
63
76
|
|
|
64
77
|
If you reach for `var(--uix-danger)` or `var(--uix-warning)` to render SLA urgency or severity, use `<StatusPill tone="sla-breached">` or `<StatusPill tone="p1">` instead — the component handles WCAG contrast, dark mode, and brand overrides; a raw literal does not.
|
|
78
|
+
|
|
79
|
+
Likewise, don't fork the data grid: a product-local `data-table.tsx` (bespoke sort/filter/selection/resize + hand-coded column widths) should be replaced by `<Table>` + the subcomponents above, composed over the framework-agnostic `table-engine` (or the `useTable` hook). Sorting, filtering, search highlighting, saved views, and virtualization then match the vanilla styleguide exactly, and every visual affordance re-themes with the tokens listed here.
|
|
80
|
+
|
|
81
|
+
## Documentation site
|
|
82
|
+
|
|
83
|
+
A **build-free** component explorer lives in [`docs/`](./docs/) — a no-bundler HTML shell (`docs/explorer.html`) with a left component nav and a per-component page whose regions (`overview`, `live-example`, `props-table`, `do-dont`, `a11y-notes`) are keyed by `data-region` and filled in incrementally. It reuses the styleguide's theming verbatim (the no-flash `data-theme` script + `[data-uix-theme-toggle]`) and links the same `--uix-*` contract via `../styles/main.css`, so light/dark behaves identically to `index.html`. `docs/docs.js` exposes pure, unit-tested helpers (`slugify`, `componentNav`, `renderPropsTable`) behind a `typeof document` DOM guard; run `node --test docs/docs.test.js`.
|
|
84
|
+
|
|
85
|
+
Serve it from the repo root (the styleguide's static root) so relative asset paths resolve:
|
|
86
|
+
|
|
87
|
+
```sh
|
|
88
|
+
npm run docs:serve
|
|
89
|
+
# → http://localhost:4178/packages/tokens/docs/explorer.html
|
|
90
|
+
```
|
package/build/css/components.css
CHANGED
|
@@ -119,6 +119,9 @@
|
|
|
119
119
|
.uix-field { display: flex; flex-direction: column; gap: var(--uix-space-2); }
|
|
120
120
|
.uix-field__label { font-size: var(--uix-text-meta); font-weight: 500; color: var(--uix-text); }
|
|
121
121
|
.uix-field__label[data-required]::after { content: " *"; color: var(--uix-danger-text); }
|
|
122
|
+
/* message slot for hint / error / success — reserves one line so an appearing error never
|
|
123
|
+
shifts the layout (UIX-FIX-04); the React <Field> always renders it. */
|
|
124
|
+
.uix-field__msg { font-size: var(--uix-text-meta); line-height: 1.45; min-height: 1.45em; }
|
|
122
125
|
.uix-field__hint { font-size: var(--uix-text-meta); color: var(--uix-text-muted); }
|
|
123
126
|
.uix-field__error { font-size: var(--uix-text-meta); color: var(--uix-danger-text); display: inline-flex; align-items: center; gap: var(--uix-space-2); }
|
|
124
127
|
.uix-field__error svg, .uix-field__success svg { width: 14px; height: 14px; flex: none; }
|
|
@@ -351,17 +354,39 @@
|
|
|
351
354
|
/* uix app shell — sidebar + topbar + content grid. Depends only on --uix-* tokens. */
|
|
352
355
|
@layer uix.components {
|
|
353
356
|
.uix-shell {
|
|
357
|
+
position: relative;
|
|
354
358
|
display: grid;
|
|
355
359
|
grid-template-columns: var(--uix-sidebar-w) 1fr;
|
|
356
360
|
grid-template-rows: var(--uix-topbar-h) 1fr;
|
|
357
361
|
height: 100%; min-height: 360px;
|
|
358
362
|
border: 1px solid var(--uix-border); border-radius: var(--uix-radius-lg); overflow: hidden;
|
|
359
|
-
transition: grid-template-columns var(--uix-dur) var(--uix-ease-out);
|
|
363
|
+
transition: grid-template-columns var(--uix-dur) var(--uix-ease-out), grid-template-rows var(--uix-dur) var(--uix-ease-out);
|
|
360
364
|
}
|
|
361
|
-
.uix-shell__sidebar { grid-row: 1 / 3; background: var(--uix-bg-subtle); border-right: 1px solid var(--uix-border); overflow-y: auto; }
|
|
365
|
+
.uix-shell__sidebar { grid-row: 1 / 3; background: var(--uix-bg-subtle); border-right: 1px solid var(--uix-border); overflow-y: auto; overflow-x: hidden; }
|
|
362
366
|
.uix-shell__topbar { grid-column: 2; display: flex; align-items: center; gap: var(--uix-space-3); padding: 0 var(--uix-space-6); background: var(--uix-bg-app); border-bottom: 1px solid var(--uix-border); }
|
|
363
367
|
.uix-shell__main { grid-column: 2; overflow: auto; padding: var(--uix-space-7); background: var(--uix-bg-app); }
|
|
364
|
-
|
|
368
|
+
|
|
369
|
+
/* ── nav width tiers ──────────────────────────────────────────────────────────
|
|
370
|
+
Progressive reveal for wide, many-column tables: full (default) → rail (icon
|
|
371
|
+
only) → hidden (0). data-collapsed stays a back-compat alias for the rail. */
|
|
372
|
+
.uix-shell[data-nav="rail"], .uix-shell[data-collapsed] { grid-template-columns: var(--uix-sidebar-w-rail) 1fr; }
|
|
373
|
+
.uix-shell[data-nav="hidden"] { grid-template-columns: 0 1fr; }
|
|
374
|
+
|
|
375
|
+
/* ── focus / immersive mode ───────────────────────────────────────────────────
|
|
376
|
+
A table-scoped escape hatch: hide the sidebar AND the topbar so a dense grid
|
|
377
|
+
uses the whole frame. The app toggles [data-focus] (from a toolbar maximize
|
|
378
|
+
control) and restores the previous nav state + focus on Esc. */
|
|
379
|
+
.uix-shell[data-focus] { grid-template-columns: 0 1fr; grid-template-rows: 0 1fr; }
|
|
380
|
+
.uix-shell[data-focus] .uix-shell__topbar { display: none; }
|
|
381
|
+
|
|
382
|
+
/* a floating host for the "exit focus" affordance (Esc also exits) */
|
|
383
|
+
.uix-shell__focus-exit { position: absolute; top: var(--uix-space-3); right: var(--uix-space-3); z-index: var(--uix-z-overlay); }
|
|
384
|
+
|
|
385
|
+
/* ── full-bleed main ──────────────────────────────────────────────────────────
|
|
386
|
+
Opt-in per surface: a genuinely wide grid drops the content gutter and runs
|
|
387
|
+
edge to edge, reclaiming 2 x --uix-space-7. Not the default — most pages want
|
|
388
|
+
the gutter. Pair with a frozen identifier column for horizontal scroll. */
|
|
389
|
+
.uix-shell__main--bleed { padding: 0; }
|
|
365
390
|
}
|
|
366
391
|
/* uix sidebar nav — items, favorites, collapsible sub-items, collapsed rail. Depends only on --uix-* tokens. */
|
|
367
392
|
@layer uix.components {
|
|
@@ -415,7 +440,7 @@
|
|
|
415
440
|
.uix-subitem .uix-navitem__label::before { content: ""; display: inline-block; width: 4px; height: 4px; border-radius: 50%; background: var(--uix-text-muted); margin-right: var(--uix-space-3); vertical-align: middle; }
|
|
416
441
|
|
|
417
442
|
/* collapsed rail */
|
|
418
|
-
.uix-sidebar[data-collapsed] { width:
|
|
443
|
+
.uix-sidebar[data-collapsed], .uix-sidebar[data-nav="rail"] { width: var(--uix-sidebar-w-rail); }
|
|
419
444
|
.uix-sidebar[data-collapsed] .uix-navitem__label,
|
|
420
445
|
.uix-sidebar[data-collapsed] .uix-navitem__badge,
|
|
421
446
|
.uix-sidebar[data-collapsed] .uix-navitem__star,
|
|
@@ -836,8 +861,28 @@
|
|
|
836
861
|
.uix-avatar--editable:hover .uix-avatar__edit, .uix-avatar--editable:focus-visible .uix-avatar__edit { opacity: 1; }
|
|
837
862
|
.uix-avatar--empty { background: var(--uix-bg-subtle); border: 1.5px dashed var(--uix-border-strong); color: var(--uix-text-muted); }
|
|
838
863
|
}
|
|
839
|
-
/* uix tooltip
|
|
864
|
+
/* uix tooltip. Two flavours, both depend only on --uix-* tokens:
|
|
865
|
+
• .uix-tooltip__bubble — the React <Tooltip>: renders in the top layer via the
|
|
866
|
+
Popover API, so it escapes any overflow:hidden/scroll ancestor (UIX-FIX-02).
|
|
867
|
+
JS sets position/left/top; CSS owns appearance + the fade.
|
|
868
|
+
• [data-uix-tip] — the legacy CSS-only tooltip, kept for back-compat. It is
|
|
869
|
+
position:absolute and so is clipped by an overflow ancestor; prefer <Tooltip>. */
|
|
840
870
|
@layer uix.components {
|
|
871
|
+
.uix-tooltip { display: inline-flex; }
|
|
872
|
+
|
|
873
|
+
.uix-tooltip__bubble {
|
|
874
|
+
position: fixed; margin: 0; inset: auto; border: 0;
|
|
875
|
+
width: max-content; max-width: 16rem;
|
|
876
|
+
background: var(--uix-text); color: var(--uix-bg-app);
|
|
877
|
+
font-size: var(--uix-text-meta); font-weight: 500; line-height: 1.4;
|
|
878
|
+
padding: var(--uix-space-2) var(--uix-space-3); border-radius: var(--uix-radius-sm);
|
|
879
|
+
box-shadow: var(--uix-shadow-popover); white-space: normal; pointer-events: none;
|
|
880
|
+
opacity: 0; transition: opacity var(--uix-dur-fast) var(--uix-ease-out);
|
|
881
|
+
}
|
|
882
|
+
.uix-tooltip__bubble:popover-open { opacity: 1; }
|
|
883
|
+
@starting-style { .uix-tooltip__bubble:popover-open { opacity: 0; } }
|
|
884
|
+
|
|
885
|
+
/* legacy CSS-only tooltip — clipped by overflow ancestors; superseded by .uix-tooltip__bubble */
|
|
841
886
|
[data-uix-tip] { position: relative; }
|
|
842
887
|
[data-uix-tip]::after {
|
|
843
888
|
content: attr(data-uix-tip); position: absolute; bottom: calc(100% + 6px); left: 50%;
|
|
@@ -848,6 +893,8 @@
|
|
|
848
893
|
transition: opacity var(--uix-dur-fast) var(--uix-ease-out), transform var(--uix-dur-fast) var(--uix-ease-out);
|
|
849
894
|
}
|
|
850
895
|
[data-uix-tip]:hover::after, [data-uix-tip]:focus-visible::after { opacity: 1; transform: translateX(-50%) translateY(0); }
|
|
896
|
+
/* when JS upgrades [data-uix-tip] to a top-layer bubble, drop the clipped CSS-only one */
|
|
897
|
+
.uix-has-js-tip [data-uix-tip]::after { content: none; }
|
|
851
898
|
}
|
|
852
899
|
/* uix progress bar + ring — depends only on --uix-* tokens. */
|
|
853
900
|
@layer uix.components {
|
|
@@ -881,16 +928,22 @@
|
|
|
881
928
|
.uix-timeline__body { padding-bottom: var(--uix-space-5); }
|
|
882
929
|
.uix-timeline__meta { font-size: var(--uix-text-meta); color: var(--uix-text-muted); }
|
|
883
930
|
}
|
|
884
|
-
/* uix tree view —
|
|
931
|
+
/* uix tree view — WAI-ARIA tree (role=tree/treeitem/group). Depends only on --uix-* tokens.
|
|
932
|
+
ARIA (aria-expanded / aria-selected / aria-level) lives on the treeitem <li>, so the chevron,
|
|
933
|
+
selection, and collapse styling all key off the item, not the row (UIX-FIX-04). */
|
|
885
934
|
@layer uix.components {
|
|
886
935
|
.uix-tree, .uix-tree ul { list-style: none; margin: 0; padding: 0; }
|
|
887
|
-
.uix-
|
|
888
|
-
.uix-
|
|
889
|
-
.uix-tree__row
|
|
936
|
+
.uix-tree__group { padding-left: var(--uix-space-5); }
|
|
937
|
+
.uix-tree__item { outline: none; } /* the focus ring is drawn on the row, below */
|
|
938
|
+
.uix-tree__row { display: flex; align-items: center; gap: var(--uix-space-2); padding: var(--uix-space-2) var(--uix-space-2); border-radius: var(--uix-radius-sm); cursor: pointer; color: var(--uix-text); font-size: var(--uix-text-body); }
|
|
939
|
+
.uix-tree__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
940
|
+
.uix-tree__item > .uix-tree__row:hover { background: var(--uix-bg-hover); }
|
|
941
|
+
.uix-tree__item[aria-selected="true"] > .uix-tree__row { background: var(--uix-bg-active); }
|
|
942
|
+
.uix-tree__item:focus-visible > .uix-tree__row { outline: 2px solid var(--uix-ring); outline-offset: -2px; }
|
|
890
943
|
.uix-tree__toggle { width: 16px; height: 16px; flex: none; display: grid; place-items: center; color: var(--uix-text-muted); transition: transform var(--uix-dur) var(--uix-ease-out); }
|
|
891
944
|
.uix-tree__toggle svg { width: 14px; height: 14px; }
|
|
892
|
-
.uix-
|
|
893
|
-
.uix-
|
|
945
|
+
.uix-tree__item[aria-expanded="false"] > .uix-tree__row .uix-tree__toggle { transform: rotate(-90deg); }
|
|
946
|
+
.uix-tree__item[aria-expanded="false"] > .uix-tree__group { display: none; }
|
|
894
947
|
}
|
|
895
948
|
/* uix calendar (shared by date pickers) — depends only on --uix-* tokens. */
|
|
896
949
|
@layer uix.components {
|
package/build/css/styles.css
CHANGED
|
@@ -415,6 +415,9 @@
|
|
|
415
415
|
.uix-field { display: flex; flex-direction: column; gap: var(--uix-space-2); }
|
|
416
416
|
.uix-field__label { font-size: var(--uix-text-meta); font-weight: 500; color: var(--uix-text); }
|
|
417
417
|
.uix-field__label[data-required]::after { content: " *"; color: var(--uix-danger-text); }
|
|
418
|
+
/* message slot for hint / error / success — reserves one line so an appearing error never
|
|
419
|
+
shifts the layout (UIX-FIX-04); the React <Field> always renders it. */
|
|
420
|
+
.uix-field__msg { font-size: var(--uix-text-meta); line-height: 1.45; min-height: 1.45em; }
|
|
418
421
|
.uix-field__hint { font-size: var(--uix-text-meta); color: var(--uix-text-muted); }
|
|
419
422
|
.uix-field__error { font-size: var(--uix-text-meta); color: var(--uix-danger-text); display: inline-flex; align-items: center; gap: var(--uix-space-2); }
|
|
420
423
|
.uix-field__error svg, .uix-field__success svg { width: 14px; height: 14px; flex: none; }
|
|
@@ -647,17 +650,39 @@
|
|
|
647
650
|
/* uix app shell — sidebar + topbar + content grid. Depends only on --uix-* tokens. */
|
|
648
651
|
@layer uix.components {
|
|
649
652
|
.uix-shell {
|
|
653
|
+
position: relative;
|
|
650
654
|
display: grid;
|
|
651
655
|
grid-template-columns: var(--uix-sidebar-w) 1fr;
|
|
652
656
|
grid-template-rows: var(--uix-topbar-h) 1fr;
|
|
653
657
|
height: 100%; min-height: 360px;
|
|
654
658
|
border: 1px solid var(--uix-border); border-radius: var(--uix-radius-lg); overflow: hidden;
|
|
655
|
-
transition: grid-template-columns var(--uix-dur) var(--uix-ease-out);
|
|
659
|
+
transition: grid-template-columns var(--uix-dur) var(--uix-ease-out), grid-template-rows var(--uix-dur) var(--uix-ease-out);
|
|
656
660
|
}
|
|
657
|
-
.uix-shell__sidebar { grid-row: 1 / 3; background: var(--uix-bg-subtle); border-right: 1px solid var(--uix-border); overflow-y: auto; }
|
|
661
|
+
.uix-shell__sidebar { grid-row: 1 / 3; background: var(--uix-bg-subtle); border-right: 1px solid var(--uix-border); overflow-y: auto; overflow-x: hidden; }
|
|
658
662
|
.uix-shell__topbar { grid-column: 2; display: flex; align-items: center; gap: var(--uix-space-3); padding: 0 var(--uix-space-6); background: var(--uix-bg-app); border-bottom: 1px solid var(--uix-border); }
|
|
659
663
|
.uix-shell__main { grid-column: 2; overflow: auto; padding: var(--uix-space-7); background: var(--uix-bg-app); }
|
|
660
|
-
|
|
664
|
+
|
|
665
|
+
/* ── nav width tiers ──────────────────────────────────────────────────────────
|
|
666
|
+
Progressive reveal for wide, many-column tables: full (default) → rail (icon
|
|
667
|
+
only) → hidden (0). data-collapsed stays a back-compat alias for the rail. */
|
|
668
|
+
.uix-shell[data-nav="rail"], .uix-shell[data-collapsed] { grid-template-columns: var(--uix-sidebar-w-rail) 1fr; }
|
|
669
|
+
.uix-shell[data-nav="hidden"] { grid-template-columns: 0 1fr; }
|
|
670
|
+
|
|
671
|
+
/* ── focus / immersive mode ───────────────────────────────────────────────────
|
|
672
|
+
A table-scoped escape hatch: hide the sidebar AND the topbar so a dense grid
|
|
673
|
+
uses the whole frame. The app toggles [data-focus] (from a toolbar maximize
|
|
674
|
+
control) and restores the previous nav state + focus on Esc. */
|
|
675
|
+
.uix-shell[data-focus] { grid-template-columns: 0 1fr; grid-template-rows: 0 1fr; }
|
|
676
|
+
.uix-shell[data-focus] .uix-shell__topbar { display: none; }
|
|
677
|
+
|
|
678
|
+
/* a floating host for the "exit focus" affordance (Esc also exits) */
|
|
679
|
+
.uix-shell__focus-exit { position: absolute; top: var(--uix-space-3); right: var(--uix-space-3); z-index: var(--uix-z-overlay); }
|
|
680
|
+
|
|
681
|
+
/* ── full-bleed main ──────────────────────────────────────────────────────────
|
|
682
|
+
Opt-in per surface: a genuinely wide grid drops the content gutter and runs
|
|
683
|
+
edge to edge, reclaiming 2 x --uix-space-7. Not the default — most pages want
|
|
684
|
+
the gutter. Pair with a frozen identifier column for horizontal scroll. */
|
|
685
|
+
.uix-shell__main--bleed { padding: 0; }
|
|
661
686
|
}
|
|
662
687
|
/* uix sidebar nav — items, favorites, collapsible sub-items, collapsed rail. Depends only on --uix-* tokens. */
|
|
663
688
|
@layer uix.components {
|
|
@@ -711,7 +736,7 @@
|
|
|
711
736
|
.uix-subitem .uix-navitem__label::before { content: ""; display: inline-block; width: 4px; height: 4px; border-radius: 50%; background: var(--uix-text-muted); margin-right: var(--uix-space-3); vertical-align: middle; }
|
|
712
737
|
|
|
713
738
|
/* collapsed rail */
|
|
714
|
-
.uix-sidebar[data-collapsed] { width:
|
|
739
|
+
.uix-sidebar[data-collapsed], .uix-sidebar[data-nav="rail"] { width: var(--uix-sidebar-w-rail); }
|
|
715
740
|
.uix-sidebar[data-collapsed] .uix-navitem__label,
|
|
716
741
|
.uix-sidebar[data-collapsed] .uix-navitem__badge,
|
|
717
742
|
.uix-sidebar[data-collapsed] .uix-navitem__star,
|
|
@@ -1177,8 +1202,28 @@
|
|
|
1177
1202
|
.uix-avatar--editable:hover .uix-avatar__edit, .uix-avatar--editable:focus-visible .uix-avatar__edit { opacity: 1; }
|
|
1178
1203
|
.uix-avatar--empty { background: var(--uix-bg-subtle); border: 1.5px dashed var(--uix-border-strong); color: var(--uix-text-muted); }
|
|
1179
1204
|
}
|
|
1180
|
-
/* uix tooltip
|
|
1205
|
+
/* uix tooltip. Two flavours, both depend only on --uix-* tokens:
|
|
1206
|
+
• .uix-tooltip__bubble — the React <Tooltip>: renders in the top layer via the
|
|
1207
|
+
Popover API, so it escapes any overflow:hidden/scroll ancestor (UIX-FIX-02).
|
|
1208
|
+
JS sets position/left/top; CSS owns appearance + the fade.
|
|
1209
|
+
• [data-uix-tip] — the legacy CSS-only tooltip, kept for back-compat. It is
|
|
1210
|
+
position:absolute and so is clipped by an overflow ancestor; prefer <Tooltip>. */
|
|
1181
1211
|
@layer uix.components {
|
|
1212
|
+
.uix-tooltip { display: inline-flex; }
|
|
1213
|
+
|
|
1214
|
+
.uix-tooltip__bubble {
|
|
1215
|
+
position: fixed; margin: 0; inset: auto; border: 0;
|
|
1216
|
+
width: max-content; max-width: 16rem;
|
|
1217
|
+
background: var(--uix-text); color: var(--uix-bg-app);
|
|
1218
|
+
font-size: var(--uix-text-meta); font-weight: 500; line-height: 1.4;
|
|
1219
|
+
padding: var(--uix-space-2) var(--uix-space-3); border-radius: var(--uix-radius-sm);
|
|
1220
|
+
box-shadow: var(--uix-shadow-popover); white-space: normal; pointer-events: none;
|
|
1221
|
+
opacity: 0; transition: opacity var(--uix-dur-fast) var(--uix-ease-out);
|
|
1222
|
+
}
|
|
1223
|
+
.uix-tooltip__bubble:popover-open { opacity: 1; }
|
|
1224
|
+
@starting-style { .uix-tooltip__bubble:popover-open { opacity: 0; } }
|
|
1225
|
+
|
|
1226
|
+
/* legacy CSS-only tooltip — clipped by overflow ancestors; superseded by .uix-tooltip__bubble */
|
|
1182
1227
|
[data-uix-tip] { position: relative; }
|
|
1183
1228
|
[data-uix-tip]::after {
|
|
1184
1229
|
content: attr(data-uix-tip); position: absolute; bottom: calc(100% + 6px); left: 50%;
|
|
@@ -1189,6 +1234,8 @@
|
|
|
1189
1234
|
transition: opacity var(--uix-dur-fast) var(--uix-ease-out), transform var(--uix-dur-fast) var(--uix-ease-out);
|
|
1190
1235
|
}
|
|
1191
1236
|
[data-uix-tip]:hover::after, [data-uix-tip]:focus-visible::after { opacity: 1; transform: translateX(-50%) translateY(0); }
|
|
1237
|
+
/* when JS upgrades [data-uix-tip] to a top-layer bubble, drop the clipped CSS-only one */
|
|
1238
|
+
.uix-has-js-tip [data-uix-tip]::after { content: none; }
|
|
1192
1239
|
}
|
|
1193
1240
|
/* uix progress bar + ring — depends only on --uix-* tokens. */
|
|
1194
1241
|
@layer uix.components {
|
|
@@ -1222,16 +1269,22 @@
|
|
|
1222
1269
|
.uix-timeline__body { padding-bottom: var(--uix-space-5); }
|
|
1223
1270
|
.uix-timeline__meta { font-size: var(--uix-text-meta); color: var(--uix-text-muted); }
|
|
1224
1271
|
}
|
|
1225
|
-
/* uix tree view —
|
|
1272
|
+
/* uix tree view — WAI-ARIA tree (role=tree/treeitem/group). Depends only on --uix-* tokens.
|
|
1273
|
+
ARIA (aria-expanded / aria-selected / aria-level) lives on the treeitem <li>, so the chevron,
|
|
1274
|
+
selection, and collapse styling all key off the item, not the row (UIX-FIX-04). */
|
|
1226
1275
|
@layer uix.components {
|
|
1227
1276
|
.uix-tree, .uix-tree ul { list-style: none; margin: 0; padding: 0; }
|
|
1228
|
-
.uix-
|
|
1229
|
-
.uix-
|
|
1230
|
-
.uix-tree__row
|
|
1277
|
+
.uix-tree__group { padding-left: var(--uix-space-5); }
|
|
1278
|
+
.uix-tree__item { outline: none; } /* the focus ring is drawn on the row, below */
|
|
1279
|
+
.uix-tree__row { display: flex; align-items: center; gap: var(--uix-space-2); padding: var(--uix-space-2) var(--uix-space-2); border-radius: var(--uix-radius-sm); cursor: pointer; color: var(--uix-text); font-size: var(--uix-text-body); }
|
|
1280
|
+
.uix-tree__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1281
|
+
.uix-tree__item > .uix-tree__row:hover { background: var(--uix-bg-hover); }
|
|
1282
|
+
.uix-tree__item[aria-selected="true"] > .uix-tree__row { background: var(--uix-bg-active); }
|
|
1283
|
+
.uix-tree__item:focus-visible > .uix-tree__row { outline: 2px solid var(--uix-ring); outline-offset: -2px; }
|
|
1231
1284
|
.uix-tree__toggle { width: 16px; height: 16px; flex: none; display: grid; place-items: center; color: var(--uix-text-muted); transition: transform var(--uix-dur) var(--uix-ease-out); }
|
|
1232
1285
|
.uix-tree__toggle svg { width: 14px; height: 14px; }
|
|
1233
|
-
.uix-
|
|
1234
|
-
.uix-
|
|
1286
|
+
.uix-tree__item[aria-expanded="false"] > .uix-tree__row .uix-tree__toggle { transform: rotate(-90deg); }
|
|
1287
|
+
.uix-tree__item[aria-expanded="false"] > .uix-tree__group { display: none; }
|
|
1235
1288
|
}
|
|
1236
1289
|
/* uix calendar (shared by date pickers) — depends only on --uix-* tokens. */
|
|
1237
1290
|
@layer uix.components {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tensor_1/tokens",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "UIx v2 design tokens — the --uix-* contract for house products (Tensor, POSx, SHOPx). One DTCG source -> CSS variables, Tailwind theme, and typed TS constants.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -39,6 +39,9 @@
|
|
|
39
39
|
"build": "npm run build:tokens && npm run build:themes && npm run build:styles",
|
|
40
40
|
"test:parity": "node scripts/check-parity.mjs",
|
|
41
41
|
"test:contract": "node scripts/check-contract.mjs",
|
|
42
|
+
"docs:serve": "serve -l 4178 ../..",
|
|
43
|
+
"size:css": "node scripts/size-report.mjs --check",
|
|
44
|
+
"size:css:update": "node scripts/size-report.mjs --update",
|
|
42
45
|
"prepublishOnly": "npm run build && npm run test:parity && npm run test:contract"
|
|
43
46
|
},
|
|
44
47
|
"devDependencies": {
|