@dashforge/tw 0.11.0-beta → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +234 -12
- package/COVERAGE.md +2 -2
- package/PARITY.md +7 -9
- package/PERFORMANCE.md +3 -4
- package/README.md +74 -15
- package/THEME-AUDIT.md +3 -4
- package/dashforge-tw-1.0.0.tgz +0 -0
- package/dist/index.esm.js +3127 -748
- package/dist/src/components/Alert/Alert.d.ts +65 -0
- package/dist/src/components/Alert/Alert.d.ts.map +1 -0
- package/dist/src/components/Alert/alert.types.d.ts +130 -0
- package/dist/src/components/Alert/alert.types.d.ts.map +1 -0
- package/dist/src/components/Alert/alert.variants.d.ts +85 -0
- package/dist/src/components/Alert/alert.variants.d.ts.map +1 -0
- package/dist/src/components/Avatar/Avatar.d.ts +48 -0
- package/dist/src/components/Avatar/Avatar.d.ts.map +1 -0
- package/dist/src/components/Avatar/avatar.types.d.ts +162 -0
- package/dist/src/components/Avatar/avatar.types.d.ts.map +1 -0
- package/dist/src/components/Avatar/avatar.variants.d.ts +208 -0
- package/dist/src/components/Avatar/avatar.variants.d.ts.map +1 -0
- package/dist/src/components/Badge/Badge.d.ts +63 -0
- package/dist/src/components/Badge/Badge.d.ts.map +1 -0
- package/dist/src/components/Badge/badge.types.d.ts +124 -0
- package/dist/src/components/Badge/badge.types.d.ts.map +1 -0
- package/dist/src/components/Badge/badge.variants.d.ts +262 -0
- package/dist/src/components/Badge/badge.variants.d.ts.map +1 -0
- package/dist/src/components/Box/Box.d.ts.map +1 -1
- package/dist/src/components/Box/box.types.d.ts +53 -0
- package/dist/src/components/Box/box.types.d.ts.map +1 -1
- package/dist/src/components/Button/Button.d.ts.map +1 -1
- package/dist/src/components/Button/button.types.d.ts +35 -0
- package/dist/src/components/Button/button.types.d.ts.map +1 -1
- package/dist/src/components/Card/Card.d.ts +107 -0
- package/dist/src/components/Card/Card.d.ts.map +1 -0
- package/dist/src/components/Card/card.types.d.ts +119 -0
- package/dist/src/components/Card/card.types.d.ts.map +1 -0
- package/dist/src/components/Chip/Chip.d.ts +67 -0
- package/dist/src/components/Chip/Chip.d.ts.map +1 -0
- package/dist/src/components/Chip/chip.types.d.ts +113 -0
- package/dist/src/components/Chip/chip.types.d.ts.map +1 -0
- package/dist/src/components/Chip/chip.variants.d.ts +155 -0
- package/dist/src/components/Chip/chip.variants.d.ts.map +1 -0
- package/dist/src/components/IconButton/IconButton.d.ts +57 -0
- package/dist/src/components/IconButton/IconButton.d.ts.map +1 -0
- package/dist/src/components/IconButton/iconButton.types.d.ts +96 -0
- package/dist/src/components/IconButton/iconButton.types.d.ts.map +1 -0
- package/dist/src/components/IconButton/iconButton.variants.d.ts +26 -0
- package/dist/src/components/IconButton/iconButton.variants.d.ts.map +1 -0
- package/dist/src/components/Menu/Menu.d.ts +118 -0
- package/dist/src/components/Menu/Menu.d.ts.map +1 -0
- package/dist/src/components/Menu/menu.types.d.ts +179 -0
- package/dist/src/components/Menu/menu.types.d.ts.map +1 -0
- package/dist/src/components/Menu/menu.variants.d.ts +129 -0
- package/dist/src/components/Menu/menu.variants.d.ts.map +1 -0
- package/dist/src/components/Snackbar/Snackbar.d.ts.map +1 -1
- package/dist/src/components/Snackbar/snackbar.types.d.ts +40 -3
- package/dist/src/components/Snackbar/snackbar.types.d.ts.map +1 -1
- package/dist/src/components/Snackbar/snackbar.variants.d.ts +12 -57
- package/dist/src/components/Snackbar/snackbar.variants.d.ts.map +1 -1
- package/dist/src/components/Spinner/Spinner.d.ts +44 -0
- package/dist/src/components/Spinner/Spinner.d.ts.map +1 -0
- package/dist/src/components/Spinner/spinner.types.d.ts +89 -0
- package/dist/src/components/Spinner/spinner.types.d.ts.map +1 -0
- package/dist/src/components/Spinner/spinner.variants.d.ts +111 -0
- package/dist/src/components/Spinner/spinner.variants.d.ts.map +1 -0
- package/dist/src/components/Table/cells/RenderChip.d.ts +15 -72
- package/dist/src/components/Table/cells/RenderChip.d.ts.map +1 -1
- package/dist/src/components/_shared/severity/index.d.ts +21 -0
- package/dist/src/components/_shared/severity/index.d.ts.map +1 -0
- package/dist/src/components/_shared/severity/severity.types.d.ts +48 -0
- package/dist/src/components/_shared/severity/severity.types.d.ts.map +1 -0
- package/dist/src/components/_shared/severity/severityIcons.d.ts +45 -0
- package/dist/src/components/_shared/severity/severityIcons.d.ts.map +1 -0
- package/dist/src/components/_shared/severity/severityVariants.d.ts +22 -0
- package/dist/src/components/_shared/severity/severityVariants.d.ts.map +1 -0
- package/dist/src/index.d.ts +27 -2
- package/dist/src/index.d.ts.map +1 -1
- package/package.json +8 -7
- package/src/components/Alert/Alert.test.tsx +302 -0
- package/src/components/Alert/Alert.tsx +186 -0
- package/src/components/Alert/alert.types.ts +144 -0
- package/src/components/Alert/alert.variants.ts +71 -0
- package/src/components/Autocomplete/autocomplete.variants.ts +1 -1
- package/src/components/Avatar/Avatar.test.tsx +287 -0
- package/src/components/Avatar/Avatar.tsx +304 -0
- package/src/components/Avatar/avatar.types.ts +205 -0
- package/src/components/Avatar/avatar.variants.ts +194 -0
- package/src/components/Badge/Badge.test.tsx +385 -0
- package/src/components/Badge/Badge.tsx +174 -0
- package/src/components/Badge/badge.types.ts +154 -0
- package/src/components/Badge/badge.variants.ts +161 -0
- package/src/components/Box/Box.test.tsx +21 -0
- package/src/components/Box/Box.tsx +32 -3
- package/src/components/Box/box.types.ts +55 -0
- package/src/components/Button/Button.test.tsx +21 -0
- package/src/components/Button/Button.tsx +28 -27
- package/src/components/Button/button.types.ts +36 -0
- package/src/components/Card/Card.test.tsx +291 -0
- package/src/components/Card/Card.tsx +241 -0
- package/src/components/Card/card.types.ts +132 -0
- package/src/components/Chip/Chip.test.tsx +316 -0
- package/src/components/Chip/Chip.tsx +224 -0
- package/src/components/Chip/chip.types.ts +128 -0
- package/src/components/Chip/chip.variants.ts +173 -0
- package/src/components/DataGrid/visibility/ColumnVisibilityMenu.tsx +1 -1
- package/src/components/IconButton/IconButton.test.tsx +367 -0
- package/src/components/IconButton/IconButton.tsx +159 -0
- package/src/components/IconButton/iconButton.types.ts +106 -0
- package/src/components/IconButton/iconButton.variants.ts +31 -0
- package/src/components/LeftNav/leftNav.variants.ts +2 -2
- package/src/components/Menu/Menu.test.tsx +408 -0
- package/src/components/Menu/Menu.tsx +335 -0
- package/src/components/Menu/menu.types.ts +221 -0
- package/src/components/Menu/menu.variants.ts +132 -0
- package/src/components/Pagination/pagination.variants.ts +1 -1
- package/src/components/Snackbar/Snackbar.tsx +46 -28
- package/src/components/Snackbar/snackbar.types.ts +47 -3
- package/src/components/Snackbar/snackbar.variants.ts +29 -22
- package/src/components/Spinner/Spinner.test.tsx +199 -0
- package/src/components/Spinner/Spinner.tsx +158 -0
- package/src/components/Spinner/spinner.types.ts +113 -0
- package/src/components/Spinner/spinner.variants.ts +83 -0
- package/src/components/Table/cells/RenderChip.tsx +24 -87
- package/src/components/Table/cells/RowActionsMenu.tsx +1 -1
- package/src/components/TextField/TextField.test.tsx +5 -1
- package/src/components/_shared/severity/index.ts +33 -0
- package/src/components/_shared/severity/severity.types.ts +50 -0
- package/src/components/_shared/severity/severityIcons.tsx +104 -0
- package/src/components/_shared/severity/severityVariants.test.ts +136 -0
- package/src/components/_shared/severity/severityVariants.ts +115 -0
- package/src/index.ts +163 -1
- package/vite.config.ts +8 -0
- package/vitest.config.mts +8 -1
- package/LICENSE +0 -21
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,238 @@ This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
12
12
|
> duplicated intentionally — no shared "lowest common denominator" headless
|
|
13
13
|
> layer.
|
|
14
14
|
|
|
15
|
+
## [1.1.0] — 2026-06-18
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **`<Alert>` + `<AlertTitle>` components.** New inline persistent
|
|
20
|
+
status surface — companion to `<Snackbar>`'s transient toast. Full
|
|
21
|
+
MUI Alert API parity (`severity`, `variant`, `icon`, `onClose`,
|
|
22
|
+
`action`, `role`, `<AlertTitle>` sub-component). Single deliberate
|
|
23
|
+
divergence: `severity="danger"` instead of MUI's `severity="error"`
|
|
24
|
+
— aligned with the `danger.*` token palette (semantically identical,
|
|
25
|
+
documented in the migration guide). Adds the Dashforge-specific
|
|
26
|
+
`visibleWhen` (engine-reactive predicate) and `access` (RBAC) props,
|
|
27
|
+
same contract as `<TextField>` / `<Button>` / etc.
|
|
28
|
+
- **Menu family — `<Menu>`, `<MenuTrigger>`, `<MenuContent>`,
|
|
29
|
+
`<MenuItem>`, `<MenuLabel>`, `<MenuSeparator>`, `<MenuSkeleton>`
|
|
30
|
+
(P8, Sprint 4.4).** Compound action-menu API built on
|
|
31
|
+
`@radix-ui/react-dropdown-menu` — the purpose-built primitive
|
|
32
|
+
ships full WAI-ARIA menu pattern (`role="menu"` / `role="menuitem"`
|
|
33
|
+
/ `role="separator"`), keyboard navigation (↑↓ Home End Enter
|
|
34
|
+
Esc Tab), type-ahead, focus management, and lazy portal mount.
|
|
35
|
+
`<MenuItem>` is `React.memo`-wrapped (Atlaskit-style perf — each
|
|
36
|
+
item re-renders only on prop change, not when siblings mutate).
|
|
37
|
+
`<MenuSkeleton>` provides Atlaskit-inspired loading state:
|
|
38
|
+
N placeholder rows matching real-item geometry, useful during
|
|
39
|
+
fetch-while-open patterns where a generic spinner would be a
|
|
40
|
+
perceived-perf regression. `<MenuItem color="danger">` highlights
|
|
41
|
+
destructive actions with a red soft-bg hover state.
|
|
42
|
+
Bridge integration on `<MenuItem>`: `access` (hide/disable per
|
|
43
|
+
RBAC) + `visibleWhen` (engine-reactive predicate — falsy → item
|
|
44
|
+
renders `null`, doesn't occupy a row). `closeOnItemClick` on
|
|
45
|
+
`<Menu>` (default `true`) for the standard action-menu pattern;
|
|
46
|
+
flip to `false` for filter / multi-select menus. Skipped for v1:
|
|
47
|
+
sub-menus (Atlaskit default — composable via Radix primitives if
|
|
48
|
+
needed later as additive change) and controlled selection mode
|
|
49
|
+
(use `<CheckboxGroup>` / `<RadioGroup>` standalone instead). New
|
|
50
|
+
runtime dep: `@radix-ui/react-dropdown-menu` (added to
|
|
51
|
+
`@dashforge/tw` `dependencies`, transitive — no consumer install
|
|
52
|
+
step required).
|
|
53
|
+
- **`<Badge>` component (P7, Sprint 4.4).** Anchored indicator
|
|
54
|
+
(count / dot / short text overlay) — wrapper mode. For inline
|
|
55
|
+
standalone pills (status labels, removable tags), use `<Chip>` —
|
|
56
|
+
Badge and Chip are complementary: Chip is interactive
|
|
57
|
+
(`onClick`, `onDelete`, `selected`), Badge is passive overlay.
|
|
58
|
+
API: `content` (number/string), `dot` mode, `max` (default 99,
|
|
59
|
+
overflow renders as `"N+"`), `showZero` (default false — typical
|
|
60
|
+
notification UX), `invisible` (DOM-stay hide for fade animations),
|
|
61
|
+
`placement` (4 corners), `overlap` (`'rectangular'` default for
|
|
62
|
+
IconButton / Card; `'circular'` for Avatar — adds 14% inset to
|
|
63
|
+
align with the round edge), `withRing` default true (auto-inverting
|
|
64
|
+
`ring-neutral-50` for visual separation from the anchor surface).
|
|
65
|
+
Default color `'danger'` matches the standard "needs attention"
|
|
66
|
+
notification UX (red dot/count). Bridge: `access` + `visibleWhen`
|
|
67
|
+
— gate the badge while the anchor always renders. Skipped: size
|
|
68
|
+
axis (badge sizes to content; demand emerges → add later);
|
|
69
|
+
standalone mode (use `<Chip>` instead — TypeScript enforces
|
|
70
|
+
`children` required); `<Badge.Ribbon>` corner pattern (AntD-only
|
|
71
|
+
edge case).
|
|
72
|
+
- **`<Spinner>` component (P6, Sprint 4.4).** Rotating-arc loading
|
|
73
|
+
indicator. SVG path + Tailwind `animate-spin` (pure CSS,
|
|
74
|
+
GPU-accelerated, gated on `motion-reduce` per WCAG 2.3.3). Color
|
|
75
|
+
inherits via `currentColor` when `color` is omitted — works
|
|
76
|
+
seamlessly inside `<Button>`, `<Alert>`, `<Card>`, or any colored
|
|
77
|
+
container with zero configuration. Pass an explicit `color`
|
|
78
|
+
(7 intents) for standalone usage. Size axis (`'xs' | 'sm' | 'md' |
|
|
79
|
+
'lg' | 'xl'`) maps to spacing tokens; `thickness` (`'thin' | 'md' |
|
|
80
|
+
'thick'`) maps to SVG `stroke-width`. **`withTrack` opt-in** renders
|
|
81
|
+
a faint ghost ring (20% opacity of currentColor) behind the
|
|
82
|
+
spinning arc — the Stripe / Vercel / Linear "premium spinner" look,
|
|
83
|
+
useful on busy backgrounds and for slow operations. **`delay` prop
|
|
84
|
+
(Atlassian-style anti-flash)** mounts the spinner as `null` for the
|
|
85
|
+
first N ms — quick operations that finish before the delay
|
|
86
|
+
never render the spinner. Pairs naturally with `visibleWhen` for
|
|
87
|
+
the canonical pattern `<Spinner visibleWhen={() => isSubmitting}
|
|
88
|
+
delay={150} />`. A11y: `role="status"` + `aria-live="polite"` +
|
|
89
|
+
visually-hidden label (default `'Loading'`). Decorative mode
|
|
90
|
+
(`label=""`) suppresses role + label entirely — used internally by
|
|
91
|
+
Button / IconButton loading state to avoid duplicate
|
|
92
|
+
announcements (the parent button already carries `aria-busy`).
|
|
93
|
+
**Refactor**: `<Button>` and `<IconButton>` loading state now
|
|
94
|
+
delegates to `<Spinner>` internally — single source of truth, the
|
|
95
|
+
spinner look propagates everywhere automatically if it changes.
|
|
96
|
+
No `access` (loading state is not permission-driven; wrap in `Box`
|
|
97
|
+
if needed).
|
|
98
|
+
- **`<Avatar>` + `<AvatarGroup>` components (P5, Sprint 4.4).**
|
|
99
|
+
Image / initials / icon visual identity primitive. `<Avatar>` falls
|
|
100
|
+
back through a 4-step chain: `src` loads OK → `<img>`; `src` fails
|
|
101
|
+
→ initials from `name`; no `src` + `name` set → initials from
|
|
102
|
+
`name` (first letter of first 2 whitespace-separated words,
|
|
103
|
+
uppercased — Mantine-style auto-generation); everything absent →
|
|
104
|
+
generic user SVG icon. Visual axes: `shape: 'circle' | 'rounded' |
|
|
105
|
+
'square'` (semantic shortcut) + `radius` from the full Box token
|
|
106
|
+
scale (explicit token wins over shape); `size: 'xs' | 'sm' | 'md' |
|
|
107
|
+
'lg' | 'xl'` mapped to spacing tokens; `color` (7 intents) +
|
|
108
|
+
optional `tone` (50-900) for type-safe access to any palette shade.
|
|
109
|
+
Truly custom colours route through `sx`. `<AvatarGroup>` is a thin
|
|
110
|
+
horizontal wrapper with negative-margin overlap, `max` slice with
|
|
111
|
+
trailing "+N" overflow indicator, optional `ring-2 ring-white`
|
|
112
|
+
halo per child (default on), `size` propagation to children.
|
|
113
|
+
Skipped: built-in status/presence dots (compose with future
|
|
114
|
+
`<Badge>` via `<Badge dot><Avatar /></Badge>`), MUI-style nested
|
|
115
|
+
`<AvatarImage>` / `<AvatarFallback>` sub-components (single-element
|
|
116
|
+
API is more ergonomic). No `access` / `visibleWhen` — Avatar is
|
|
117
|
+
display-only; wrap in `<Box>` for visibility gating.
|
|
118
|
+
- **`<Card>`, `<CardContent>`, `<CardActionArea>` components (P2,
|
|
119
|
+
Sprint 4.4).** Opinionated surface preset over `<Box>`. `<Card>` is
|
|
120
|
+
a thin alias with card-shaped defaults (`variant='outlined'`,
|
|
121
|
+
`rounded='lg'`, `elevation=1`, no padding) and a restricted variant
|
|
122
|
+
axis (`'outlined' | 'elevated' | 'plain'` — `'soft'` / `'solid'`
|
|
123
|
+
belong to Box callouts and banners, not cards). `<CardContent>` is
|
|
124
|
+
a padded inner section (`p=4` default). `<CardActionArea>` is the
|
|
125
|
+
real value-add: a clickable wrapper with focus ring + hover state
|
|
126
|
+
+ Radix Slot polymorphism (router `<Link>` without `<a>`-in-
|
|
127
|
+
`<button>` a11y violation) + `selected` for option-card patterns
|
|
128
|
+
(`aria-pressed`).
|
|
129
|
+
Skipped MUI's `CardHeader`, `CardMedia`, `CardActions` —
|
|
130
|
+
composable via `Stack` + `Box` + `Typography`, no value-add to
|
|
131
|
+
ship as separate components. Atlassian DS validates the
|
|
132
|
+
minimalist take (they ship no Card primitive at all).
|
|
133
|
+
- **`access` + `visibleWhen` retrofit to `<Box>` (Sprint 4.4 surface
|
|
134
|
+
alignment, additive).** The bridge integration is now available on
|
|
135
|
+
Dashforge's surface primitive too. Use case: dashboard with
|
|
136
|
+
role-based cards (`access` hides revenue card from non-billing
|
|
137
|
+
roles), state-driven sections (`visibleWhen` toggles a section
|
|
138
|
+
based on form / external state) without `{condition && <Box>...}`
|
|
139
|
+
JSX guards. Idempotent for existing consumers — both props default
|
|
140
|
+
to no-op. RBAC-disabled / readonly Box surfaces dim visually and
|
|
141
|
+
carry `aria-disabled` / `aria-readonly` so descendants and
|
|
142
|
+
assistive tech can react. By extension, `<Card>` (which extends
|
|
143
|
+
`BoxProps`) inherits both props automatically.
|
|
144
|
+
- **`visibleWhen` prop extended to `<Button>` + `<IconButton>` (Sprint
|
|
145
|
+
4.4 alignment).** Previously available only on form fields and the
|
|
146
|
+
new `<Alert>` / `<Chip>`, the engine-reactive visibility predicate
|
|
147
|
+
now ships on the action-trigger components too. The pattern is now
|
|
148
|
+
uniform across every interactive Dashforge TW primitive (Button,
|
|
149
|
+
IconButton, Chip, plus all form fields + Alert): `visibleWhen?:
|
|
150
|
+
(engine: Engine) => boolean` returns `null` when false; reactive on
|
|
151
|
+
engine state changes inside `<DashForm>`, closure-based outside.
|
|
152
|
+
Idempotent for consumers who don't use it.
|
|
153
|
+
- **`<Chip>` component.** Public status / filter / tag pill — promoted
|
|
154
|
+
from the internal `Table/cells/RenderChip`. The 3 × 7 (variant ×
|
|
155
|
+
color) matrix is preserved byte-identical and now lives in
|
|
156
|
+
`Chip/chip.variants.ts` as the single source of truth, consumed by
|
|
157
|
+
both the public `<Chip>` and (via thin wrapper) the legacy
|
|
158
|
+
`RenderChip` — zero breaking change for Table cell consumers.
|
|
159
|
+
Variant axis is `'soft' | 'solid' | 'outline'` (default `'soft'`,
|
|
160
|
+
Dashforge chip vocabulary — distinct from Button's
|
|
161
|
+
`'solid' | 'outline' | 'ghost' | 'link'` and Alert's
|
|
162
|
+
`'standard' | 'filled' | 'outlined'`, see the design note in
|
|
163
|
+
`MIGRATION.md`). Full MUI Chip API parity: `label`, `icon`, `avatar`
|
|
164
|
+
(avatar wins over icon when both set), `clickable`, `onClick`,
|
|
165
|
+
`onDelete`, `deleteIcon`, `deleteLabel`. Plus Dashforge extras:
|
|
166
|
+
`selected` (filter-pill pressed state with `aria-pressed`) and
|
|
167
|
+
`access` (RBAC integration, same contract as `<Button>` /
|
|
168
|
+
`<IconButton>`). Static chips render as `<span>`; clickable chips
|
|
169
|
+
render as `<button>` with focus ring + hover state. 7 colors, 2
|
|
170
|
+
sizes.
|
|
171
|
+
- **`<IconButton>` component.** Square, icon-only action button —
|
|
172
|
+
reuses `buttonVariants` 1:1 (`variant: 'solid' | 'outline' | 'ghost'
|
|
173
|
+
| 'link'`, `color: 'primary' | 'secondary' | 'success' | 'warning' |
|
|
174
|
+
'danger'`, `size: 'sm' | 'md' | 'lg'`, `loading`). Adds square
|
|
175
|
+
geometry (token-driven `w-N + px-0 + aspect-square`), a
|
|
176
|
+
TS-enforced `aria-label` (icon-only buttons MUST have an accessible
|
|
177
|
+
name), `asChild` via Radix Slot, and the standard `access` RBAC
|
|
178
|
+
integration. No `visibleWhen` / `slotProps` by design — mirrors
|
|
179
|
+
`<Button>`. Bundles `<IconButton>` exports + `ICON_BUTTON_BASE` /
|
|
180
|
+
`ICON_BUTTON_SIZE_OVERRIDES` constants for advanced overrides.
|
|
181
|
+
- **`_shared/severity/` foundation.** New shared module
|
|
182
|
+
(`_shared/severity/{severity.types, severityVariants, severityIcons,
|
|
183
|
+
index}`) consumed by `<Alert>` and the refactored `<Snackbar>` (and
|
|
184
|
+
future Banner). Centralises the 3×4 (variant × severity) color
|
|
185
|
+
matrix and the per-severity default icons. Every cell is
|
|
186
|
+
token-driven via `dashforgePreset()` — no hardcoded hex, no `dark:`
|
|
187
|
+
variants on neutral.
|
|
188
|
+
|
|
189
|
+
### Changed (BREAKING — visual only)
|
|
190
|
+
|
|
191
|
+
- **`<Snackbar>` default appearance updated.** Snackbar now consumes
|
|
192
|
+
the same 3-variant severity surface as `<Alert>` (`standard` /
|
|
193
|
+
`filled` / `outlined`), with `standard` (soft tinted) as the new
|
|
194
|
+
default. Previously, severity discriminated only border + icon
|
|
195
|
+
colour; the surface bg + text stayed neutral. The new default
|
|
196
|
+
visually communicates severity at first glance (the previous
|
|
197
|
+
pattern read as "neutral message with coloured trim"). Consumers
|
|
198
|
+
who want the closest visual match to 1.0.x can pass
|
|
199
|
+
`variant="outlined"` on each enqueue or set
|
|
200
|
+
`<SnackbarProvider defaults={{ variant: 'outlined' }}>`.
|
|
201
|
+
- **`<Snackbar>` Unicode-glyph icons replaced with inline SVG.** The
|
|
202
|
+
per-severity defaults are no longer `ⓘ ✓ ⚠ ✕` Unicode glyphs but
|
|
203
|
+
inline stroke SVG icons shared with `<Alert>` via
|
|
204
|
+
`_shared/severity/severityIcons`. Consumers who want the legacy
|
|
205
|
+
glyphs can pass `icon={<span>{glyph}</span>}` on each enqueue.
|
|
206
|
+
- **`<Snackbar>` `severity="info"` now uses the dedicated `info-*`
|
|
207
|
+
token scale.** Previously aliased to `primary-*` (inadvertent
|
|
208
|
+
inconsistency with the rest of the catalog). `patchTheme({ info:
|
|
209
|
+
... })` now correctly targets the info snackbar surface without
|
|
210
|
+
spilling into primary consumers.
|
|
211
|
+
|
|
212
|
+
### Added — `<Snackbar>` API extensions
|
|
213
|
+
|
|
214
|
+
- **`variant` option on `enqueue()` and `defaults`** —
|
|
215
|
+
`'standard' | 'filled' | 'outlined'`. Same axis as `<Alert>`.
|
|
216
|
+
- **`icon` option on `enqueue()`** — same tristate semantics as Alert
|
|
217
|
+
(`undefined` → default per severity, `ReactNode` → custom, `false`
|
|
218
|
+
→ no icon).
|
|
219
|
+
- New exported type `SnackbarVariant`.
|
|
220
|
+
|
|
221
|
+
### Fixed
|
|
222
|
+
|
|
223
|
+
- **Defensive list-style reset across interactive `<ul>` lists.**
|
|
224
|
+
`Autocomplete` (listbox), `Pagination`, `LeftNav` (outer list + group
|
|
225
|
+
children), `DataGrid` column-visibility menu, and `Table` row-actions
|
|
226
|
+
menu now ship `list-none pl-0 m-0` directly on their `<ul>` variants
|
|
227
|
+
/ inline classes instead of relying on the consumer environment
|
|
228
|
+
having Tailwind preflight active. Previously, environments without
|
|
229
|
+
preflight — or with a **scoped** preflight that intentionally omits
|
|
230
|
+
the `ol, ul { list-style: none }` reset (multi-ecosystem docs sites,
|
|
231
|
+
apps that opt out of preflight) — would render browser-default disc
|
|
232
|
+
bullets next to each option / row. The change is idempotent: in
|
|
233
|
+
consumers that have preflight, the new classes are no-ops; in
|
|
234
|
+
consumers without, the components render correctly out of the box.
|
|
235
|
+
|
|
236
|
+
## [1.0.0] — 2026-05-23
|
|
237
|
+
|
|
238
|
+
**Stable release.** First semver-stable version. The public API is now
|
|
239
|
+
governed by strict semver — any future breaking change requires a major
|
|
240
|
+
bump. Functionally identical to the previous beta tarball.
|
|
241
|
+
|
|
242
|
+
- Version: `1.0.0`
|
|
243
|
+
- Cross-package `@dashforge/*` peer-dependency ranges updated to `^1.0.0`.
|
|
244
|
+
- See the [top-level CHANGELOG](https://github.com/kensaadi/dashforge/blob/main/CHANGELOG.md#100---2026-05-23) for the coordinated release context.
|
|
245
|
+
- See [`MIGRATION.md`](https://github.com/kensaadi/dashforge/blob/main/MIGRATION.md) for the upgrade guide from any `0.x-beta` to `1.0.0` (no code changes required).
|
|
246
|
+
|
|
15
247
|
## [0.11.0-beta] — 2026-05-22
|
|
16
248
|
|
|
17
249
|
**Sprint 7 — Tabs.** `<Tabs>` rebuilt as a custom, clean-room component.
|
|
@@ -137,8 +369,8 @@ Strictly additive — no breaking changes on existing component APIs.
|
|
|
137
369
|
starts a column-reorder drag. On coarse-pointer (touch) devices the
|
|
138
370
|
reorder `draggable` affordance is disabled — native HTML5
|
|
139
371
|
drag-and-drop does not fire touch events, so it was a dead
|
|
140
|
-
interaction.
|
|
141
|
-
|
|
372
|
+
interaction. A pointer-event reorder covering touch is tracked
|
|
373
|
+
internally.
|
|
142
374
|
- **`Table`** now emits a dev-only `console.warn` when `getRowId` is
|
|
143
375
|
omitted while sort / search / selection / expandable rows are
|
|
144
376
|
active — the positional-index fallback breaks row identity on
|
|
@@ -1349,16 +1581,6 @@ have shipped as `0.2.2-beta` in isolation.
|
|
|
1349
1581
|
Breadcrumbs in its center slot, so fixing the Breadcrumbs link
|
|
1350
1582
|
fixes TopBar transitively.
|
|
1351
1583
|
|
|
1352
|
-
### Internal
|
|
1353
|
-
|
|
1354
|
-
- **`libs/dashforge/tw/CONSUMER-VALIDATION.md`** — Sprint 2 P1
|
|
1355
|
-
deliverable. Per-component status table for the dash-consumer
|
|
1356
|
-
end-to-end validation pass (24 components, 7-point check each).
|
|
1357
|
-
Records the pattern lesson that motivated the Autocomplete
|
|
1358
|
-
async fix: the bug was invisible to both unit tests (using
|
|
1359
|
-
static `options`) and the docs lab (static demo) — only a real
|
|
1360
|
-
consumer with `loadOptions` configured exposed it.
|
|
1361
|
-
|
|
1362
1584
|
### Compatibility
|
|
1363
1585
|
|
|
1364
1586
|
| Compatibility axis | Pre-`0.3.0` | Post-`0.3.0` |
|
package/COVERAGE.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# COVERAGE — `@dashforge/tw`
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
3
|
+
> Test-coverage audit for `@dashforge/tw`. Current numbers, the gap-fill
|
|
4
|
+
> performed, and the tracked debt.
|
|
5
5
|
|
|
6
6
|
## Current coverage (`vitest --coverage`, v8 provider)
|
|
7
7
|
|
package/PARITY.md
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
# `@dashforge/tw` ↔ `@dashforge/ui` parity audit
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
3
|
+
> Per-component diff between the two Dashforge UI lines for the
|
|
4
|
+
> **10 bridge-integrated components**.
|
|
5
5
|
>
|
|
6
|
-
> **Motivation
|
|
7
|
-
> support customer migration MUI→TW (no consumer switches across UI
|
|
8
|
-
> ecosystems in real life). It exists because:
|
|
6
|
+
> **Motivation.** This audit ensures:
|
|
9
7
|
>
|
|
10
8
|
> 1. **Internal consistency** — a refactor on `@dashforge/ui` that
|
|
11
9
|
> doesn't land on `@dashforge/tw` would otherwise be invisible.
|
|
12
|
-
> 2. **Bridge contract validation** —
|
|
13
|
-
>
|
|
14
|
-
> 3. **
|
|
10
|
+
> 2. **Bridge contract validation** — the same `@dashforge/forms`
|
|
11
|
+
> schema works identically on both lines.
|
|
12
|
+
> 3. **Parallel starter-kit maintainability** — two parallel kits
|
|
15
13
|
> (one MUI, one TW) require call-site-level parity to stay
|
|
16
|
-
>
|
|
14
|
+
> in sync.
|
|
17
15
|
|
|
18
16
|
## Versions audited
|
|
19
17
|
|
package/PERFORMANCE.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# `@dashforge/tw` performance baseline
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
5
|
-
>
|
|
6
|
-
> justify the regression in `CHANGELOG.md`.
|
|
3
|
+
> Establishes the performance commitment for `@dashforge/tw`. Every
|
|
4
|
+
> subsequent release should hold these numbers or justify any
|
|
5
|
+
> regression in `CHANGELOG.md`.
|
|
7
6
|
|
|
8
7
|
## Bundle size
|
|
9
8
|
|
package/README.md
CHANGED
|
@@ -1,38 +1,97 @@
|
|
|
1
1
|
# @dashforge/tw
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
**A props-driven React UI library on top of Tailwind CSS.** Every utility
|
|
4
|
+
that matters for the public API becomes a typed prop — `size`, `color`,
|
|
5
|
+
`variant`, `layout`, … — so you write components that read like a design
|
|
6
|
+
system and render output that's pure Tailwind. Raw `className` / `sx` /
|
|
7
|
+
`slotProps` stay available as escape hatches for the cases the prop
|
|
8
|
+
surface doesn't cover.
|
|
9
|
+
|
|
10
|
+
> **Status**: `1.0.0` — **stable release**. Public API frozen, semver
|
|
11
|
+
> guaranteed. 37 components shipped across forms, data display,
|
|
12
|
+
> navigation, feedback, layout primitives, and providers. The MUI side
|
|
13
|
+
> of Dashforge (`@dashforge/ui`, `@dashforge/theme-mui`,
|
|
14
|
+
> `@dashforge/theme-core`) is **fully isolated** from this package — the
|
|
15
|
+
> two ecosystems share only the bridge layer (`@dashforge/forms` +
|
|
8
16
|
> `@dashforge/ui-core` + `@dashforge/rbac`).
|
|
9
17
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
## Why Dashforge TW
|
|
19
|
+
|
|
20
|
+
- **Props, not utility soup** — component APIs that read like MUI,
|
|
21
|
+
render output that's pure Tailwind. No more 40-class `<button>` tags
|
|
22
|
+
copied across the codebase.
|
|
23
|
+
- **Dark mode built in** — CSS-variable inversion via the
|
|
24
|
+
`dashforgePreset` Tailwind preset. Same JSX renders in light and dark
|
|
25
|
+
without a single `dark:` variant.
|
|
26
|
+
- **RBAC-aware out of the box** — every interactive component takes an
|
|
27
|
+
`access` prop, hidden / disabled / read-only centrally via
|
|
28
|
+
`@dashforge/rbac`.
|
|
29
|
+
- **Bridge-integrated forms** — Form Closure v1, controlled error
|
|
30
|
+
gating, StrictMode-safe registration, per-field re-render isolation
|
|
31
|
+
via the shared `@dashforge/forms` engine.
|
|
32
|
+
- **Router-agnostic** — pass `linkComponent` to use React Router, Next,
|
|
33
|
+
TanStack Router, or any other navigation primitive.
|
|
34
|
+
- **TypeScript-first** — typed tokens, typed variants, typed slot
|
|
35
|
+
overrides, augmentable per-package.
|
|
16
36
|
|
|
17
37
|
## Component catalog
|
|
18
38
|
|
|
19
|
-
### Form components (
|
|
39
|
+
### Form components (13)
|
|
20
40
|
|
|
21
41
|
`Button` · `TextField` · `Checkbox` · `Switch` · `RadioGroup` ·
|
|
22
42
|
`Textarea` · `NumberField` · `OTPField` · `Autocomplete` ·
|
|
23
|
-
`DateTimePicker`
|
|
43
|
+
`DatePicker` · `DateRangePicker` · `TimePicker` · `DateTimePicker`
|
|
24
44
|
|
|
25
45
|
All bridge-integrated, RBAC-aware (`access` prop), Form Closure v1
|
|
26
46
|
error gating, StrictMode-safe.
|
|
27
47
|
|
|
28
|
-
###
|
|
48
|
+
### Navigation & shell (4)
|
|
29
49
|
|
|
30
|
-
`
|
|
50
|
+
`AppShell` · `LeftNav` · `TopBar` · `Breadcrumbs`
|
|
31
51
|
|
|
32
52
|
Router-agnostic — pass a `linkComponent` prop for SPA navigation
|
|
33
53
|
(React Router, Next, TanStack Router, …). Mobile-responsive shell
|
|
34
54
|
with drawer + body scroll lock.
|
|
35
55
|
|
|
56
|
+
### Layout primitives (8)
|
|
57
|
+
|
|
58
|
+
`Box` · `Container` · `Stack` · `Grid` · `Divider` · `AspectRatio` ·
|
|
59
|
+
`Typography` · `VisuallyHidden`
|
|
60
|
+
|
|
61
|
+
Polymorphic via `as` prop, dark-mode-aware, prop-driven spacing /
|
|
62
|
+
sizing / alignment.
|
|
63
|
+
|
|
64
|
+
### Data display (3)
|
|
65
|
+
|
|
66
|
+
`Table` · `DataGrid` · `Pagination`
|
|
67
|
+
|
|
68
|
+
Virtualized rows, sticky columns (left + right), server-side mode,
|
|
69
|
+
per-column filter chips, column resize / reorder / visibility,
|
|
70
|
+
controlled or uncontrolled state.
|
|
71
|
+
|
|
72
|
+
### Disclosure (2)
|
|
73
|
+
|
|
74
|
+
`Accordion` · `Tabs`
|
|
75
|
+
|
|
76
|
+
Radix-based, keyboard-accessible, fully styled through props.
|
|
77
|
+
|
|
78
|
+
### Overlay (3)
|
|
79
|
+
|
|
80
|
+
`Dialog` · `Popover` · `Tooltip`
|
|
81
|
+
|
|
82
|
+
Portal-rendered, focus-trapped, dismiss-on-esc + click-outside
|
|
83
|
+
out of the box.
|
|
84
|
+
|
|
85
|
+
### Feedback (1)
|
|
86
|
+
|
|
87
|
+
`Skeleton`
|
|
88
|
+
|
|
89
|
+
### Date (1)
|
|
90
|
+
|
|
91
|
+
`Calendar` — standalone month grid. Also powers `DatePicker` /
|
|
92
|
+
`DateRangePicker` / `DateTimePicker` under the hood, but exported on
|
|
93
|
+
its own for custom layouts.
|
|
94
|
+
|
|
36
95
|
### Providers (2)
|
|
37
96
|
|
|
38
97
|
`ConfirmDialogProvider` + `useConfirm()` · `SnackbarProvider` +
|
package/THEME-AUDIT.md
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
# THEME-AUDIT — @dashforge/tw catalog identity sweep
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
5
|
-
> (memory: `feedback_dashforge_preset_is_identity`).
|
|
3
|
+
> Audit of every `@dashforge/tw` component against the **default
|
|
4
|
+
> `dashforgePreset()` identity rule**.
|
|
6
5
|
>
|
|
7
6
|
> **Rule recap.** The `dashforgePreset()` CSS-variable swap
|
|
8
7
|
> auto-inverts the neutral palette:
|
|
9
8
|
> `bg-neutral-50` / `text-neutral-900` etc. resolve to the
|
|
10
9
|
> appropriate physical color via `--df-tw-color-neutral-N`. Adding a
|
|
11
10
|
> `dark:` variant on a neutral class **double-inverts** the value
|
|
12
|
-
> and breaks dark mode. The
|
|
11
|
+
> and breaks dark mode. The Table fix established the
|
|
13
12
|
> canonical patterns; Sprint 4.3 applies them to the whole catalog.
|
|
14
13
|
|
|
15
14
|
## Scoring legend
|
|
Binary file
|