@vegastack/design 0.1.0 → 0.2.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/bin/check-updates.mjs +706 -108
- package/bin/skills.mjs +262 -0
- package/bin/vegastack-design.mjs +32 -14
- package/bin/verify-registry-item.mjs +775 -214
- package/css/base.css +1 -1
- package/css/theme.css +1 -1
- package/css/utilities.css +1 -1
- package/dist/icons/index.cjs +199 -0
- package/dist/icons/index.d.cts +164 -0
- package/dist/icons/index.d.ts +39 -29
- package/dist/icons/index.js +81 -14
- package/dist/index.cjs +78 -0
- package/dist/index.d.cts +56 -0
- package/dist/index.d.ts +7 -0
- package/dist/preset.cjs +37 -0
- package/dist/preset.d.cts +19 -0
- package/dist/theme-scope.cjs +56 -0
- package/dist/theme-scope.d.cts +23 -0
- package/dist/theme-scope.d.ts +23 -0
- package/dist/theme-scope.js +21 -0
- package/package.json +40 -18
- package/skills/vegastack-brand/SKILL.md +29 -0
- package/skills/vegastack-consume/SKILL.md +182 -0
- package/skills/vegastack-consume/references/registry-integrity.md +132 -0
- package/skills/vegastack-design-audit/SKILL.md +123 -0
- package/skills/vegastack-design-system/SKILL.md +110 -0
- package/skills/vegastack-design-system/references/components.md +151 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Registry integrity — what the three steps actually guarantee
|
|
2
|
+
|
|
3
|
+
The fail-closed add flow in the `vegastack-consume` skill is three commands. This explains what each
|
|
4
|
+
one proves, what it deliberately does not prove, and how to configure it.
|
|
5
|
+
|
|
6
|
+
## Contents
|
|
7
|
+
|
|
8
|
+
- [Why three steps and not one](#why-three-steps-and-not-one)
|
|
9
|
+
- [Step 1 — pre-write verification](#step-1--pre-write-verification)
|
|
10
|
+
- [Step 2 — copy-in](#step-2--copy-in)
|
|
11
|
+
- [Step 3 — post-write verification](#step-3--post-write-verification)
|
|
12
|
+
- [The guarantee, stated precisely](#the-guarantee-stated-precisely)
|
|
13
|
+
- [Limits](#limits)
|
|
14
|
+
- [Configuration](#configuration)
|
|
15
|
+
- [Staying up to date](#staying-up-to-date)
|
|
16
|
+
|
|
17
|
+
## Why three steps and not one
|
|
18
|
+
|
|
19
|
+
`shadcn add` **re-fetches** the item from the registry. A registry that changed between your
|
|
20
|
+
preflight and the copy-in would slip through a single-step check — a time-of-check/time-of-use
|
|
21
|
+
(TOCTOU) gap.
|
|
22
|
+
|
|
23
|
+
Step 1 saves the exact verified bytes. Step 3 proves the files on disk match **those saved bytes**,
|
|
24
|
+
not a fresh fetch. That is what closes the gap.
|
|
25
|
+
|
|
26
|
+
## Step 1 — pre-write verification
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npx --package=@vegastack/design vegastack-design verify --save "$ITEM" button
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Full mode (the default) checks the Sigstore signature via `cosign` **and** the canonical item hash.
|
|
33
|
+
The signature is the real trust boundary: it requires the deployed signed manifest and asserts the
|
|
34
|
+
exact pinned GitHub-OIDC release identity, not merely a valid signature from anyone.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx --package=@vegastack/design vegastack-design verify --hash-only --save "$ITEM" button
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Hash-only mode skips `cosign`. Use it for local development, where `cosign` is unavailable, or before
|
|
41
|
+
the signed manifest is deployed. **It does not prove provenance** — it only proves the item is
|
|
42
|
+
internally consistent.
|
|
43
|
+
|
|
44
|
+
Either mode aborts on mismatch and writes the verified item JSON to `--save`. If `--save` is omitted,
|
|
45
|
+
it creates a private unique temp directory and prints the path; reuse that path in step 3.
|
|
46
|
+
|
|
47
|
+
Retain the verified digest in the parent shell **before** `shadcn` or any dependency code runs:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
EXPECTED="$(node -e 'process.stdout.write(JSON.parse(require("node:fs").readFileSync(process.argv[1],"utf8")).meta.integrity)' "$ITEM")"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Step 3 uses this independently retained value to detect replacement of the saved item itself, not
|
|
54
|
+
just drift in the copied files.
|
|
55
|
+
|
|
56
|
+
## Step 2 — copy-in
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pnpm dlx shadcn@latest add @vegastack/button
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The registry item content carries a provenance header (`// @vegastack <name>@<ver> sha256-…`), but
|
|
63
|
+
the current shadcn CLI **strips leading comments on copy-in**. That is expected and is never a
|
|
64
|
+
finding by itself — update tracking is header-optional.
|
|
65
|
+
|
|
66
|
+
## Step 3 — post-write verification
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npx --package=@vegastack/design vegastack-design verify \
|
|
70
|
+
--post-write --item "$ITEM" --expected-integrity "$EXPECTED" --target-dir .
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Offline, no network. `--target-dir` is your project root, where shadcn wrote the files.
|
|
74
|
+
|
|
75
|
+
It first recomputes the saved item's hash against the independently retained digest, then compares
|
|
76
|
+
the bytes on disk against the item's `content` for every file. Exits 1 with a per-file diff on any
|
|
77
|
+
mismatch.
|
|
78
|
+
|
|
79
|
+
## The guarantee, stated precisely
|
|
80
|
+
|
|
81
|
+
shadcn's contiguous start-of-file comment/whitespace prologue removal is accepted **only** for the
|
|
82
|
+
file types it actually transforms. After that:
|
|
83
|
+
|
|
84
|
+
- every non-import line must match byte-for-byte;
|
|
85
|
+
- an `import` (or `export … from`) line may differ **only** in its module specifier, and **only** when
|
|
86
|
+
that difference exactly matches the registry-source-alias → consumer-alias rewrite declared by your
|
|
87
|
+
`components.json` (resolved using standard TypeScript/JavaScript `paths`).
|
|
88
|
+
|
|
89
|
+
Anything else exits 1: an injected or removed line, an altered non-import line, an import repointed to
|
|
90
|
+
a non-alias specifier, altered import bindings, or a missing file. No executable code can change
|
|
91
|
+
without being caught.
|
|
92
|
+
|
|
93
|
+
## Limits
|
|
94
|
+
|
|
95
|
+
It proves byte-faithfulness _modulo_ the exact transformed-code leading-comment removal and the
|
|
96
|
+
configured alias rewrite. It does **not** evaluate arbitrary build-tool alias plugins, package import
|
|
97
|
+
maps, or extended config files.
|
|
98
|
+
|
|
99
|
+
## Configuration
|
|
100
|
+
|
|
101
|
+
`--help` lists every flag and environment variable: `VEGASTACK_REGISTRY`,
|
|
102
|
+
`VEGASTACK_TRUSTED_REGISTRY_ORIGIN`, the `CF_ACCESS_*` service-token headers, and `VEGASTACK_SIGNER_*`.
|
|
103
|
+
|
|
104
|
+
Credentialed requests must use the exact trusted HTTPS origin (production is the default) and
|
|
105
|
+
redirects are rejected. A custom credentialed registry must set its trust anchor in
|
|
106
|
+
operator-controlled process or CI configuration — **never** in a checkout-local dotenv file.
|
|
107
|
+
|
|
108
|
+
If `@vegastack/design` is a devDependency, wire `verify:registry` (pre-write) and
|
|
109
|
+
`verify:registry:post` (post-write) scripts instead of invoking `npx` each time.
|
|
110
|
+
|
|
111
|
+
## Staying up to date
|
|
112
|
+
|
|
113
|
+
Copy-in means no automatic updates — you re-pull when you want them.
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npx --package=@vegastack/design vegastack-design check-updates # ⬆ update · ≈ drift · ✓ up to date · ? not in registry
|
|
117
|
+
npx --package=@vegastack/design vegastack-design check-updates --fail-on-update # CI drift gate (exit 1 on update or drift)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
A provenance header is used as a fast path when present. For normal headerless shadcn copies, the
|
|
121
|
+
tool maps the exact registry target by filename and compares the complete installed item after the
|
|
122
|
+
real leading-comment and configured-alias transforms.
|
|
123
|
+
|
|
124
|
+
`≈ drift` means the file differs from the registry item — either an upstream update or your own local
|
|
125
|
+
edits. It refuses to attach credentials to any origin other than `VEGASTACK_TRUSTED_REGISTRY_ORIGIN`
|
|
126
|
+
(default `https://design.vegastack.com`) and never follows registry redirects.
|
|
127
|
+
|
|
128
|
+
Per stale component: `shadcn add @vegastack/<name> --diff` to review, then `--overwrite` to apply,
|
|
129
|
+
then re-run the post-write verification above.
|
|
130
|
+
|
|
131
|
+
Status is computed by hash, so a component correctly reads `up to date` when the registry's global
|
|
132
|
+
version bumped but that component's content did not change.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vegastack-design-audit
|
|
3
|
+
description: Read-only audit of an application that consumes the VegaStack design system — finds hardcoded colours and sizes, off-system utility classes, raw HTML where a component exists, accessibility gaps, provider/setup mistakes, and component copies that have drifted from the registry. Reports file:line findings with severity; never edits. Use when asked to audit a project for design-system alignment, check token compliance, or find stale VegaStack components.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Consumer design audit (read-only)
|
|
7
|
+
|
|
8
|
+
**Reports findings; never edits.** Output is a grouped `file:line · rule · fix · severity` list.
|
|
9
|
+
|
|
10
|
+
This audits an application that consumes VegaStack. Scope it to your own UI source — **exclude
|
|
11
|
+
`components/ui/`**, which holds copied-in VegaStack components you do not own. Drift there is a
|
|
12
|
+
separate check (§5), not a styling finding.
|
|
13
|
+
|
|
14
|
+
## 1. Drift and setup first
|
|
15
|
+
|
|
16
|
+
These are mechanical and catch the highest-value problems:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx --package=@vegastack/design vegastack-design check-updates
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`⬆ update` means the registry has a newer version. `≈ drift` means the installed file differs from
|
|
23
|
+
the registry item — either an upstream change or a local edit to a file you do not own. Both are
|
|
24
|
+
findings; a local edit to a copied-in component is a **high** finding, because the next
|
|
25
|
+
`--overwrite` silently destroys it. The fix is to move the customisation into your own wrapper
|
|
26
|
+
component or a token override.
|
|
27
|
+
|
|
28
|
+
Then verify setup, since these failures look like component bugs:
|
|
29
|
+
|
|
30
|
+
- Is `@vegastack/design/theme.css` (or `preset.css`) imported before your own CSS?
|
|
31
|
+
- Does the app root have `isolation: isolate` — either via `base.css` or `className="isolate"`?
|
|
32
|
+
Without it, portaled popups render under page chrome.
|
|
33
|
+
- Is `<VegaStackProvider>` mounted once at the app root, with `suppressHydrationWarning` on `<html>`?
|
|
34
|
+
- Are there two providers, or a provider mounted below a route boundary? Both cause theme and toast
|
|
35
|
+
bugs that present as random.
|
|
36
|
+
|
|
37
|
+
## 2. Hardcoded visual values
|
|
38
|
+
|
|
39
|
+
Every visual value must resolve through a semantic token.
|
|
40
|
+
|
|
41
|
+
**The searches below produce candidates, not findings.** Open every hit before reporting it. A `#`
|
|
42
|
+
match inside a comment, a URL fragment, a CSS id selector, or a string that documents some library's
|
|
43
|
+
default is not a hardcoded colour. A `[…]` arbitrary value is legitimate when it holds a
|
|
44
|
+
`var(--token)`, a `calc()` containing one, a layout primitive (`fr`, `%`, `auto`, `min-content`), or
|
|
45
|
+
a CSS keyword. Reporting a comment as an error costs the owner more trust than the finding is worth.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
rg -n '#[0-9a-fA-F]{3,8}\b' --glob '!components/ui/**' --glob '*.{ts,tsx,css}'
|
|
49
|
+
rg -n '\b(bg|text|border|fill|stroke|ring)-(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-[0-9]{2,3}' --glob '!components/ui/**'
|
|
50
|
+
rg -n '\[[0-9]+(px|rem|em)\]' --glob '!components/ui/**'
|
|
51
|
+
rg -n 'style=\{\{' --glob '!components/ui/**'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- **hardcoded colour** — a hex literal used as a style value. Use a semantic token. **error**
|
|
55
|
+
- **raw palette** — a Tailwind palette class. Use `bg-primary`, `text-muted-foreground`,
|
|
56
|
+
`border-border`, or a status family. **error**
|
|
57
|
+
- **hardcoded dimension** — an arbitrary px/rem value. Use the size, spacing, or radius scale.
|
|
58
|
+
**error**
|
|
59
|
+
- **inline style** — allowed only when every key is a `--*` custom property. Any direct visual
|
|
60
|
+
property is a finding. **error**
|
|
61
|
+
|
|
62
|
+
## 3. Off-system utilities
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
rg -n '\b(rounded-xl|rounded-2xl|rounded-3xl|text-4xl|text-5xl|text-6xl|font-bold|font-semibold|transition-all|transition-colors|z-[0-9]+|opacity-[0-9]+|tracking-[a-z]+|shadow-[a-z]+|blur-[a-z]+)\b' --glob '!components/ui/**'
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- `rounded-xl` and larger do not exist — the scale caps at `rounded-lg`. **error**
|
|
69
|
+
- `text-4xl` and larger are off-scale — use `text-display-sm/md/lg/xl`. **error**
|
|
70
|
+
- `font-bold`/`font-semibold` — the weight ladder is 400/500, owned by the type roles. **error**
|
|
71
|
+
- `transition-all` / `transition-colors` — colour changes are immediate; enumerate the causal
|
|
72
|
+
opacity, transform, or geometry properties. **error**
|
|
73
|
+
- a raw `z-N` — two bands only: `z-(--z-raised)`, `z-(--z-overlay)`. **error**
|
|
74
|
+
- a raw `opacity-NN` — use an `--opacity-*` role (`opacity-0`/`opacity-100` are exempt). **warning**
|
|
75
|
+
- raw `tracking-*`, `shadow-*`, `blur-*` — owned by the type and effect roles. **warning**
|
|
76
|
+
- a raw `/NN` colour-alpha step — use an `--alpha-*` role. Alpha and opacity are different roles and
|
|
77
|
+
are not interchangeable. **warning**
|
|
78
|
+
- `uppercase` on non-mono type, or above 14px. Uppercase is mono-exclusive. **warning**
|
|
79
|
+
|
|
80
|
+
Every `transition*` utility must pair a `duration-*` **and** an `ease-*` token in the same class
|
|
81
|
+
string, or it silently inherits a default curve. **warning**
|
|
82
|
+
|
|
83
|
+
## 4. Component substitution and accessibility
|
|
84
|
+
|
|
85
|
+
- **Raw HTML where a component exists** — a native `<button>`, `<input>`, `<select>`, `<textarea>`,
|
|
86
|
+
or a hand-rolled dialog, dropdown, tooltip, or tab set. Use the VegaStack component; it carries the
|
|
87
|
+
states, keyboard model, and ARIA. **warning**
|
|
88
|
+
- **A second icon library**, or a hand-written inline `<svg>` used as an icon. Only `lucide-react`
|
|
89
|
+
and `Icon`/`BrandIcon` from `@vegastack/design/icons` are sanctioned. **error**
|
|
90
|
+
- **`outline-none` with no replacement focus affordance** anywhere in the file. **error**
|
|
91
|
+
- **Icon-only controls with no accessible name** — a button with no visible text needs `aria-label`
|
|
92
|
+
or `aria-labelledby`. Prefer `IconButton`, which requires it at the type level. **error**
|
|
93
|
+
- **Missing states** — a surface that fetches data needs loading, empty, and error states, not just
|
|
94
|
+
the success path. **warning**
|
|
95
|
+
- **Truncation** — `truncate`/`line-clamp-*` on the same element as `flex`/`inline-flex` silently
|
|
96
|
+
does nothing, because `flex` wins the display conflict. Put `min-w-0` on the flex container and
|
|
97
|
+
`truncate` on an inner span. **warning**
|
|
98
|
+
- **Touch targets** below 24×24 — expand with an invisible hit area
|
|
99
|
+
(`relative` + `before:absolute before:-inset-N`), not a larger visual control. **warning**
|
|
100
|
+
|
|
101
|
+
## 5. Local edits to copied-in components
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
rg -n '@vegastack' components/ui/ -l
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
A copied-in component is yours to keep but not to edit — the next `--overwrite` overwrites it. Any
|
|
108
|
+
diff reported by `check-updates` as `≈ drift` on a file you did not intend to change is a **high**
|
|
109
|
+
finding. Route customisation through a token override, a wrapper component, or a `className` prop.
|
|
110
|
+
|
|
111
|
+
A missing `// @vegastack …` provenance header is **normal** and never a finding on its own: the
|
|
112
|
+
shadcn CLI strips leading comments during copy-in.
|
|
113
|
+
|
|
114
|
+
## 6. Output
|
|
115
|
+
|
|
116
|
+
Group by file. Each finding: `file:line` · rule · suggested fix · severity.
|
|
117
|
+
|
|
118
|
+
- **error** — a hardcoded visual value, an accessibility violation, or an edited copied-in component.
|
|
119
|
+
- **warning** — raw HTML where a component exists, a missing state, an off-system utility with a
|
|
120
|
+
working fallback.
|
|
121
|
+
- **info** — a component with an available update worth a deliberate `--diff` review.
|
|
122
|
+
|
|
123
|
+
Never auto-fix. Report, and let the owner decide.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vegastack-design-system
|
|
3
|
+
description: Build product UI with the VegaStack design system — which component to pick, the semantic token vocabulary, composition patterns for forms and overlays, and the do/don't rules that keep code on-system. Use before generating or editing any UI code in a project that consumes @vegastack/design.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# VegaStack design system
|
|
7
|
+
|
|
8
|
+
Base UI + Tailwind v4 + OKLCH semantic tokens. Components are copy-in via a private shadcn registry;
|
|
9
|
+
the runtime and token layer are public npm.
|
|
10
|
+
|
|
11
|
+
Load this before writing UI code. For first-time project setup (installing packages, wiring the
|
|
12
|
+
provider, configuring registry access), use the `vegastack-consume` skill instead.
|
|
13
|
+
|
|
14
|
+
## Pick a component
|
|
15
|
+
|
|
16
|
+
[references/components.md](references/components.md) is the complete roster, grouped by family, with
|
|
17
|
+
each component's one-line purpose. Read it when choosing between components.
|
|
18
|
+
|
|
19
|
+
You can also query the live registry, which carries `meta.whenToUse` / `meta.whenNotToUse` on every
|
|
20
|
+
item to disambiguate close calls (primary vs. ghost vs. destructive):
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pnpm dlx shadcn@latest list @vegastack
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Rules that decide most component questions:
|
|
27
|
+
|
|
28
|
+
- **Compose `app-shell`** for a sidebar + header + main layout — never hand-roll the landmark trio.
|
|
29
|
+
- **`segmented`** for 2–5 exclusive options inline; **`tabs`** when the choice switches page regions.
|
|
30
|
+
- **`alert` variant=strip** for in-content notices and plan/trial rows; **`announcement-banner`** only
|
|
31
|
+
for the full-width inverse strip at the very top of the page.
|
|
32
|
+
- **`code-block`** for static syntax-highlighted source; **`terminal`** for command sessions.
|
|
33
|
+
- **`navigation-menu`** is top-level site navigation with panels, not a menu inside a page.
|
|
34
|
+
- **Marketing components** (`marketing-surface`, `section-header`, `figure-frame`, `terminal`,
|
|
35
|
+
`logo-row`, `testimonial`, `staggered-text-reveal`, `particle-field`, `pricing-section`, and
|
|
36
|
+
Button's `cta` variant) are scoped to `.vs-marketing` and must never appear in product UI.
|
|
37
|
+
|
|
38
|
+
## Tokens
|
|
39
|
+
|
|
40
|
+
Semantic CSS custom properties from `@vegastack/design-tokens/theme.css` (OKLCH, `:root` + `.dark`).
|
|
41
|
+
Always use the utility, never a raw value.
|
|
42
|
+
|
|
43
|
+
| Role | Utilities |
|
|
44
|
+
| -------- | ------------------------------------------------------------------------------------------------ |
|
|
45
|
+
| Surface | `bg-background` `bg-card` `bg-popover` `bg-muted` `bg-accent` `bg-sidebar-*` |
|
|
46
|
+
| Text | `text-foreground` `text-muted-foreground` `text-{primary,accent,popover}-foreground` |
|
|
47
|
+
| Status | `bg-{destructive,success,warning,info}` + `-subtle` / `-hover` / `-text` / `-foreground` |
|
|
48
|
+
| Border | `border-border` `border-input` — there are no rings; focus is the native outline |
|
|
49
|
+
| Radius | `rounded-{xs,sm,md,lg}` — `lg` is the cap, `xl` does not exist |
|
|
50
|
+
| Type | `text-{xs…3xl}` · `text-h1…h4` · `text-label` · `text-mono-label` · `text-display-{sm,md,lg,xl}` |
|
|
51
|
+
| Font | `font-sans` `font-mono` `font-serif` |
|
|
52
|
+
| Motion | `duration-{fast,base,slow}` paired with `ease-{standard,emphasized,exit,spring}` |
|
|
53
|
+
| Entrance | `motion-pop-in` `motion-enter-up` `motion-shake` |
|
|
54
|
+
|
|
55
|
+
Alpha and opacity are **different roles**: colour compositing takes an `--alpha-*` token
|
|
56
|
+
(`bg-foreground/(--alpha-ink-tint)`), whole-element opacity takes an `--opacity-*` token
|
|
57
|
+
(`opacity-(--opacity-dim)`). A raw `/20` or `opacity-50` is wrong in both cases.
|
|
58
|
+
|
|
59
|
+
`--brand` is a marker-role accent only — never a functional state colour.
|
|
60
|
+
|
|
61
|
+
**Overriding tokens:** redefine one runtime variable in your global CSS and every component repaints
|
|
62
|
+
in both themes:
|
|
63
|
+
|
|
64
|
+
```css
|
|
65
|
+
:root {
|
|
66
|
+
--primary: oklch(0.55 0.2 264);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Never override a `--color-*` variable — that is the build-inlined Tailwind bridge, not the runtime
|
|
71
|
+
contract.
|
|
72
|
+
|
|
73
|
+
## Composition patterns
|
|
74
|
+
|
|
75
|
+
- **Forms** — Base UI `Field` + react-hook-form `Controller` + Zod 4 (`z.email()`). `Field.Control`
|
|
76
|
+
emits `onValueChange`, not a DOM `onChange` event.
|
|
77
|
+
- **Overlays** — enter/exit is driven by `data-starting-style`/`data-ending-style` on the popup root,
|
|
78
|
+
inside a portal + positioner. Theme, toast, tooltip, and direction providers all come from
|
|
79
|
+
`<VegaStackProvider>`; your app root needs `isolation: isolate` or portaled popups can render under
|
|
80
|
+
page chrome.
|
|
81
|
+
- **Compound parts import flat** — `import { DialogTrigger, DialogContent }`. Sub-property access
|
|
82
|
+
(`<Dialog.Trigger>`) only works inside a `'use client'` file, because across the RSC boundary the
|
|
83
|
+
compound is a client-reference proxy and the sub-property is `undefined`.
|
|
84
|
+
- **Polymorphism** uses Base UI's `render` prop, never Radix's `asChild`.
|
|
85
|
+
|
|
86
|
+
## Do / Don't
|
|
87
|
+
|
|
88
|
+
**Do**
|
|
89
|
+
|
|
90
|
+
- Use a semantic token for every visual value.
|
|
91
|
+
- Use `render` for polymorphism and `cn()` from `@vegastack/design` for class merging.
|
|
92
|
+
- Use `Icon`/`BrandIcon` from `@vegastack/design/icons`, or `lucide-react` directly for internal
|
|
93
|
+
chrome.
|
|
94
|
+
- Implement every applicable state: default, hover, focus, loading, empty, error, success, disabled.
|
|
95
|
+
- Put `truncate` on an inner span, with `min-w-0` on the flex container.
|
|
96
|
+
|
|
97
|
+
**Don't**
|
|
98
|
+
|
|
99
|
+
- Hardcode a hex, a px value, or a raw Tailwind palette class (`bg-neutral-900`, `text-red-500`).
|
|
100
|
+
- Use `font-bold`/`font-semibold` — the weight ladder is 400/500, owned by the type roles.
|
|
101
|
+
- Use `rounded-xl`, `text-4xl` or larger, a raw `z-N`, or `transition-all`/`transition-colors`.
|
|
102
|
+
- Set `outline-none` without providing another focus affordance.
|
|
103
|
+
- Pull in a second icon library or hand-write an inline `<svg>` as an icon.
|
|
104
|
+
- Put `uppercase` on non-mono type, or on anything above 14px.
|
|
105
|
+
|
|
106
|
+
## Reference
|
|
107
|
+
|
|
108
|
+
Full component documentation, live previews, prop tables, and accessibility notes:
|
|
109
|
+
<https://design.vegastack.com/docs/components>. Machine-readable summaries for agents are at
|
|
110
|
+
`/llms.txt` and `/llms-full.txt` on the same host.
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Component roster
|
|
2
|
+
|
|
3
|
+
<!-- GENERATED — do not hand-edit. Regenerated from the design system's component contract,
|
|
4
|
+
which is the authority for membership and counts. -->
|
|
5
|
+
|
|
6
|
+
**96 components**, plus 439 animated-icon items, 2 hooks (`use-animation-replay`, `use-mobile`), and 1 starter block (`dashboard-01`) — 538 registry items in total.
|
|
7
|
+
|
|
8
|
+
Install any of them with `shadcn add @vegastack/<name>`. Animated icons install as
|
|
9
|
+
`@vegastack/icon-<name>`; the bare name is reserved for components, so `icon-button` is the
|
|
10
|
+
component and never an icon.
|
|
11
|
+
|
|
12
|
+
## Actions
|
|
13
|
+
|
|
14
|
+
- **`button`** — Trigger an action. 15 variants × 8 sizes, with loading + Base UI Button semantics.
|
|
15
|
+
- **`copy-button`** — Copy a value to the clipboard with transient check feedback — a ghost icon button that swaps Copy → Check and fires onCopied.
|
|
16
|
+
- **`icon-button`** — A square, icon-only action button — a thin Button wrapper that requires an accessible label.
|
|
17
|
+
- **`segmented`** — Segmented control — a single-select, always-one-selected view/mode switcher on a muted track with a raised active chip.
|
|
18
|
+
- **`split-button`** — A primary action joined to a dropdown of related secondary actions — one default click, plus a chevron menu.
|
|
19
|
+
- **`toggle`** — A two-state button that can be pressed on or off — bold/italic, mute, pin.
|
|
20
|
+
- **`toggle-group`** — Joined toggle buttons sharing one selection — single or multiple, variants/sizes, horizontal/vertical, full keyboard navigation.
|
|
21
|
+
|
|
22
|
+
## Form
|
|
23
|
+
|
|
24
|
+
- **`auto-save-input`** — An input that debounces edits and persists them via an async onSave, with an inline idle/saving/saved/error status.
|
|
25
|
+
- **`checkbox`** — A binary (or tri-state) toggle — checked, unchecked, indeterminate, disabled, built on Base UI Checkbox.
|
|
26
|
+
- **`color-picker`** — A swatch-triggered popover presenting a grid of preset colors — pick one, fire onValueChange, mark the selection.
|
|
27
|
+
- **`combobox`** — A filterable, keyboard-navigable listbox behind a text input — type-to-filter, grouped items, async status, and a multi-select chip mode.
|
|
28
|
+
- **`country-select`** — A searchable country combobox returning the ISO 3166-1 alpha-2 code, with flag + name. Built on Combobox.
|
|
29
|
+
- **`date-picker`** — Pick a single date or a date range from a calendar popover — token-styled, keyboard-navigable, with optional quick presets.
|
|
30
|
+
- **`emoji-picker`** — A popover with a searchable, category-grouped grid of emoji that returns the selected character via onSelect (curated set, not full Unicode).
|
|
31
|
+
- **`field`** — A form-field wrapper — label, inline label action, description, and error/success message, built on Base UI Field.
|
|
32
|
+
- **`field-inline`** — Click-to-edit text — displays a value, swaps to a focused input on click, commits on Enter or blur, cancels on Escape.
|
|
33
|
+
- **`input`** — A styled Base UI input — all input types, Field state data attributes, error and disabled states, focus-visible ring, and optional prefix/suffix addons.
|
|
34
|
+
- **`label`** — A styled native label for form controls — htmlFor association, disabled dimming, optional required indicator.
|
|
35
|
+
- **`otp-input`** — A multi-slot one-time-passcode input — keyboard navigation, paste distribution, masking, disabled, built on Base UI OTP Field.
|
|
36
|
+
- **`password-input`** — A password field with a show/hide eye toggle and an optional live requirements checklist.
|
|
37
|
+
- **`radio-group`** — A set of mutually-exclusive options — single selection, arrow-key navigation, disabled, built on Base UI Radio Group.
|
|
38
|
+
- **`region-select`** — A searchable combobox of states/provinces for a country, with a free-text fallback for countries with no subdivisions.
|
|
39
|
+
- **`select`** — A dropdown for choosing one option — trigger with value and chevron, grouped scrollable popup, full keyboard navigation, animated enter/exit.
|
|
40
|
+
- **`slider`** — Pick a number or a [from, to] range from a continuous track — keyboard accessible, with optional steps. Built on Base UI Slider.
|
|
41
|
+
- **`switch`** — An on/off toggle for instant, self-saving binary settings — built on Base UI Switch.
|
|
42
|
+
- **`textarea`** — A styled native textarea for multi-line text — error/disabled states, a focus-visible ring, and an optional auto-grow mode.
|
|
43
|
+
|
|
44
|
+
## Display
|
|
45
|
+
|
|
46
|
+
- **`code-block`** — A code panel with a language header and copy affordance — the shared code surface for chat transcripts, docs, and examples.
|
|
47
|
+
- **`onboarding-checklist`** — A getting-started card — segmented progress + step rows, collapsible to a progress pill.
|
|
48
|
+
- **`stat`** — A labelled value block — muted label over a value, honest faint empty state, optional delta line. Two scales.
|
|
49
|
+
- **`tag-group`** — Hue-tinted label chips on the 10-hue tag palette, with +N overflow collapsing and removable tags.
|
|
50
|
+
|
|
51
|
+
## Data display
|
|
52
|
+
|
|
53
|
+
- **`accordion`** — A stack of collapsible sections — single or multiple open, animated height, a rotating chevron, full keyboard support.
|
|
54
|
+
- **`animated-number`** — A number display that tweens from its previous value to a new one on every change — Intl.NumberFormat-aware (currency/percent/compact), instant under reduced motion, the dashboard stat-card counter.
|
|
55
|
+
- **`avatar`** — A circular user/entity image with an initials fallback, five sizes, and an overlapping AvatarGroup stack.
|
|
56
|
+
- **`badge`** — A compact status or label chip. 3 variants × semantic colors × 4 sizes, with dot, loading, and icon support.
|
|
57
|
+
- **`card`** — A borders-only content surface — no shadows, with composable header, content, and footer parts.
|
|
58
|
+
- **`chart`** — A themed Recharts wrapper — token-only series colors (--chart-1…--chart-8), a bordered tooltip/legend, and Recharts' own built-in keyboard + screen-reader layer.
|
|
59
|
+
- **`collapsible`** — A single toggleable open/close region with an animated height, built on Base UI Collapsible.
|
|
60
|
+
- **`empty`** — A zero-data placeholder — icon, title, description, actions, with intent tints and an optional dashed border.
|
|
61
|
+
- **`item`** — A compact anatomy row for list/feed content — media, title, description, actions, groupable with dividers.
|
|
62
|
+
- **`kbd`** — A styled keyboard-key indicator — OS-aware modifier glyphs, a keys array, and small sizes.
|
|
63
|
+
- **`markdown-view`** — Render a markdown string to safe, token-styled HTML — headings, lists, code, blockquotes, links, GFM tables — XSS-safe, no raw HTML.
|
|
64
|
+
- **`relative-time`** — Render a date as a human-relative string ("2 hours ago", "yesterday") with native Intl.RelativeTimeFormat — self-updating, with an absolute-date tooltip.
|
|
65
|
+
- **`status-icon`** — A small status indicator icon — todo, in progress, blocked, done — each mapping to a lucide icon and semantic color.
|
|
66
|
+
- **`table`** — Styled semantic table primitives — a scrollable container plus header, body, footer, row, head, cell, caption.
|
|
67
|
+
- **`truncated-text`** — Truncate text to one line or N lines with an ellipsis, revealing the full text in a tooltip only when it overflows.
|
|
68
|
+
|
|
69
|
+
## Data
|
|
70
|
+
|
|
71
|
+
- **`data-list`** — A generic, typed data table — configurable columns, row selection, sortable headers, plus loading and empty states.
|
|
72
|
+
- **`filter-bar`** — A row of removable filter chips, an "Add filter" dropdown, and an optional search input — for list and table filter toolbars.
|
|
73
|
+
- **`property-list`** — Record-facts rows: an icon+label column beside a value column, as an accessible definition list.
|
|
74
|
+
|
|
75
|
+
## Overlay
|
|
76
|
+
|
|
77
|
+
- **`alert-dialog`** — A modal confirmation dialog with four semantic intents — non-dismissable, forcing a deliberate Cancel/confirm choice.
|
|
78
|
+
- **`context-menu`** — A menu of actions revealed by right-click (or long-press) — items, submenus, separators, labels, shortcuts, checkbox/radio.
|
|
79
|
+
- **`dialog`** — A modal overlay — five sizes, a header/footer layout, focus trapping, and animated enter/exit.
|
|
80
|
+
- **`dropdown-menu`** — A menu of actions triggered by a button — items, submenus, separators, labels, shortcuts, and checkbox/radio selections.
|
|
81
|
+
- **`hover-card`** — A rich preview panel that opens on hover or focus — interactive content, four directions, forgiving delays.
|
|
82
|
+
- **`popover`** — A click-triggered floating panel for arbitrary content — positioning, an optional arrow, and built-in dismiss.
|
|
83
|
+
- **`sheet`** — A dialog that slides in from a screen edge — four sides, header/footer layout, focus trapping, animated slide.
|
|
84
|
+
- **`tooltip`** — A floating label on hover or focus — smart shared delay, rich content, optional keyboard hints, collision-aware positioning.
|
|
85
|
+
|
|
86
|
+
## Navigation
|
|
87
|
+
|
|
88
|
+
- **`breadcrumb`** — A hierarchical navigation trail — links, separators, the current page, and ellipsis collapse for long paths.
|
|
89
|
+
- **`command`** — A searchable command palette — filtered, grouped items with keyboard navigation, optionally inside a ⌘K dialog.
|
|
90
|
+
- **`navigation-menu`** — Site-nav mega-dropdown on the Base UI NavigationMenu primitive — chip triggers, one shared sliding panel, grid links.
|
|
91
|
+
- **`page-header`** — The standardized header at the top of a page — back button, breadcrumb trail, title, description, actions, secondary menu, and a favorite star.
|
|
92
|
+
- **`pagination`** — Page navigation — previous/next, numbered page links, an ellipsis for long ranges, and the active page.
|
|
93
|
+
- **`sidebar`** — A collapsible app navigation rail — header/content/footer, labelled groups, menu items with active state, and an expand/collapse trigger.
|
|
94
|
+
- **`tabs`** — Layered content sections — line or pill variants, optional icons and count badges, horizontal or vertical, full keyboard navigation.
|
|
95
|
+
|
|
96
|
+
## Feedback
|
|
97
|
+
|
|
98
|
+
- **`alert`** — A status banner — five semantic variants, an optional icon, and an optional dismiss button.
|
|
99
|
+
- **`progress`** — A determinate horizontal progress bar for measurable, ongoing tasks — built on Base UI Progress.
|
|
100
|
+
- **`progress-indicator`** — A compact circular pie-fill progress indicator (0–100%) — a server-safe SVG glyph in circle or squircle shapes.
|
|
101
|
+
- **`provider`** — The single app-root wrapper — theme (next-themes), Sonner toasts, tooltip coordination, and text direction in one mount-once component.
|
|
102
|
+
- **`skeleton`** — A token-driven loading placeholder — line, circle, rect, card shapes, configurable count, reduced-motion-aware pulse.
|
|
103
|
+
- **`sonner`** — Brief, non-blocking notifications — a token-styled Sonner toaster with success/error/warning/info variants that follows the theme.
|
|
104
|
+
- **`spinner`** — An indeterminate loading indicator — a spinning icon inheriting currentColor, four sizes, role=status by default.
|
|
105
|
+
|
|
106
|
+
## Layout
|
|
107
|
+
|
|
108
|
+
- **`app-shell`** — The shared dashboard layout — a skip-linked sidebar + header + scrollable main region, composing Sidebar/SidebarTrigger into one reusable, hash-tracked shell.
|
|
109
|
+
- **`resizable`** — Draggable, keyboard-resizable split panes — horizontal or vertical, nestable, with an optional collapsible panel. Built on react-resizable-panels.
|
|
110
|
+
- **`scroll-area`** — A scroll container with custom, auto-hiding scrollbars — dual-axis, token-styled, built on Base UI ScrollArea.
|
|
111
|
+
- **`separator`** — A thin rule dividing content — horizontal or vertical, decorative by default, built on Base UI.
|
|
112
|
+
- **`settings-row`** — A borders-only settings layout — titled sections, bordered cards, and label-plus-control rows.
|
|
113
|
+
|
|
114
|
+
## Media
|
|
115
|
+
|
|
116
|
+
- **`image`** — A presentational framed image with aspect-ratio, rounding, a loading skeleton, and an error fallback.
|
|
117
|
+
- **`notification-bell`** — A bell icon button with an unread-count badge overlay. Presentational — the app supplies the count.
|
|
118
|
+
|
|
119
|
+
## Rich text
|
|
120
|
+
|
|
121
|
+
- **`text-edit`** — A Tiptap-based rich-text editor with a compact, token-styled toolbar (bold, italic, strike, heading, lists, blockquote, code) — controlled HTML in, HTML out. Collaboration deferred.
|
|
122
|
+
|
|
123
|
+
## Chat
|
|
124
|
+
|
|
125
|
+
- **`tool-call-chip`** — An agent-activity chip — tool action label + muted result meta, optionally rendered as a button.
|
|
126
|
+
|
|
127
|
+
## Communication
|
|
128
|
+
|
|
129
|
+
- **`attachment`** — A file chip / thumbnail card for chat and message-compose surfaces - media slot, name + meta, uploading/error/complete states, remove/download actions.
|
|
130
|
+
- **`bubble`** — A chat speech bubble - 7 token-driven variants (incl. brand-tinted), start/end alignment, interactive content, and a floating reactions chip.
|
|
131
|
+
- **`marker`** — An inline conversation marker - status lines, system notes, and labelled dividers. 3 variants, Base UI render-polymorphic.
|
|
132
|
+
- **`message`** — Layout primitives for a conversation row - avatar anchoring, content column, header/footer slots, start/end alignment. Server-safe.
|
|
133
|
+
- **`message-scroller`** — A virtualised, auto-scrolling conversation viewport - pins to the latest message, preserves position on prepend, tracks the anchor, and a floating scroll-to-end button.
|
|
134
|
+
|
|
135
|
+
## Marketing
|
|
136
|
+
|
|
137
|
+
- **`announcement-banner`** — A dismissible one-line announcement — the full-width inverse page-top band (in-content notices use Alert variant=strip).
|
|
138
|
+
- **`comparison-matrix`** — A plan-feature matrix with accessible ✓/− availability cells and a highlighted plan column.
|
|
139
|
+
- **`figure-frame`** — A sharp-cornered media frame with an optional mono FIG-annotation caption.
|
|
140
|
+
- **`logo-row`** — A muted logo/wordmark strip — alpha-dimmed at rest, restoring on hover for linked items.
|
|
141
|
+
- **`marketing-surface`** — Opts a subtree into the brand's dark warm ground, independent of the page's .dark class.
|
|
142
|
+
- **`particle-field`** — A deterministic, very-low-alpha canvas field of drifting phosphor dots — hero atmosphere only.
|
|
143
|
+
- **`pricing-section`** — Marketing plan cards — mono price display, check feature lists, highlighted-plan treatment.
|
|
144
|
+
- **`ruled-band`** — A hairline-bounded editorial strip with mono-label ends — the changelog/serial-number furniture.
|
|
145
|
+
- **`section-header`** — A marketing section lead-in — mono uppercase eyebrow, display-scale title, optional description.
|
|
146
|
+
- **`terminal`** — A dark mono command block with a phosphor prompt glyph and a composed copy button.
|
|
147
|
+
- **`testimonial`** — A pull-quote — a serif-italic quote over a mono uppercase attribution line.
|
|
148
|
+
|
|
149
|
+
## Marketing motion
|
|
150
|
+
|
|
151
|
+
- **`staggered-text-reveal`** — Display text whose words rise in on mount, staggered one motion-enter-up step apart — CSS-only.
|