@viglet/viglet-design-system 2026.3.2 → 2026.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +334 -8
- package/dist/assets.cjs +1 -0
- package/dist/assets.es.js +2 -0
- package/dist/badge-locale-BxI9TwkE.js +579 -0
- package/dist/badge-locale-sIsBdP_e.cjs +7 -0
- package/dist/bento/bento-actions-menu.d.ts +42 -0
- package/dist/bento/bento-actions-menu.d.ts.map +1 -0
- package/dist/bento/bento-back-to-top.d.ts +11 -0
- package/dist/bento/bento-back-to-top.d.ts.map +1 -0
- package/dist/bento/bento-command-palette.d.ts +28 -0
- package/dist/bento/bento-command-palette.d.ts.map +1 -0
- package/dist/bento/bento-count-tile.d.ts +18 -0
- package/dist/bento/bento-count-tile.d.ts.map +1 -0
- package/dist/bento/bento-empty-state.d.ts +35 -0
- package/dist/bento/bento-empty-state.d.ts.map +1 -0
- package/dist/bento/bento-entity-shell.d.ts +123 -0
- package/dist/bento/bento-entity-shell.d.ts.map +1 -0
- package/dist/bento/bento-entity-tile.d.ts +40 -0
- package/dist/bento/bento-entity-tile.d.ts.map +1 -0
- package/dist/bento/bento-form-hero.d.ts +91 -0
- package/dist/bento/bento-form-hero.d.ts.map +1 -0
- package/dist/bento/bento-form-section.d.ts +31 -0
- package/dist/bento/bento-form-section.d.ts.map +1 -0
- package/dist/bento/bento-hero-icon-picker.d.ts +35 -0
- package/dist/bento/bento-hero-icon-picker.d.ts.map +1 -0
- package/dist/bento/bento-hero.d.ts +62 -0
- package/dist/bento/bento-hero.d.ts.map +1 -0
- package/dist/bento/bento-inline-edit.d.ts +52 -0
- package/dist/bento/bento-inline-edit.d.ts.map +1 -0
- package/dist/bento/bento-layout.d.ts +52 -0
- package/dist/bento/bento-layout.d.ts.map +1 -0
- package/dist/bento/bento-list-page.d.ts +124 -0
- package/dist/bento/bento-list-page.d.ts.map +1 -0
- package/dist/bento/bento-nav-rail.d.ts +32 -0
- package/dist/bento/bento-nav-rail.d.ts.map +1 -0
- package/dist/bento/bento-nav.d.ts +69 -0
- package/dist/bento/bento-nav.d.ts.map +1 -0
- package/dist/bento/bento-save-bar.d.ts +36 -0
- package/dist/bento/bento-save-bar.d.ts.map +1 -0
- package/dist/bento/bento-scroll-fade.d.ts +20 -0
- package/dist/bento/bento-scroll-fade.d.ts.map +1 -0
- package/dist/bento/bento-scroll-save-bar.d.ts +22 -0
- package/dist/bento/bento-scroll-save-bar.d.ts.map +1 -0
- package/dist/bento/bento-section-chrome.d.ts +60 -0
- package/dist/bento/bento-section-chrome.d.ts.map +1 -0
- package/dist/bento/bento-section.d.ts +27 -0
- package/dist/bento/bento-section.d.ts.map +1 -0
- package/dist/bento/bento-shortcuts-dialog.d.ts +15 -0
- package/dist/bento/bento-shortcuts-dialog.d.ts.map +1 -0
- package/dist/bento/bento-status-marker.d.ts +26 -0
- package/dist/bento/bento-status-marker.d.ts.map +1 -0
- package/dist/bento/bento-tile.d.ts +42 -0
- package/dist/bento/bento-tile.d.ts.map +1 -0
- package/dist/bento/bento-tones.d.ts +33 -0
- package/dist/bento/bento-tones.d.ts.map +1 -0
- package/dist/bento/bento-user-menu.d.ts +31 -0
- package/dist/bento/bento-user-menu.d.ts.map +1 -0
- package/dist/bento/index.d.ts +59 -0
- package/dist/bento/index.d.ts.map +1 -0
- package/dist/bento.cjs +1 -0
- package/dist/bento.css +442 -0
- package/dist/bento.es.js +1502 -0
- package/dist/breadcrumb.context-CGqjI0-U.js +914 -0
- package/dist/breadcrumb.context-DYeZEC65.cjs +1 -0
- package/dist/components/app-switcher.d.ts +2 -0
- package/dist/components/app-switcher.d.ts.map +1 -1
- package/dist/components/badge-locale.d.ts.map +1 -1
- package/dist/components/error-boundary.d.ts.map +1 -1
- package/dist/components/language-select.d.ts.map +1 -1
- package/dist/components/router/blank-slate.d.ts +10 -0
- package/dist/components/router/blank-slate.d.ts.map +1 -1
- package/dist/components/router/grid.list.d.ts +13 -0
- package/dist/components/router/grid.list.d.ts.map +1 -1
- package/dist/components/router/internal.sidebar.d.ts +39 -3
- package/dist/components/router/internal.sidebar.d.ts.map +1 -1
- package/dist/components/router/loading-provider.d.ts +6 -1
- package/dist/components/router/loading-provider.d.ts.map +1 -1
- package/dist/components/router/nav-main.d.ts +10 -0
- package/dist/components/router/nav-main.d.ts.map +1 -1
- package/dist/components/router/nav-user.d.ts +13 -0
- package/dist/components/router/nav-user.d.ts.map +1 -1
- package/dist/components/router/page-content.d.ts +10 -0
- package/dist/components/router/page-content.d.ts.map +1 -1
- package/dist/components/router/page-header.d.ts +13 -0
- package/dist/components/router/page-header.d.ts.map +1 -1
- package/dist/components/router/page.d.ts +13 -0
- package/dist/components/router/page.d.ts.map +1 -1
- package/dist/components/router/sticky.page.header.d.ts +14 -0
- package/dist/components/router/sticky.page.header.d.ts.map +1 -1
- package/dist/components/router/sub.page.d.ts +31 -11
- package/dist/components/router/sub.page.d.ts.map +1 -1
- package/dist/components/router/sub.page.header.d.ts +13 -0
- package/dist/components/router/sub.page.header.d.ts.map +1 -1
- package/dist/components/startup-first/startup-first.d.ts.map +1 -1
- package/dist/components/theme-provider.d.ts +37 -2
- package/dist/components/theme-provider.d.ts.map +1 -1
- package/dist/components/ui/floating-formulas-bg.d.ts +8 -1
- package/dist/components/ui/floating-formulas-bg.d.ts.map +1 -1
- package/dist/components/ui/form.d.ts +2 -2
- package/dist/components/ui/form.d.ts.map +1 -1
- package/dist/components/ui/gradient-button.d.ts.map +1 -1
- package/dist/components/ui/gradient-switch.d.ts.map +1 -1
- package/dist/components/ui/icon-picker-dialog.d.ts +35 -0
- package/dist/components/ui/icon-picker-dialog.d.ts.map +1 -0
- package/dist/components/ui/index.d.ts +1 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/section-card.d.ts +3 -3
- package/dist/components/ui/section-card.d.ts.map +1 -1
- package/dist/components/ui/sidebar.d.ts.map +1 -1
- package/dist/components/ui/slider.d.ts +1 -1
- package/dist/components/ui/slider.d.ts.map +1 -1
- package/dist/components/viglet-app-switcher.d.ts +3 -0
- package/dist/components/viglet-app-switcher.d.ts.map +1 -1
- package/dist/contexts/user.context.d.ts +24 -0
- package/dist/contexts/user.context.d.ts.map +1 -1
- package/dist/exports.json +404 -0
- package/dist/floating-formulas-bg.cjs +1 -0
- package/dist/floating-formulas-bg.css +21 -0
- package/dist/floating-formulas-bg.es.js +84 -56
- package/dist/fonts/inter-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-cyrillic-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-greek-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-greek-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-vietnamese-wght-normal.woff2 +0 -0
- package/dist/fonts/plus-jakarta-sans-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/plus-jakarta-sans-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/plus-jakarta-sans-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/plus-jakarta-sans-vietnamese-wght-normal.woff2 +0 -0
- package/dist/fonts.css +126 -0
- package/dist/hooks/use-grid-adapter.d.ts.map +1 -1
- package/dist/hooks/use-mobile.d.ts +10 -0
- package/dist/hooks/use-mobile.d.ts.map +1 -1
- package/dist/hooks/use-sub-page-breadcrumb.d.ts.map +1 -1
- package/dist/i18n/index.d.ts +136 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/locales/en/bento.json.d.ts +51 -0
- package/dist/i18n/locales/en/common.json.d.ts +7 -1
- package/dist/i18n/locales/en/forms.json.d.ts +15 -1
- package/dist/i18n/locales/en/nav.json.d.ts +3 -1
- package/dist/i18n/locales/pt/bento.json.d.ts +51 -0
- package/dist/i18n/locales/pt/common.json.d.ts +7 -1
- package/dist/i18n/locales/pt/forms.json.d.ts +15 -1
- package/dist/i18n/locales/pt/nav.json.d.ts +3 -1
- package/dist/i18n-DoNdMLEd.cjs +1 -0
- package/dist/{i18n-C94rDRaM.js → i18n-DuNITbWa.js} +155 -27
- package/dist/i18n.cjs +1 -0
- package/dist/i18n.es.js +2 -1
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.es.js +493 -750
- package/dist/lib/axios.d.ts.map +1 -1
- package/dist/lib/export-xlsx.d.ts +7 -1
- package/dist/lib/export-xlsx.d.ts.map +1 -1
- package/dist/lib/react-markers.d.ts +17 -0
- package/dist/lib/react-markers.d.ts.map +1 -0
- package/dist/lib/utils.d.ts +22 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/loading-provider-1mgM91iY.cjs +1 -0
- package/dist/loading-provider-CMnOuvdR.js +224 -0
- package/dist/preset.css +103 -3
- package/dist/products-DL_YYXkV.cjs +1 -0
- package/dist/products-Du9KB6Xl.js +9 -0
- package/dist/{rolldown-runtime-CMqjfN_6.cjs → rolldown-runtime-BocRIvOZ.cjs} +1 -1
- package/dist/router.cjs +1 -0
- package/dist/router.es.js +334 -504
- package/dist/user.context-kPAqKN4o.js +512 -0
- package/dist/user.context-r50nSWER.cjs +1 -0
- package/dist/viglet-design-system.css +1 -1
- package/dist/vite/boot-loader.d.ts +21 -7
- package/dist/vite/boot-loader.d.ts.map +1 -1
- package/dist/{vite.cjs.js → vite.cjs} +8 -8
- package/dist/vite.es.js +29 -16
- package/package.json +66 -22
- package/scripts/check-duplicates.mjs +198 -0
- package/dist/breadcrumb.context-C7VCfh49.js +0 -1501
- package/dist/breadcrumb.context-Td6Tjc_z.cjs +0 -7
- package/dist/floating-formulas-bg.cjs.js +0 -1
- package/dist/i18n-DN_2YzjB.cjs +0 -1
- package/dist/i18n.cjs.js +0 -1
- package/dist/index.cjs.js +0 -1
- package/dist/router.cjs.js +0 -1
package/README.md
CHANGED
|
@@ -1,13 +1,102 @@
|
|
|
1
1
|
# Viglet Design System
|
|
2
2
|
|
|
3
|
-
Shared component library, design tokens, hooks, utilities, and i18n for
|
|
3
|
+
Shared component library, design tokens, hooks, utilities, and i18n for the six
|
|
4
|
+
applications that install it: the Turing, Dumont and Shio consoles,
|
|
5
|
+
the Cloud Console, the Cloud Home, and Schools. `consumers.json` is the list,
|
|
6
|
+
and it is what the guards read.
|
|
7
|
+
|
|
8
|
+
**[Browse the component catalogue](https://openviglet.github.io/viglet-design-system/)** — every
|
|
9
|
+
component, its variants and its props, rebuilt on each commit to `2026.3`. Look
|
|
10
|
+
there before writing a component: the catalogue is the answer to "does this
|
|
11
|
+
already exist".
|
|
12
|
+
|
|
13
|
+
The six applications that install this package are the consumers it holds itself
|
|
14
|
+
to, declared in [`consumers.json`](consumers.json) rather than remembered: each
|
|
15
|
+
entry names its framework, its chrome, the accent it renders with and the
|
|
16
|
+
subpaths it takes, and CI refuses prose that names a subset as though it were
|
|
17
|
+
the whole set. A seventh is one entry there, and the checks widen with it.
|
|
18
|
+
|
|
19
|
+
Three are Vite consoles (Turing, Shio, Dumont), one is a Vite platform home
|
|
20
|
+
(the Cloud Home), and two are Next applications (the Cloud Console and Schools).
|
|
21
|
+
The split matters: a Next consumer takes no `./router` and no `./vite`.
|
|
4
22
|
|
|
5
23
|
## Installation
|
|
6
24
|
|
|
7
25
|
```bash
|
|
8
|
-
|
|
26
|
+
pnpm add @viglet/viglet-design-system
|
|
9
27
|
```
|
|
10
28
|
|
|
29
|
+
## Trying a change in a product before publishing
|
|
30
|
+
|
|
31
|
+
A change here is a change to shared chrome, so the question is always what it
|
|
32
|
+
does to Shio, Turing, Dumont, the Cloud Console, the Cloud Home and Schools —
|
|
33
|
+
and the answer should not require a publish. `use:local` walks a products root,
|
|
34
|
+
so it reaches the first three; the other three are checked out elsewhere and
|
|
35
|
+
`npm pack` into them is the loop until that changes (VDS73). From this checkout:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pnpm use:local # build, then push dist into every 2026.3 product on disk
|
|
39
|
+
pnpm use:local --list # show what it would write to, and stop
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
It finds the consumers by reading their `package.json`, and finds where each one
|
|
43
|
+
keeps the installed copy by following the link its own package manager made, so
|
|
44
|
+
neither a version bump nor a switch of package manager breaks the loop. Nothing
|
|
45
|
+
in the product's manifest or lockfile changes: `pnpm install` in the product puts
|
|
46
|
+
the published build back.
|
|
47
|
+
|
|
48
|
+
Pass directories to narrow it, and `--no-build` to reuse the `dist` already on
|
|
49
|
+
disk:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pnpm use:local ../shio/2026.3/shio-react --no-build
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
One thing it refuses to do: push over a tree whose dependencies are behind. It
|
|
56
|
+
writes files, and files cannot re-resolve a dependency — so if a range moved
|
|
57
|
+
here since the product last installed, the manifest it copies would ask for a
|
|
58
|
+
version the directory beside it does not have, and the product would fail to
|
|
59
|
+
build on symbols that version does not export. It names those packages and
|
|
60
|
+
stops. That is a real limit rather than a check to switch off: a range that
|
|
61
|
+
moved reaches a product through a release, not through this. `--skip-dep-check`
|
|
62
|
+
pushes anyway when you know why you want it.
|
|
63
|
+
|
|
64
|
+
## Catching a duplicate before it drifts
|
|
65
|
+
|
|
66
|
+
The package ships `dist/exports.json` — every name it exports, per entry point —
|
|
67
|
+
and a CLI that reads it. Run it in the product's own CI:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
viglet-ds-check-duplicates src
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
It fails, naming the import that replaces each local copy:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
src/components/page-header.tsx:18 declares PageHeader
|
|
77
|
+
replace it with: import { PageHeader } from "@viglet/viglet-design-system/router"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
One-line re-export shims are the sanctioned pattern and are skipped. When a
|
|
81
|
+
collision is deliberate — a product component that renders that product's own
|
|
82
|
+
data and merely shares a name — keep it by writing the reason in the file:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
// viglet-ds-allow-duplicate AppFooter -- renders Shio's build version
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
In a product's workflow, it is one step beside the lint:
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
- name: No local copy of a shared component
|
|
92
|
+
run: pnpm exec viglet-ds-check-duplicates src
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Add `--warn` to report without failing while the existing collisions are being
|
|
96
|
+
worked through, and drop it once the count is zero. `--json` prints the findings
|
|
97
|
+
for a bot to read; `--manifest <path>` checks against an export list other than
|
|
98
|
+
the installed one.
|
|
99
|
+
|
|
11
100
|
## Setup
|
|
12
101
|
|
|
13
102
|
### 1. Import styles
|
|
@@ -24,6 +113,37 @@ Or in your entry TypeScript/JavaScript:
|
|
|
24
113
|
import "@viglet/viglet-design-system/styles";
|
|
25
114
|
```
|
|
26
115
|
|
|
116
|
+
The brand faces are a **separate import**, and one you probably want:
|
|
117
|
+
|
|
118
|
+
```css
|
|
119
|
+
@import "@viglet/viglet-design-system/styles";
|
|
120
|
+
@import "@viglet/viglet-design-system/fonts";
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
They used to be inside `./styles`, where they were 741 KB of its 964 KB —
|
|
124
|
+
Vite's library mode inlines every asset regardless of `assetsInlineLimit`, so
|
|
125
|
+
every subset of Inter and Plus Jakarta Sans was base64 in the CSS, twice over
|
|
126
|
+
because the preset imported them as well. Base64 of an already-compressed woff2
|
|
127
|
+
does not compress again, which is why 2,276 rules gzipped to 594 KB. Splitting
|
|
128
|
+
them takes `./styles` to 31 KB gzipped.
|
|
129
|
+
|
|
130
|
+
`./fonts` is 5 KB of rules pointing at 11 `.woff2` files shipped beside it in
|
|
131
|
+
`dist/fonts/`. Nothing in it resolves through your `node_modules`, and your CDN
|
|
132
|
+
and browser cache the faces apart from the rules — so a change to any rule no
|
|
133
|
+
longer re-downloads every font, and a product already serving Inter can drop
|
|
134
|
+
this copy.
|
|
135
|
+
|
|
136
|
+
**A page fetches about 77 KB of that, not 272 KB.** Each face carries a
|
|
137
|
+
`unicode-range`, so the browser asks only for the subsets your text needs; an
|
|
138
|
+
English or Portuguese page takes `latin` and nothing else, the accented
|
|
139
|
+
characters Portuguese uses being Latin-1 rather than `latin-ext`.
|
|
140
|
+
`size-budget.json` records both numbers, and CI fails if either moves — or if
|
|
141
|
+
the faces stop being subsetted at all.
|
|
142
|
+
|
|
143
|
+
**Upgrading:** add the second line, or the type falls back through `--font-sans`
|
|
144
|
+
to `system-ui`. That is a real look rather than a broken one, but it is not the
|
|
145
|
+
one the catalogue shows.
|
|
146
|
+
|
|
27
147
|
### 2. Initialize i18n
|
|
28
148
|
|
|
29
149
|
```ts
|
|
@@ -69,6 +189,42 @@ function App() {
|
|
|
69
189
|
}
|
|
70
190
|
```
|
|
71
191
|
|
|
192
|
+
`ThemeProvider` is a thin wrapper over [`next-themes`](https://github.com/pacocoursey/next-themes),
|
|
193
|
+
which is a peer dependency. Three consequences worth knowing:
|
|
194
|
+
|
|
195
|
+
- **It renders on a server.** No `localStorage` is read during render, so a
|
|
196
|
+
server-rendered or React Server Components consumer can mount it.
|
|
197
|
+
- **There is one theme source.** This package's `Toaster` reads `next-themes`
|
|
198
|
+
directly, so mounting both used to run two theme systems writing the class
|
|
199
|
+
from two storage keys. It no longer does.
|
|
200
|
+
- **You can skip it.** A consumer that mounts `next-themes`'s own provider gets
|
|
201
|
+
the same result, and `useTheme` from here reads that one — useful when a
|
|
202
|
+
framework already sets the theme up for you.
|
|
203
|
+
|
|
204
|
+
`useTheme()` returns `{ theme, setTheme }`, where `theme` is the *setting*
|
|
205
|
+
(`"light" | "dark" | "system"`) rather than the resolved colour.
|
|
206
|
+
|
|
207
|
+
### React Server Components
|
|
208
|
+
|
|
209
|
+
The published entries carry a `"use client"` directive where they need one, so a
|
|
210
|
+
Next App Router server component can import this package without adding a
|
|
211
|
+
directive of its own:
|
|
212
|
+
|
|
213
|
+
| Entry | |
|
|
214
|
+
|---|---|
|
|
215
|
+
| `.`, `./bento`, `./router`, `./floating-formulas-bg`, `./i18n` | client — they reach React state, context or a browser API |
|
|
216
|
+
| `./assets`, `./vite` | server-renderable — logo data, and a build-time Vite plugin |
|
|
217
|
+
|
|
218
|
+
`./i18n` is the one worth pointing at: it looks pure, and it pulls
|
|
219
|
+
`i18next-browser-languagedetector`. `./assets` staying unmarked is deliberate —
|
|
220
|
+
a server component can read a product logo without a client boundary.
|
|
221
|
+
|
|
222
|
+
**The directive is not the whole story for a Next consumer.** `./router` and
|
|
223
|
+
`./bento` import `react-router-dom` (see the peer note further down), which an
|
|
224
|
+
App Router application does not use. Being marked client makes them *compile*
|
|
225
|
+
under RSC; it does not make them route. Today a Next consumer takes the root
|
|
226
|
+
entry, `./assets`, `./floating-formulas-bg` and the styles.
|
|
227
|
+
|
|
72
228
|
### 4. Setup Axios CSRF protection
|
|
73
229
|
|
|
74
230
|
```ts
|
|
@@ -107,19 +263,40 @@ import {
|
|
|
107
263
|
|
|
108
264
|
```tsx
|
|
109
265
|
import {
|
|
110
|
-
PageHeader,
|
|
111
|
-
SubPageHeader,
|
|
112
|
-
GridList,
|
|
113
266
|
DialogDelete,
|
|
114
|
-
BlankSlate,
|
|
115
267
|
LoadProvider,
|
|
116
|
-
|
|
268
|
+
GradientButtonLink,
|
|
117
269
|
AppFooter,
|
|
118
270
|
LanguageSelect,
|
|
119
271
|
ModeToggle,
|
|
120
272
|
} from "@viglet/viglet-design-system";
|
|
121
273
|
```
|
|
122
274
|
|
|
275
|
+
A page's chrome — its header, its list, its sidebar — comes from the
|
|
276
|
+
[bento layer](#the-bento-layer) rather than from here. Read the next section
|
|
277
|
+
before reaching for `PageHeader`, `GridList` or `InternalSidebar`.
|
|
278
|
+
|
|
279
|
+
### Two eras, and which one a new page should use
|
|
280
|
+
|
|
281
|
+
This package exports two complete page vocabularies. The **console era** is what the consoles ship on today; the **[bento layer](#the-bento-layer)** is the current one, and Turing has cut over to it. Every console-era export is marked `@deprecated` in its own types, so an editor strikes it through and offers the swap.
|
|
282
|
+
|
|
283
|
+
Nothing is being removed. No product has started cutting over, and a removal will get its own roadmap line rather than arriving as a side effect of this notice — so existing pages keep working and need no rush.
|
|
284
|
+
|
|
285
|
+
| Console era | Use instead | |
|
|
286
|
+
|---|---|---|
|
|
287
|
+
| `PageHeader` | `BentoHero` | Same title/subtitle/icon, plus a tone — the chip follows the product accent. |
|
|
288
|
+
| `SubPageHeader` | `BentoHero` | With `BentoBackLink` for the back target and `BentoActionsMenu` for the menu. |
|
|
289
|
+
| `StickyPageHeader` | `useBentoScrollFade` | The scroll state is separated from the chrome, so it also drives `BentoScrollSaveBar`. |
|
|
290
|
+
| `GridList` | `BentoListPage` | `BentoTileGrid` is the mosaic alone, for a page with its own chrome. |
|
|
291
|
+
| `BlankSlate` | `BentoEmptyState` | |
|
|
292
|
+
| `InternalSidebar` | `BentoNavRail` | The rail takes its nav array as a prop instead of importing routes. |
|
|
293
|
+
| `NavMain` | `BentoNavRail` | |
|
|
294
|
+
| `NavUser` | `BentoUserMenu` | Routes and feature flags arrive as props. |
|
|
295
|
+
| `SubPage` | `BentoEntityShell` | Renders through a render prop, so the shell never learns what an entity is. |
|
|
296
|
+
| `Page`, `PageContent` | — | No single replacement, deliberately: the shell is where a product is itself. Compose `BentoNavRail`, `BentoUserMenu` and `BentoCommandPalette`. |
|
|
297
|
+
|
|
298
|
+
`DialogDelete`, `LoadProvider` and `GradientButtonLink` are **not** console-era — the bento layer uses them itself, and they are not deprecated.
|
|
299
|
+
|
|
123
300
|
### Hooks
|
|
124
301
|
|
|
125
302
|
```tsx
|
|
@@ -146,6 +323,27 @@ import {
|
|
|
146
323
|
} from "@viglet/viglet-design-system";
|
|
147
324
|
```
|
|
148
325
|
|
|
326
|
+
`exportToXlsx(data, headers, filename, sheetName?)` takes an optional sheet name; without one the sheet is named after `filename` (it used to be `Logging`, whatever you exported). The header row is written from `headers`, so an export with no rows still arrives with its column titles rather than as an empty file.
|
|
327
|
+
|
|
328
|
+
### Product logos
|
|
329
|
+
|
|
330
|
+
```tsx
|
|
331
|
+
import { productLogos, type ProductId } from "@viglet/viglet-design-system/assets";
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
Their own subpath, not the root barrel. Vite's library mode inlines every asset
|
|
335
|
+
regardless of `assetsInlineLimit`, so anything the root barrel could reach was
|
|
336
|
+
base64 inside the root entry — `productLogos` names all four logos, and one of
|
|
337
|
+
them is 1.24 MB, which put 1.90 MB of PNG in front of every consumer. Nothing
|
|
338
|
+
renders that one: `VigletAppSwitcher` draws the Viglet Cloud entry with an icon.
|
|
339
|
+
Moving the map here left the root entry 56% lighter, and the size gate now
|
|
340
|
+
refuses any single inlined asset over 256 KB.
|
|
341
|
+
|
|
342
|
+
`VigletAppSwitcher` still imports the three logos it draws, so it needs no
|
|
343
|
+
change — and those three are now 256px rather than 1024–2375px, which is nine
|
|
344
|
+
times the 28 pixels the switcher renders them at. A test holds that ceiling,
|
|
345
|
+
because an asset this package can reach is an asset it ships.
|
|
346
|
+
|
|
149
347
|
### Models
|
|
150
348
|
|
|
151
349
|
```tsx
|
|
@@ -164,20 +362,47 @@ Accordion, Avatar, Badge, Breadcrumb, Button, Card, Checkbox, Dialog, Drawer, Dr
|
|
|
164
362
|
|
|
165
363
|
### App Components (23 components)
|
|
166
364
|
|
|
167
|
-
AppFooter, BadgeColorful, BadgeLocale,
|
|
365
|
+
AppFooter, BadgeColorful, BadgeLocale, DialogDelete, GradientButtonLink, LanguageSelect, LoadProvider, ModeToggle, NavSecondary, ThemeProvider
|
|
366
|
+
|
|
367
|
+
Console-era, `@deprecated`, still exported — see [the swap table](#two-eras-and-which-one-a-new-page-should-use): BlankSlate, GridList, InternalSidebar, NavMain, NavUser, Page, PageContent, PageHeader, StickyPageHeader, SubPage, SubPageHeader
|
|
168
368
|
|
|
169
369
|
### Hooks
|
|
170
370
|
|
|
171
371
|
`useIsMobile`, `useDateLocale`, `useGridAdapter`, `useSubPageBreadcrumb`
|
|
172
372
|
|
|
373
|
+
`useGridAdapter(data, config)` tracks each extractor in `config`, not the object holding them, so a `url` builder that closes over a route param or a locale re-maps the rows when it changes. Pass the config inline if you like — keep the extractors themselves stable (a field name, a module-level function, a `useCallback`) and the memo holds.
|
|
374
|
+
|
|
173
375
|
### Contexts
|
|
174
376
|
|
|
175
377
|
`BreadcrumbProvider` / `useBreadcrumb`, `UserProvider` / `useCurrentUser`, `ThemeProvider` / `useTheme`
|
|
176
378
|
|
|
379
|
+
`useCurrentUser()` returns `status` (`"loading" | "ready" | "failed"`) and `error` alongside `user` and `refreshUser`. Read `status` rather than inferring one from an empty `user` — the same empty object means a request that has not settled, a session that expired, and an account with no username. A rejecting `fetchUser` sets `status: "failed"` and is not rethrown.
|
|
380
|
+
|
|
177
381
|
### Design Tokens
|
|
178
382
|
|
|
179
383
|
OKLCH-based color system with light/dark mode, CSS variables for theming, consistent radius scale, chart palette, sidebar theme, animations.
|
|
180
384
|
|
|
385
|
+
**The brand accent is one token, set once.** The tinted icon chip in a page header, the ring around it, an accented label and the solid primary fill all derive from two gradient stops, so a product picks its colour at the root rather than in every component:
|
|
386
|
+
|
|
387
|
+
```css
|
|
388
|
+
:root {
|
|
389
|
+
--vg-accent-from: oklch(70.5% 0.213 47.604);
|
|
390
|
+
--vg-accent-to: oklch(64.6% 0.222 41.116);
|
|
391
|
+
--vg-accent-text: oklch(55.3% 0.195 38.402); /* readable on light */
|
|
392
|
+
--vg-accent-text-dark: oklch(75% 0.183 55.934); /* readable on dark */
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
The tint, the strong tint and the hairline (`--vg-accent-surface`, `--vg-accent-surface-strong`, `--vg-accent-line`) are `color-mix` over `--vg-accent-from`, so they follow automatically; only the readable foreground is stated, because contrast is not a mix away. Use `--vg-accent-fg` in a component — it is already resolved for the current theme, so no `dark:` twin is needed.
|
|
397
|
+
|
|
398
|
+
**Declare them on `:root`, not on a wrapper.** A custom property substitutes its `var()` references where it is *declared*, so the derived tokens above are mixed against the `--vg-accent-from` declared in the preset's `:root`. Re-keying a subtree moves what a utility class mixes on the element — the chip, the solid fill — and leaves the tint, the hairline and the button fill at the root's value. The result looks like a component that half-ignores the theme.
|
|
399
|
+
|
|
400
|
+
Three utility classes cover the common shapes: `vg-accent-chip` (the tinted gradient chip — pair it with Tailwind's `ring-1`), `vg-accent-text` (an accented label or icon), and `vg-accent-solid` (a solid gradient fill).
|
|
401
|
+
|
|
402
|
+
`GradientButton` and `GradientSwitch` follow the accent in their primary variants (`default`, `outline`, `ghost`), so a re-key reaches the buttons too; their `secondary`, `destructive` and `success` variants keep fixed semantic hues, because "destructive" does not change colour with the brand.
|
|
403
|
+
|
|
404
|
+
This is separate from a component's **colour palette**. `SectionCard` (`blue | violet | emerald | amber | rose | cyan`) and `StickySaveBar` (`gray | blue | orange | green`) are keyed by hue — the caller picked that colour deliberately — so re-keying the accent leaves them alone, the same way it leaves the [bento tones](#the-bento-layer) alone.
|
|
405
|
+
|
|
181
406
|
### i18n
|
|
182
407
|
|
|
183
408
|
Base translations (EN/PT) for common UI strings: buttons, form labels, dialog text, navigation, theme.
|
|
@@ -195,6 +420,107 @@ Base translations (EN/PT) for common UI strings: buttons, form labels, dialog te
|
|
|
195
420
|
- Sonner for toast notifications
|
|
196
421
|
- Lucide + Tabler icons
|
|
197
422
|
|
|
423
|
+
## The bento layer
|
|
424
|
+
|
|
425
|
+
Turing grew a second era of chrome — the frosted tile, the airy hero, the
|
|
426
|
+
mosaic — inside one product while this package sat next to it exporting console
|
|
427
|
+
chrome. It lives here now: the components, their stylesheet, their strings and
|
|
428
|
+
their suites. Turing consumes them through one-line re-exports at the paths its
|
|
429
|
+
pages already imported, so a product adopting the layer writes the imports above
|
|
430
|
+
rather than a second copy.
|
|
431
|
+
|
|
432
|
+
What stayed behind is the product's, deliberately: commercial chrome (activation,
|
|
433
|
+
quota, the first-run tour) and navigation data. `BentoListPage` takes a `layout`
|
|
434
|
+
object rather than fetching one, because where a layout is stored is the
|
|
435
|
+
product's business — its API, its cache, its mutation library.
|
|
436
|
+
|
|
437
|
+
It is a separate entry point, so a console still on the first era carries none
|
|
438
|
+
of it:
|
|
439
|
+
|
|
440
|
+
```ts
|
|
441
|
+
import "@viglet/viglet-design-system/bento.css";
|
|
442
|
+
import {
|
|
443
|
+
BentoEntityShell,
|
|
444
|
+
BentoListPage,
|
|
445
|
+
BentoFormHero,
|
|
446
|
+
BentoNavRail,
|
|
447
|
+
BentoCommandPalette,
|
|
448
|
+
} from "@viglet/viglet-design-system/bento";
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
The stylesheet is a separate import from the components, so a consumer taking
|
|
452
|
+
only the layout maths does not pull CSS it never renders. It reads the preset's
|
|
453
|
+
tokens, so import the preset too.
|
|
454
|
+
|
|
455
|
+
"Carries none of it" is measured rather than claimed. `pnpm run build` ends by
|
|
456
|
+
bundling three fixtures through this package's own `exports` map, and fails if a
|
|
457
|
+
bento module, a bento class name or a run of `bento.css`'s selectors reaches a
|
|
458
|
+
consumer that imported only the root entry. `size-budget.json` records what each
|
|
459
|
+
entry costs: today the whole root entry is 87 KB gzipped and `./bento` 22 KB,
|
|
460
|
+
measured with everything the build externalises left out, so the numbers
|
|
461
|
+
describe this package rather than its dependencies. The preset's
|
|
462
|
+
`--vg-bento-tone-*` tokens are deliberately not counted as the layer: they ship
|
|
463
|
+
with every other token and are about a kilobyte of custom properties.
|
|
464
|
+
|
|
465
|
+
The test is whether a root consumer carries the subpath's **code**, not whether
|
|
466
|
+
the subpath exists. `./floating-formulas-bg` has its own entry *and*
|
|
467
|
+
`FloatingFormulasBg` is exported from the root barrel, where `Login` and
|
|
468
|
+
`StartupFirst` render it — so its rules are in `./styles` too, and that is
|
|
469
|
+
correct rather than a leak. The subpath is for a consumer who wants only that
|
|
470
|
+
background.
|
|
471
|
+
|
|
472
|
+
Every subpath in the table above is also **imported, required and type-checked
|
|
473
|
+
as you would use it** on each build: one fixture pulls all fifteen through the
|
|
474
|
+
real `exports` map, a CommonJS probe requires the seven that offer it, and a
|
|
475
|
+
generated TypeScript probe imports a value from each typed entry and uses it —
|
|
476
|
+
so a `types` field resolving to the wrong declarations fails here rather than
|
|
477
|
+
turning into `any` in your editor.
|
|
478
|
+
|
|
479
|
+
That last check found a real one. `"type": "module"` makes Node read any `.js`
|
|
480
|
+
as ESM, and the CommonJS entries were named `<entry>.cjs.js`, so every
|
|
481
|
+
`require()` of this package failed. They are `<entry>.cjs` now. No product met
|
|
482
|
+
it, because every consumer — the Vite ones through their bundler, the Next ones
|
|
483
|
+
through the App Router — takes the `import` condition.
|
|
484
|
+
|
|
485
|
+
**`./bento` requires `react-router-dom`.** The package declares that peer
|
|
486
|
+
optional because the root entry does not need it — only `./router` and `./bento`
|
|
487
|
+
do, and npm cannot mark a peer required for one entry point and optional for
|
|
488
|
+
another. `pnpm run build` fails if any other entry starts importing it, so the
|
|
489
|
+
split above stays true rather than becoming folklore.
|
|
490
|
+
|
|
491
|
+
[docs/BENTO-AUTHORING.md](docs/BENTO-AUTHORING.md) is the contract for writing a
|
|
492
|
+
bento page: the three page shapes, what the package will not hold for you, and
|
|
493
|
+
the colour, i18n, accessibility and layout rules that keep two consoles looking
|
|
494
|
+
like the same product. Read it before the first screen, not after the fifth.
|
|
495
|
+
|
|
496
|
+
[docs/BENTO-BOUNDARY.md](docs/BENTO-BOUNDARY.md) says which exports become part
|
|
497
|
+
of this package and which stay in the product, and why. Four of them are one
|
|
498
|
+
product's commercial offer rendered as cards, and shipping those as chrome would
|
|
499
|
+
put that offer in every console.
|
|
500
|
+
|
|
501
|
+
## Contributing
|
|
502
|
+
|
|
503
|
+
The package manager here is pnpm, matching the Shio, Turing, Dumont, Cloud Home
|
|
504
|
+
and Schools workspaces. The Cloud Console installs with npm, which is a fact
|
|
505
|
+
about that repository and not about this one.
|
|
506
|
+
|
|
507
|
+
```bash
|
|
508
|
+
pnpm install
|
|
509
|
+
pnpm lint # eslint
|
|
510
|
+
pnpm typecheck # tsc -b --force
|
|
511
|
+
pnpm test # vitest
|
|
512
|
+
pnpm build # tsc, vite, and the dist checks
|
|
513
|
+
pnpm storybook # the component catalogue, on :6006
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
CI runs all of those on every push and pull request, and the publish workflow
|
|
517
|
+
re-runs them before it releases.
|
|
518
|
+
|
|
519
|
+
`pnpm build` ends in `scripts/check-dist.mjs`, which fails the build when dist
|
|
520
|
+
would be broken for consumers in a way nothing here can see — a declaration
|
|
521
|
+
importing through a `node_modules` path, a test artefact in the published tree,
|
|
522
|
+
or an `exports` entry the build did not produce.
|
|
523
|
+
|
|
198
524
|
## License
|
|
199
525
|
|
|
200
526
|
Apache-2.0
|
package/dist/assets.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./products-DL_YYXkV.cjs");exports.dumontLogoUrl=e.n,exports.productLogos=e.t,exports.shioLogoUrl=e.r,exports.turingLogoUrl=e.i,exports.vigletLogoUrl=e.a;
|