@squadbase/vantage 0.5.0 → 0.5.1
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 +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/docs/en/changelog.md +28 -0
- package/docs/en/roadmap.md +199 -0
- package/docs/en/ui-and-theming.md +19 -0
- package/docs/index.json +22 -0
- package/docs/ja/changelog.md +28 -0
- package/docs/ja/roadmap.md +196 -0
- package/docs/ja/ui-and-theming.md +20 -0
- package/package.json +1 -1
- package/skills/vantage-pitfalls/SKILL.md +22 -0
- package/templates/AGENTS.md +15 -0
- package/theme.css +19 -0
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ You write `index.tsx`. Vantage owns routing, React, TanStack Query, Tailwind v4,
|
|
|
7
7
|
the UI kit, the dev server, the optional API server, and the build. There is no
|
|
8
8
|
config file.
|
|
9
9
|
|
|
10
|
-
> **Status: prototype (v0.5.
|
|
10
|
+
> **Status: prototype (v0.5.1).** APIs may still change between releases.
|
|
11
11
|
|
|
12
12
|
## Install
|
|
13
13
|
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime/define-page.ts","../src/index.ts"],"names":[],"mappings":";;;AAyCO,SAAS,WAAW,MAAA,EAAgC;AACzD,EAAA,OAAO,MAAA;AACT;;;AChCO,IAAM,OAAA,GAAU","file":"index.js","sourcesContent":["import type { ComponentType, ReactNode } from \"react\"\n\n/**\n * Optional per-page configuration. The only required part of a page module is\n * its default-exported component; `definePage` covers everything else.\n */\nexport interface PageConfig {\n /** Document title applied when this route is active. */\n title?: string\n /** Description metadata for the page. */\n description?: string\n /**\n * Short label for navigation built from `useRoutes()`. Defaults to `title`,\n * which is often too long for a nav (\"Overview · Acme Analytics\").\n */\n navLabel?: string\n /**\n * Component rendered while the route is loading.\n * (Reserved — not yet applied to Vantage's code-split routes in the prototype.)\n */\n pendingComponent?: ComponentType\n /**\n * Component rendered when the route throws.\n * (Reserved — not yet applied to Vantage's code-split routes in the prototype.)\n */\n errorComponent?: ComponentType<{ error: unknown }>\n /**\n * Validate/transform the URL search params for this route.\n * (Reserved — not yet applied to Vantage's code-split routes in the prototype.)\n */\n validateSearch?: (search: Record<string, unknown>) => Record<string, unknown>\n}\n\n/**\n * Declare optional page configuration.\n *\n * ```tsx\n * export const page = definePage({ title: \"Monthly Analysis\" })\n * export default function MonthlyAnalysis() { return <div/> }\n * ```\n */\nexport function definePage(config: PageConfig): PageConfig {\n return config\n}\n\n/** Convenience type for a Vantage page component. */\nexport type PageComponent = ComponentType & { (): ReactNode }\n","/**\n * `@squadbase/vantage` — public runtime surface.\n *\n * The only import most pages need. Server state lives in\n * `@squadbase/vantage/query`, navigation in `@squadbase/vantage/router`,\n * UI in `@squadbase/vantage/ui`, and API types in `@squadbase/vantage/server`.\n */\nexport { definePage } from \"./runtime/define-page\"\nexport type { PageConfig, PageComponent } from \"./runtime/define-page\"\n\n/** Framework version, kept in sync with package.json at build time. */\nexport const VERSION = \"0.5.
|
|
1
|
+
{"version":3,"sources":["../src/runtime/define-page.ts","../src/index.ts"],"names":[],"mappings":";;;AAyCO,SAAS,WAAW,MAAA,EAAgC;AACzD,EAAA,OAAO,MAAA;AACT;;;AChCO,IAAM,OAAA,GAAU","file":"index.js","sourcesContent":["import type { ComponentType, ReactNode } from \"react\"\n\n/**\n * Optional per-page configuration. The only required part of a page module is\n * its default-exported component; `definePage` covers everything else.\n */\nexport interface PageConfig {\n /** Document title applied when this route is active. */\n title?: string\n /** Description metadata for the page. */\n description?: string\n /**\n * Short label for navigation built from `useRoutes()`. Defaults to `title`,\n * which is often too long for a nav (\"Overview · Acme Analytics\").\n */\n navLabel?: string\n /**\n * Component rendered while the route is loading.\n * (Reserved — not yet applied to Vantage's code-split routes in the prototype.)\n */\n pendingComponent?: ComponentType\n /**\n * Component rendered when the route throws.\n * (Reserved — not yet applied to Vantage's code-split routes in the prototype.)\n */\n errorComponent?: ComponentType<{ error: unknown }>\n /**\n * Validate/transform the URL search params for this route.\n * (Reserved — not yet applied to Vantage's code-split routes in the prototype.)\n */\n validateSearch?: (search: Record<string, unknown>) => Record<string, unknown>\n}\n\n/**\n * Declare optional page configuration.\n *\n * ```tsx\n * export const page = definePage({ title: \"Monthly Analysis\" })\n * export default function MonthlyAnalysis() { return <div/> }\n * ```\n */\nexport function definePage(config: PageConfig): PageConfig {\n return config\n}\n\n/** Convenience type for a Vantage page component. */\nexport type PageComponent = ComponentType & { (): ReactNode }\n","/**\n * `@squadbase/vantage` — public runtime surface.\n *\n * The only import most pages need. Server state lives in\n * `@squadbase/vantage/query`, navigation in `@squadbase/vantage/router`,\n * UI in `@squadbase/vantage/ui`, and API types in `@squadbase/vantage/server`.\n */\nexport { definePage } from \"./runtime/define-page\"\nexport type { PageConfig, PageComponent } from \"./runtime/define-page\"\n\n/** Framework version, kept in sync with package.json at build time. */\nexport const VERSION = \"0.5.1\"\n"]}
|
package/docs/en/changelog.md
CHANGED
|
@@ -9,6 +9,34 @@ What changed in each Vantage release. Newest is on top.
|
|
|
9
9
|
> minor release may include backwards-incompatible changes. A patch is limited to
|
|
10
10
|
> backwards-compatible additions and bug fixes.
|
|
11
11
|
|
|
12
|
+
## v0.5.1
|
|
13
|
+
|
|
14
|
+
Fixes `dark:` utilities not being wired to the same switch as the theme tokens.
|
|
15
|
+
Anything on `^0.5.0` picks this up as-is.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **`dark:` now follows the `.dark` class, not the OS setting.** Tailwind's stock
|
|
20
|
+
`dark:` is `@media (prefers-color-scheme: dark)`, but Vantage's tokens only flip
|
|
21
|
+
when an ancestor carries `.dark` / `[data-theme="dark"]`. **In a browser set to
|
|
22
|
+
OS dark mode** that split the theme in two — background and text tokens stayed
|
|
23
|
+
light while every `dark:` class fired. Text vanished on white cards, badges
|
|
24
|
+
inverted on their own, and so on.
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
// 0.5.0: on an OS-dark browser, this text disappeared against the white card
|
|
28
|
+
<div className="text-slate-900 dark:text-slate-100">{name}</div>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`theme.css` now binds `dark:` to the same class as the tokens. **Unless you add
|
|
32
|
+
`.dark` / `[data-theme="dark"]` yourself, the app always renders light**
|
|
33
|
+
(→ [UI and theming](ui-and-theming)). If your app meant to follow the OS
|
|
34
|
+
setting, set the class on your root element explicitly.
|
|
35
|
+
|
|
36
|
+
- **`color-scheme` is now declared** — browser-owned UI (scrollbars, `<select>`
|
|
37
|
+
popups, autofill) no longer goes dark on an OS-dark machine while the app itself
|
|
38
|
+
stays light.
|
|
39
|
+
|
|
12
40
|
## v0.5.0
|
|
13
41
|
|
|
14
42
|
Browser-to-terminal forwarding now runs on Vite's native mechanism. Which levels
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
> Where Vantage is heading — ideas under consideration for giving agents eyes and memory, plus what we deliberately will not do.
|
|
4
|
+
|
|
5
|
+
Where Vantage is heading. For what already works, see the [changelog](changelog);
|
|
6
|
+
for what you can write today, see the guides.
|
|
7
|
+
|
|
8
|
+
> [!WARNING]
|
|
9
|
+
> Nothing on this page is implemented yet. The order and the contents will change, and
|
|
10
|
+
> some of it will be dropped entirely. **Do not write apps that depend on anything here.**
|
|
11
|
+
|
|
12
|
+
## The premise — who is this framework for?
|
|
13
|
+
|
|
14
|
+
Vantage treats **AI coding agents as first-class citizens**. Being pleasant for humans
|
|
15
|
+
to read matters less than letting an agent **write it without mistakes and verify it on
|
|
16
|
+
its own**. That is why config files are banned, why the framework owns the UI kit and
|
|
17
|
+
the data layer, and why `vantage docs` / `vantage search` live in the CLI —
|
|
18
|
+
**the CLI is the agent's interface, and conventions remove the room for judgment.**
|
|
19
|
+
|
|
20
|
+
Seen from that angle, today's Vantage supports agents well in two places:
|
|
21
|
+
|
|
22
|
+
- **Before writing** — `vantage docs` / `vantage search` / `vantage add skill` / `AGENTS.md`
|
|
23
|
+
- **Verifying statically** — `vantage check` / `vantage routes`
|
|
24
|
+
|
|
25
|
+
And there is one large gap.
|
|
26
|
+
|
|
27
|
+
> **An agent cannot see the screen it just wrote.**
|
|
28
|
+
|
|
29
|
+
Browser-to-terminal forwarding in `vantage dev` (`console.warn` / `console.error` and
|
|
30
|
+
uncaught errors) is the first small window into that gap. Most of the ideas below exist
|
|
31
|
+
to close it.
|
|
32
|
+
|
|
33
|
+
## In design
|
|
34
|
+
|
|
35
|
+
### Element inspector — from the screen to the agent
|
|
36
|
+
|
|
37
|
+
Hover and click an element in the browser, then tell the agent "fix **this**". A staple
|
|
38
|
+
of vibe-coding tools, but here it belongs to the **framework** rather than to each app.
|
|
39
|
+
|
|
40
|
+
Three parts:
|
|
41
|
+
|
|
42
|
+
- **Inject source locations into JSX in development only** —
|
|
43
|
+
`data-vtg="src/sales/index.tsx:42:7"` plus the component name. Vantage owns its UI kit,
|
|
44
|
+
and most of it spreads `{...props}` straight onto the DOM, so an attribute placed on
|
|
45
|
+
something like `<DataTable />` still reaches a real DOM node.
|
|
46
|
+
- **A development-only overlay** that outlines the element, labels it, and emits the selection.
|
|
47
|
+
- **`vantage select`** so the agent picks the selection up from the CLI, with `--json` and
|
|
48
|
+
a `--wait` that blocks until something is selected.
|
|
49
|
+
|
|
50
|
+
Production builds drop both the attributes and the overlay **entirely** — leaving source
|
|
51
|
+
paths in a bundle is a straight information leak.
|
|
52
|
+
|
|
53
|
+
For tools that embed the preview in an iframe, such as Squadbase Editor, the selection is
|
|
54
|
+
also posted over `postMessage`, and the overlay itself can be taken over by the host tool.
|
|
55
|
+
Vantage owns the correctness of the position data and a minimal default UI; the polished
|
|
56
|
+
experience belongs to the tool.
|
|
57
|
+
|
|
58
|
+
## Under consideration — giving agents eyes
|
|
59
|
+
|
|
60
|
+
### `vantage snap` — a structured snapshot of a page
|
|
61
|
+
|
|
62
|
+
Render each route headlessly and return **structured text rather than an image**.
|
|
63
|
+
|
|
64
|
+
```jsonc
|
|
65
|
+
{
|
|
66
|
+
"route": "/sales",
|
|
67
|
+
"state": "ready", // loading | ready | error | empty
|
|
68
|
+
"regions": [
|
|
69
|
+
{ "type": "kpi", "labels": ["Revenue", "MoM"], "values": ["$12.4M", "+8.2%"] },
|
|
70
|
+
{ "type": "chart", "component": "EChart", "series": ["actual", "target"], "points": 12 },
|
|
71
|
+
{ "type": "table", "component": "DataTable", "columns": ["date", "store", "amount"], "rows": 0 }
|
|
72
|
+
],
|
|
73
|
+
"console": [{ "level": "warn", "text": "…" }],
|
|
74
|
+
"network": [{ "url": "/api/sales", "status": 500 }]
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
For an agent this is orders of magnitude more readable than a screenshot. "The table has
|
|
79
|
+
zero rows" and "the API returned 500" are exactly the failures **nobody notices until a
|
|
80
|
+
human pastes a screenshot**.
|
|
81
|
+
|
|
82
|
+
Those `regions` can carry meaning only because Vantage owns the UI kit, the routing, and
|
|
83
|
+
the data layer. A general-purpose browser automation tool cannot produce this granularity,
|
|
84
|
+
which is why we think this is the strongest bet on the list.
|
|
85
|
+
|
|
86
|
+
### `vantage check --runtime` — diagnostics that need a render
|
|
87
|
+
|
|
88
|
+
Today's [diagnostics](cli-reference) only read source. This would put the failures that
|
|
89
|
+
require an actual render behind the same command and the same exit code.
|
|
90
|
+
|
|
91
|
+
- A query stuck pending, so the page never leaves its loading state
|
|
92
|
+
- Fetching succeeded but the table or chart is empty
|
|
93
|
+
- An API returned 4xx / 5xx during the render
|
|
94
|
+
- Unhandled promise rejections
|
|
95
|
+
- An element overflowing its parent
|
|
96
|
+
|
|
97
|
+
The goal is to **close the agent's self-verification loop with an exit code** — one line
|
|
98
|
+
that says: if `vantage check` passes, it is safe to ship.
|
|
99
|
+
|
|
100
|
+
### `vantage dev --agent` — a structured event stream
|
|
101
|
+
|
|
102
|
+
The dev server would emit HMR results, render errors, API responses, and slow queries as
|
|
103
|
+
NDJSON on a separate channel. Human-facing terminal output stays as it is, while an agent
|
|
104
|
+
tails the stream and **learns it broke something the moment it edits**. A natural extension
|
|
105
|
+
of today's console forwarding.
|
|
106
|
+
|
|
107
|
+
## Under consideration — giving agents memory
|
|
108
|
+
|
|
109
|
+
### An `intent` field on `definePage`
|
|
110
|
+
|
|
111
|
+
Let the framework hold **what a page is for** as structure.
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
export const page = definePage({
|
|
115
|
+
title: "Sales dashboard",
|
|
116
|
+
intent: "Spot stores missing their target by looking at daily revenue per store",
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Comments get lost as code is rewritten; this shows up in `vantage routes` and lands in the
|
|
121
|
+
manifest. The readers are "yourself thirty turns from now" and "the next agent to pick this
|
|
122
|
+
up". It is the per-page version of the same idea behind `AGENTS.md` and Agent Skills:
|
|
123
|
+
**the framework decides where memory lives.**
|
|
124
|
+
|
|
125
|
+
### `vantage diff` — diffing the app, not the code
|
|
126
|
+
|
|
127
|
+
```text
|
|
128
|
+
routes + /reports/monthly - /legacy
|
|
129
|
+
api ~ GET /api/sales (POST is gone)
|
|
130
|
+
render /sales table columns 5 → 4 ("owner" disappeared)
|
|
131
|
+
bundle +11.2 MB
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Agents systematically miss the **side effects** of their own edits. This confronts them with
|
|
135
|
+
the difference between the change they intended and the change that happened.
|
|
136
|
+
|
|
137
|
+
### `vantage explain <route|file>`
|
|
138
|
+
|
|
139
|
+
Documentation in reverse, for an agent inheriting an existing app: the route, the components
|
|
140
|
+
in use, the APIs it calls, the environment variables it depends on, and the parent layouts,
|
|
141
|
+
on one screen. An extension of `vantage routes --detail`, aimed at **a granularity that
|
|
142
|
+
replaces reading the source** and cuts context consumption sharply.
|
|
143
|
+
|
|
144
|
+
## Under consideration — preventing the mistake
|
|
145
|
+
|
|
146
|
+
### Turn errors into entry points to the docs
|
|
147
|
+
|
|
148
|
+
Vantage knows its own stack inside out — TanStack Query, Base UI, ECharts, Hono. When it
|
|
149
|
+
forwards a browser error to the terminal, it should be able to **append the next move**.
|
|
150
|
+
|
|
151
|
+
```text
|
|
152
|
+
[console.error] Cannot read properties of undefined (reading 'map')
|
|
153
|
+
> src/sales/index.tsx:42
|
|
154
|
+
↳ data from useApiQuery is undefined on the first render. Use `data?.map`
|
|
155
|
+
or branch on isLoading → vantage docs data-fetching
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Agents stumble hardest at "what should I even search for", so the error itself should pull
|
|
159
|
+
up the documentation.
|
|
160
|
+
|
|
161
|
+
### Absorb common mistakes instead of diagnosing them
|
|
162
|
+
|
|
163
|
+
A generalization of how the UI kit already absorbs Base UI's `Select` quirks. **A diagnostic
|
|
164
|
+
that fires often is a candidate for being made to just work.** We want to treat "how often
|
|
165
|
+
agents get this wrong" as a metric for improving the framework.
|
|
166
|
+
|
|
167
|
+
### `vantage check --budget`
|
|
168
|
+
|
|
169
|
+
Fail the build on bundle-size or first-render regressions. Agents add heavy dependencies
|
|
170
|
+
without hesitation — a single Markdown renderer can add more than 10 MB of output. This turns
|
|
171
|
+
the unease a human would feel into a threshold a machine can read.
|
|
172
|
+
|
|
173
|
+
### Scaffolding from the shape of the data
|
|
174
|
+
|
|
175
|
+
Hand it an API response or a SQL result and get back a page skeleton suited to that shape:
|
|
176
|
+
a line chart for time series, a table plus KPIs for category × value, and so on. Agents redo
|
|
177
|
+
this judgment from scratch every time; the conventional answers belong in the framework.
|
|
178
|
+
|
|
179
|
+
## What we deliberately will not do
|
|
180
|
+
|
|
181
|
+
What is *not* on a roadmap matters just as much, so here is the current position.
|
|
182
|
+
|
|
183
|
+
- **Config files.** There will be no `vantage.config`. When something seems to need
|
|
184
|
+
configuration, we first ask whether a convention or a flag can solve it. Room for judgment
|
|
185
|
+
is a liability for an agent.
|
|
186
|
+
- **A swappable stack.** React, the router, the data layer, and the UI kit are fixed by
|
|
187
|
+
Vantage. The moment swapping is allowed, the docs, the skills, and the diagnostics all have
|
|
188
|
+
to assume they do not know what you are using — and nearly every idea above stops working.
|
|
189
|
+
- **Replacing the `QueryClient` wholesale.** Customization happens per query (see
|
|
190
|
+
[data fetching](data-fetching)).
|
|
191
|
+
- **Becoming a general-purpose application framework.** Vantage is a framework for
|
|
192
|
+
**dashboards**. Rather than broadening the scope, we would rather step on every landmine
|
|
193
|
+
dashboards have to offer.
|
|
194
|
+
|
|
195
|
+
## Feedback
|
|
196
|
+
|
|
197
|
+
We would rather prioritize the list above from real friction. If you hit a spot where the
|
|
198
|
+
agent always gets it wrong, or where you were stuck because something was not discoverable,
|
|
199
|
+
please tell us.
|
|
@@ -78,6 +78,25 @@ and `--sidebar-*` for the sidebar. Changing `--chart-*` also changes
|
|
|
78
78
|
[`EChart`](parts/echart)'s palette — charts build their theme by reading those CSS
|
|
79
79
|
variables directly.
|
|
80
80
|
|
|
81
|
+
## Dark mode is opt-in
|
|
82
|
+
|
|
83
|
+
The dark tokens apply only when an ancestor carries `.dark` or `[data-theme="dark"]`. Vantage
|
|
84
|
+
**does not read the OS/browser setting (`prefers-color-scheme`)** — a dashboard reads better when it
|
|
85
|
+
doesn't flip with whatever it happens to be embedded in, so the switch stays with the app.
|
|
86
|
+
|
|
87
|
+
`dark:` utilities are wired to the same switch (`theme.css` declares it via `@custom-variant dark`).
|
|
88
|
+
Without a `.dark` ancestor no `dark:` utility applies, so the theme can't split in two — light tokens
|
|
89
|
+
under dark-mode utilities.
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
// With no `.dark` ancestor, the second class does nothing
|
|
93
|
+
<div className="text-foreground dark:text-slate-100" />
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
> [!NOTE]
|
|
97
|
+
> Prefer the semantic tokens (`text-foreground`, `text-muted-foreground`, `bg-card`) over the raw
|
|
98
|
+
> Tailwind palette (`text-slate-900`). Written with tokens, you rarely need a `dark:` pair at all.
|
|
99
|
+
|
|
81
100
|
## When you want to edit the source: `vantage add`
|
|
82
101
|
|
|
83
102
|
To make a component's internals your own, copy an editable source into `components/`.
|
package/docs/index.json
CHANGED
|
@@ -123,6 +123,17 @@
|
|
|
123
123
|
"order": 10,
|
|
124
124
|
"searchable": false
|
|
125
125
|
},
|
|
126
|
+
{
|
|
127
|
+
"slug": "roadmap",
|
|
128
|
+
"lang": "ja",
|
|
129
|
+
"section": "guide",
|
|
130
|
+
"sectionTitle": "ガイド",
|
|
131
|
+
"title": "ロードマップ",
|
|
132
|
+
"description": "Vantage がこれから向かう方向。エージェントに「目」と「記憶」を与えるための検討中のアイデアと、意図的にやらないこと。",
|
|
133
|
+
"file": "ja/roadmap.md",
|
|
134
|
+
"order": 11,
|
|
135
|
+
"searchable": false
|
|
136
|
+
},
|
|
126
137
|
{
|
|
127
138
|
"slug": "components",
|
|
128
139
|
"lang": "ja",
|
|
@@ -804,6 +815,17 @@
|
|
|
804
815
|
"order": 10,
|
|
805
816
|
"searchable": false
|
|
806
817
|
},
|
|
818
|
+
{
|
|
819
|
+
"slug": "roadmap",
|
|
820
|
+
"lang": "en",
|
|
821
|
+
"section": "guide",
|
|
822
|
+
"sectionTitle": "Guide",
|
|
823
|
+
"title": "Roadmap",
|
|
824
|
+
"description": "Where Vantage is heading — ideas under consideration for giving agents eyes and memory, plus what we deliberately will not do.",
|
|
825
|
+
"file": "en/roadmap.md",
|
|
826
|
+
"order": 11,
|
|
827
|
+
"searchable": false
|
|
828
|
+
},
|
|
807
829
|
{
|
|
808
830
|
"slug": "components",
|
|
809
831
|
"lang": "en",
|
package/docs/ja/changelog.md
CHANGED
|
@@ -8,6 +8,34 @@ Vantage のリリースごとの変更点です。新しいものが上に来ま
|
|
|
8
8
|
> まだプロトタイプ(**0.x**)です。0.x の間は **minor が実質のメジャー**扱いで、後方互換性の
|
|
9
9
|
> ない変更は minor で入ることがあります。patch は後方互換の機能追加とバグ修正のみです。
|
|
10
10
|
|
|
11
|
+
## v0.5.1
|
|
12
|
+
|
|
13
|
+
`dark:` ユーティリティがテーマトークンと同じスイッチに繋がっていなかった不具合の修正です。
|
|
14
|
+
`^0.5.0` を指定していればそのまま入ります。
|
|
15
|
+
|
|
16
|
+
### 修正
|
|
17
|
+
|
|
18
|
+
- **`dark:` が OS の設定ではなく `.dark` クラスに従うようになりました。** Tailwind の既定の
|
|
19
|
+
`dark:` は `@media (prefers-color-scheme: dark)` ですが、Vantage のトークンは祖先の
|
|
20
|
+
`.dark` / `[data-theme="dark"]` でしか切り替わりません。そのため **OS がダークのブラウザ**では
|
|
21
|
+
テーマが二つに割れていました ― 背景・文字色のトークンはライトのまま、`dark:` の付いた
|
|
22
|
+
クラスだけが全部効いてしまう。白いカードの上で `dark:text-slate-100` の文字が消える、
|
|
23
|
+
バッジだけ黒地に反転する、といった症状が出ます。
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
// 0.5.0: OS がダークだと、白いカードの上でこの文字が見えなくなっていた
|
|
27
|
+
<div className="text-slate-900 dark:text-slate-100">{name}</div>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`theme.css` で `dark:` をトークンと同じクラスに繋ぎ直しました。**`.dark` /
|
|
31
|
+
`[data-theme="dark"]` を自分で付けない限り、アプリは常にライトで描かれます**
|
|
32
|
+
(→ [UI とテーマ](ui-and-theming))。OS の設定に追従させていたつもりのアプリは、
|
|
33
|
+
ルート要素へ明示的にクラスを付けてください。
|
|
34
|
+
|
|
35
|
+
- **`color-scheme` を宣言するようになりました** ― スクロールバー、`<select>` のポップアップ、
|
|
36
|
+
オートフィルといったブラウザ側の UI が、アプリはライトなのに OS 設定でダークになる、という
|
|
37
|
+
ちぐはぐが解消します。
|
|
38
|
+
|
|
11
39
|
## v0.5.0
|
|
12
40
|
|
|
13
41
|
ブラウザから開発ターミナルへの転送を Vite ネイティブの仕組みに置き換えました。転送される
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# ロードマップ
|
|
2
|
+
|
|
3
|
+
> Vantage がこれから向かう方向。エージェントに「目」と「記憶」を与えるための検討中のアイデアと、意図的にやらないこと。
|
|
4
|
+
|
|
5
|
+
Vantage がこれから向かおうとしている方向をまとめたページです。**すでに動くもの**については
|
|
6
|
+
[変更履歴](changelog)を、いま書けることについては各ガイドを参照してください。
|
|
7
|
+
|
|
8
|
+
> [!WARNING]
|
|
9
|
+
> ここに書かれているものは**まだ実装されていません**。順序も内容も変わりますし、途中で丸ごと
|
|
10
|
+
> 取りやめることもあります。**このページの機能を前提にアプリを書かないでください。**
|
|
11
|
+
|
|
12
|
+
## 前提 ― 誰のためのフレームワークか
|
|
13
|
+
|
|
14
|
+
Vantage は **AI コーディングエージェントを一級市民**として設計されています。人間が読みやすいこと
|
|
15
|
+
より、エージェントが**間違えずに書けること・自分で検証できること**を優先します。設定ファイルを
|
|
16
|
+
禁止しているのも、UI キットとデータ層をフレームワークが所有しているのも、`vantage docs` /
|
|
17
|
+
`vantage search` が CLI にあるのも、すべて同じ理由です ―
|
|
18
|
+
**エージェントの窓口は CLI であり、判断の余地は規約で潰す。**
|
|
19
|
+
|
|
20
|
+
この視点で今の Vantage を眺めると、支援が厚いのは 2 箇所です。
|
|
21
|
+
|
|
22
|
+
- **書く前** ― `vantage docs` / `vantage search` / `vantage add skill` / `AGENTS.md`
|
|
23
|
+
- **静的に検証する** ― `vantage check` / `vantage routes`
|
|
24
|
+
|
|
25
|
+
そして、大きな空白が 1 つあります。
|
|
26
|
+
|
|
27
|
+
> **エージェントは、自分が書いた画面を見られない。**
|
|
28
|
+
|
|
29
|
+
`vantage dev` のブラウザ → ターミナル転送(`console.warn` / `console.error` / 未捕捉エラー)は、
|
|
30
|
+
その穴に開いた最初の小さな窓です。以下のアイデアは、ほとんどがこの穴を埋めるためのものです。
|
|
31
|
+
|
|
32
|
+
## 設計中
|
|
33
|
+
|
|
34
|
+
### 要素インスペクタ ― 画面からエージェントへ
|
|
35
|
+
|
|
36
|
+
ブラウザ上の要素をホバー・クリックで選び、「**これ**を直して」とエージェントに渡す仕組み。
|
|
37
|
+
バイブコーディングツールでは定番の体験ですが、これをアプリ側の実装ではなく
|
|
38
|
+
**フレームワークの機能**として持ちます。
|
|
39
|
+
|
|
40
|
+
構成は 3 つです。
|
|
41
|
+
|
|
42
|
+
- **開発時だけ JSX にソース位置を注入する** ― `data-vtg="src/sales/index.tsx:42:7"` と
|
|
43
|
+
コンポーネント名。Vantage は UI キットを自分で所有していて、その大半が `{...props}` を
|
|
44
|
+
そのまま DOM へ渡すため、`<DataTable />` のような要素に付けた属性も実際の DOM まで届きます。
|
|
45
|
+
- **開発時だけのオーバーレイ** ― 要素の輪郭とラベルを描き、選択結果を送出する。
|
|
46
|
+
- **`vantage select`** ― 選択されたものをエージェントが CLI から受け取る。
|
|
47
|
+
`--json` と、選択されるまで待つ `--wait`。
|
|
48
|
+
|
|
49
|
+
本番ビルドでは属性もオーバーレイも**完全に落とします**(ソースパスがバンドルに残るのは
|
|
50
|
+
情報漏洩そのものなので)。
|
|
51
|
+
|
|
52
|
+
Squadbase Editor のようにプレビューを iframe で埋め込むツール向けには、選択結果を
|
|
53
|
+
`postMessage` でも流し、オーバーレイの見た目自体をツール側が乗っ取れるようにする方針です。
|
|
54
|
+
Vantage が持つのは「位置情報の正しさ」と最小限の既定 UI までで、体験の作り込みはツール側に
|
|
55
|
+
譲ります。
|
|
56
|
+
|
|
57
|
+
## 検討中 ― エージェントに「目」を与える
|
|
58
|
+
|
|
59
|
+
### `vantage snap` ― ページの構造化スナップショット
|
|
60
|
+
|
|
61
|
+
各ルートをヘッドレスで描画し、**画像ではなく構造化テキスト**で返すコマンド。
|
|
62
|
+
|
|
63
|
+
```jsonc
|
|
64
|
+
{
|
|
65
|
+
"route": "/sales",
|
|
66
|
+
"state": "ready", // loading | ready | error | empty
|
|
67
|
+
"regions": [
|
|
68
|
+
{ "type": "kpi", "labels": ["今月の売上", "前月比"], "values": ["¥12.4M", "+8.2%"] },
|
|
69
|
+
{ "type": "chart", "component": "EChart", "series": ["売上", "目標"], "points": 12 },
|
|
70
|
+
{ "type": "table", "component": "DataTable", "columns": ["日付", "店舗", "金額"], "rows": 0 }
|
|
71
|
+
],
|
|
72
|
+
"console": [{ "level": "warn", "text": "…" }],
|
|
73
|
+
"network": [{ "url": "/api/sales", "status": 500 }]
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
エージェントにとっては、スクリーンショットの画像よりこの形のほうが桁違いに読めます。
|
|
78
|
+
「表が 0 行」「API が 500 を返している」は、**人間がスクリーンショットを貼るまで誰も気づかない**
|
|
79
|
+
種類の失敗です。
|
|
80
|
+
|
|
81
|
+
`regions` に意味づけができるのは、Vantage が UI キット・ルーティング・データ層をすべて
|
|
82
|
+
所有しているからです。汎用のブラウザ自動化ツールには出せない粒度で、ここが最大の勝ち筋だと
|
|
83
|
+
考えています。
|
|
84
|
+
|
|
85
|
+
### `vantage check --runtime` ― 描画して初めてわかる診断
|
|
86
|
+
|
|
87
|
+
いまの [診断](cli-reference) はソースを読むだけの静的なものです。実際に描画しないと
|
|
88
|
+
分からない失敗を、同じコマンド・同じ終了コードに載せます。
|
|
89
|
+
|
|
90
|
+
- クエリが pending のまま抜けず、ローディング表示から戻らない
|
|
91
|
+
- データ取得は成功しているのに表やチャートが空
|
|
92
|
+
- 描画中に叩いた API が 4xx / 5xx を返した
|
|
93
|
+
- 未処理の Promise リジェクション
|
|
94
|
+
- 要素が親の幅をはみ出している
|
|
95
|
+
|
|
96
|
+
狙いは「**エージェントの自己検証ループが終了コードで閉じる**」ことです。`vantage check` が
|
|
97
|
+
通れば出荷してよい、という一本の線を引きたい。
|
|
98
|
+
|
|
99
|
+
### `vantage dev --agent` ― 構造化イベントストリーム
|
|
100
|
+
|
|
101
|
+
開発サーバーが、HMR の成否・描画エラー・API のレスポンス・遅いクエリを NDJSON で別チャネルへ
|
|
102
|
+
出す案。人間向けのターミナル出力は今のままにして、エージェントは追記を読み続けることで
|
|
103
|
+
**編集した直後に壊れたことを知れる**ようにします。いまのコンソール転送の自然な延長線です。
|
|
104
|
+
|
|
105
|
+
## 検討中 ― エージェントに「記憶」を与える
|
|
106
|
+
|
|
107
|
+
### `definePage` の `intent`
|
|
108
|
+
|
|
109
|
+
そのページが**何のためにあるか**をフレームワークが構造として持つ案。
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
export const page = definePage({
|
|
113
|
+
title: "売上ダッシュボード",
|
|
114
|
+
intent: "店舗別の日次売上を見て、目標未達の店舗を早く見つける",
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
コメントは書き換えの過程で消えますが、これは `vantage routes` に出てマニフェストに載る
|
|
119
|
+
**構造**です。読者は「30 ターン後の自分」や「引き継いだ別のエージェント」。
|
|
120
|
+
`AGENTS.md` や Agent Skills と同じ「**フレームワークが記憶の置き場所を規定する**」という
|
|
121
|
+
考え方の、ページ単位版にあたります。
|
|
122
|
+
|
|
123
|
+
### `vantage diff` ― コードの差分ではなくアプリの差分
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
routes + /reports/monthly - /legacy
|
|
127
|
+
api ~ GET /api/sales (POST が消えた)
|
|
128
|
+
render /sales 表の列 5 → 4 ("担当者" が消えた)
|
|
129
|
+
bundle +11.2 MB
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
エージェントは自分の変更の**副作用**を系統的に見落とします。「意図した変更」と「実際に起きた
|
|
133
|
+
変更」の差を突きつけるためのコマンドです。
|
|
134
|
+
|
|
135
|
+
### `vantage explain <route|file>`
|
|
136
|
+
|
|
137
|
+
既存のアプリを引き継いだエージェント向けの、逆向きのドキュメント。そのページのルート・使って
|
|
138
|
+
いるコンポーネント・叩いている API・依存している環境変数・親レイアウトを 1 画面にまとめます。
|
|
139
|
+
`vantage routes --detail` の延長ですが、狙いは「**ソースを読む代わりになる粒度**」で、
|
|
140
|
+
コンテキストの消費を大きく減らすことです。
|
|
141
|
+
|
|
142
|
+
## 検討中 ― そもそも間違えさせない
|
|
143
|
+
|
|
144
|
+
### エラーをドキュメントへの入口にする
|
|
145
|
+
|
|
146
|
+
Vantage は自分のスタック(TanStack Query・Base UI・ECharts・Hono)を全部知っています。
|
|
147
|
+
ブラウザのエラーをターミナルへ転送するときに、**次の一手を添える**ことができるはずです。
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
[console.error] Cannot read properties of undefined (reading 'map')
|
|
151
|
+
> src/sales/index.tsx:42
|
|
152
|
+
↳ useApiQuery の data は初回 undefined です。`data?.map` にするか
|
|
153
|
+
isLoading で分岐してください → vantage docs data-fetching
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
エージェントが最もつまずくのは「何を検索すればいいか分からない」場面なので、
|
|
157
|
+
**エラーが自動的にドキュメントを引く**形にします。
|
|
158
|
+
|
|
159
|
+
### 「よく間違える」を診断ではなく吸収で潰す
|
|
160
|
+
|
|
161
|
+
Base UI の `Select` の癖を UI キット側で吸収しているのと同じ方針の一般化です。
|
|
162
|
+
**診断が頻繁に鳴るパターンは、診断ではなく「そのまま書いても動く」ようにする候補**と考えます。
|
|
163
|
+
エージェントが間違えた回数そのものを、フレームワークの改善指標として扱いたい。
|
|
164
|
+
|
|
165
|
+
### `vantage check --budget`
|
|
166
|
+
|
|
167
|
+
バンドルサイズや初期描画の回帰でビルドを止める案。エージェントは重い依存を平気で追加します
|
|
168
|
+
(Markdown レンダラを 1 つ足しただけで出力が 10 MB 以上増えることがあります)。人間なら気づく
|
|
169
|
+
違和感を、機械が読める閾値に落とします。
|
|
170
|
+
|
|
171
|
+
### データの形から骨格を作る
|
|
172
|
+
|
|
173
|
+
API のレスポンスや SQL の結果を渡すと、その形に合った可視化の骨格を出す案
|
|
174
|
+
(時系列なら折れ線、カテゴリ × 数値なら表と KPI、など)。エージェントは毎回この判断を
|
|
175
|
+
ゼロからやり直しているので、定石はフレームワークが持つべきだと考えています。
|
|
176
|
+
|
|
177
|
+
## 意図的にやらないこと
|
|
178
|
+
|
|
179
|
+
ロードマップに載らないことも同じくらい重要なので、現時点の方針を書いておきます。
|
|
180
|
+
|
|
181
|
+
- **設定ファイルの導入** ― `vantage.config` は作りません。設定を足したくなったら、それは
|
|
182
|
+
規約かフラグで解けないかをまず疑います。判断の余地はエージェントにとって負債です。
|
|
183
|
+
- **スタックの差し替えを可能にすること** ― React・ルーター・データ層・UI キットは
|
|
184
|
+
Vantage が固定します。差し替えを許した瞬間、ドキュメントも Skill も診断も「相手が何を
|
|
185
|
+
使っているか分からない」前提になり、上に挙げたアイデアはほぼ全部成立しなくなります。
|
|
186
|
+
- **`QueryClient` の丸ごと差し替え** ― カスタマイズの手段はクエリ単位の上書きです
|
|
187
|
+
([データ取得](data-fetching)を参照)。
|
|
188
|
+
- **汎用のアプリケーションフレームワーク化** ― Vantage は**ダッシュボード**のための
|
|
189
|
+
フレームワークです。用途を広げるより、ダッシュボードで踏む地雷を全部踏み抜いておくことに
|
|
190
|
+
投資します。
|
|
191
|
+
|
|
192
|
+
## フィードバック
|
|
193
|
+
|
|
194
|
+
上のアイデアの優先順位は、実際に詰まった場所で決めたいと考えています。使っていて
|
|
195
|
+
「エージェントがここで必ず間違える」「これが分からず手が止まった」という箇所があれば、
|
|
196
|
+
ぜひ教えてください。
|
|
@@ -78,6 +78,26 @@ import { cn } from "@squadbase/vantage/ui";
|
|
|
78
78
|
[`EChart`](parts/echart) の配色も一緒に変わります。チャートは CSS 変数を実際に読み取って
|
|
79
79
|
テーマを組み立てるためです。
|
|
80
80
|
|
|
81
|
+
## ダークモードは opt-in
|
|
82
|
+
|
|
83
|
+
ダークのトークンが効くのは、祖先に `.dark` か `[data-theme="dark"]` が付いているときだけです。
|
|
84
|
+
**OS やブラウザの設定(`prefers-color-scheme`)は見ません** ― ダッシュボードは埋め込み先の
|
|
85
|
+
明暗に勝手に追従しないほうが読めるため、切り替えはアプリ側の明示的な指定に任せています。
|
|
86
|
+
|
|
87
|
+
`dark:` ユーティリティも同じスイッチに繋がっています(`theme.css` が
|
|
88
|
+
`@custom-variant dark` でそう定義しています)。`.dark` が無ければ `dark:` は一切効かないので、
|
|
89
|
+
トークンだけライトで `dark:` だけダーク、という食い違いは起きません。
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
// `.dark` が付いていなければ、下段のクラスは効かない
|
|
93
|
+
<div className="text-foreground dark:text-slate-100" />
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
> [!NOTE]
|
|
97
|
+
> 色は素の Tailwind パレット(`text-slate-900` など)ではなく、
|
|
98
|
+
> セマンティックトークン(`text-foreground` / `text-muted-foreground` / `bg-card`)で書くのが
|
|
99
|
+
> おすすめです。トークンで書けば `dark:` を並べる必要がそもそも無くなります。
|
|
100
|
+
|
|
81
101
|
## ソースを編集したいとき: `vantage add`
|
|
82
102
|
|
|
83
103
|
コンポーネントの中身を自分のものにしたいときは、編集可能なソースを `components/` にコピーします。
|
package/package.json
CHANGED
|
@@ -35,6 +35,28 @@ Base UI の `SelectValue` は選択中の **value をそのまま描き**、`Sel
|
|
|
35
35
|
|
|
36
36
|
トリガーに `kanto` や `/sales` と生の値が出たら、まずこれを疑う。
|
|
37
37
|
|
|
38
|
+
## 配色:素のパレット + `dark:` ではなく、セマンティックトークンで書く
|
|
39
|
+
|
|
40
|
+
色は `text-foreground` / `text-muted-foreground` / `bg-card` / `border-border` などの
|
|
41
|
+
トークンで書く。トークンはライト / ダークの両方を持っているので、`dark:` を並べる必要が無い。
|
|
42
|
+
|
|
43
|
+
`text-slate-900 dark:text-slate-100` のような素の Tailwind パレット + `dark:` の組は、
|
|
44
|
+
**トークンで塗られた周囲と食い違う**。ダークトークンが効くのは祖先に `.dark` /
|
|
45
|
+
`[data-theme="dark"]` が付いているときだけで、`dark:` ユーティリティも同じスイッチに
|
|
46
|
+
繋がっている(`theme.css` の `@custom-variant dark`)。つまり自分でクラスを付けない限り
|
|
47
|
+
アプリは常にライトで動くのに、素のパレットを使うとその 1 か所だけ手動で両モードを
|
|
48
|
+
管理することになる。
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
// ✗ 手動で 2 モードを管理することになる
|
|
52
|
+
<div className="font-medium text-slate-900 dark:text-slate-100">{name}</div>
|
|
53
|
+
// ✓ トークンなら 1 つで済む
|
|
54
|
+
<div className="font-medium text-foreground">{name}</div>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`--muted` / `--accent` / `--secondary` / `--border` は**背景・境界用**で、ライトではほぼ白。
|
|
58
|
+
文字色に使うと読めなくなる ― 弱い文字色は `text-muted-foreground`。
|
|
59
|
+
|
|
38
60
|
## チャート:`EChart` の配色はトークン追従。上書きは `option.color`
|
|
39
61
|
|
|
40
62
|
系列色は `--chart-1..5`、軸・凡例・ツールチップは文字色/境界色のトークンから組まれる
|
package/templates/AGENTS.md
CHANGED
|
@@ -36,6 +36,11 @@ UI キット・開発サーバー・API サーバー・ビルドはすべて Van
|
|
|
36
36
|
- **クライアントに届く env は `PUBLIC_` 接頭辞のものだけ。** `import.meta.env.PUBLIC_FOO`。
|
|
37
37
|
それ以外を `import.meta.env` で読むと `PUBLIC_ENV_MISUSE` 警告。シークレットは
|
|
38
38
|
`ApiContext.env`(server/ 内)にだけ届く。
|
|
39
|
+
- **色はセマンティックトークンで書く。** `text-foreground`・`text-muted-foreground`・`bg-card`・
|
|
40
|
+
`border-border`。トークンがライト / ダークの両方を持つので `dark:` を並べる必要が無い。
|
|
41
|
+
素のパレット + `dark:`(`text-slate-900 dark:text-slate-100`)を混ぜると、その 1 か所だけ
|
|
42
|
+
手動で 2 モードを管理することになる(→「ダークモードは opt-in」)。`--muted`・`--accent`・
|
|
43
|
+
`--secondary`・`--border` は背景・境界用で、文字色に使うと読めない。
|
|
39
44
|
- **`.vantage/` と `dist/` は生成物。** 編集しない・読みにいかない(gitignore 済み)。任意の CLI
|
|
40
45
|
コマンド、または `vantage upgrade` で再生成される。
|
|
41
46
|
- **`definePage` の値はリテラルで書く。** title/description/navLabel はビルド時に静的抽出される
|
|
@@ -318,6 +323,16 @@ const save = useApiMutation<Customer, Payload>("/api/customers", { method: "POST
|
|
|
318
323
|
`ui: data-table` と `block: sales-overview` の 2 つだけ。それ以外の名前は import 専用で
|
|
319
324
|
`add` の対象ではない(未知名で実行すると候補が一覧表示される)。
|
|
320
325
|
|
|
326
|
+
### ダークモードは opt-in
|
|
327
|
+
|
|
328
|
+
ダークのトークンが効くのは、祖先に `.dark` か `[data-theme="dark"]` が付いているときだけ。
|
|
329
|
+
**OS / ブラウザの設定(`prefers-color-scheme`)は見ない。** `dark:` ユーティリティも同じ
|
|
330
|
+
スイッチに繋いであるので(`theme.css` の `@custom-variant dark`)、自分でクラスを付けない限り
|
|
331
|
+
アプリは常にライトで描かれる ― `dark:` を書いてもそこだけダークになることはない。
|
|
332
|
+
|
|
333
|
+
明暗を切り替えたいときは、レイアウトのルート要素などに `.dark` / `data-theme="dark"` を
|
|
334
|
+
自分で付ける。
|
|
335
|
+
|
|
321
336
|
## ドキュメントを引く(`vantage docs` / `vantage search`)
|
|
322
337
|
|
|
323
338
|
```bash
|
package/theme.css
CHANGED
|
@@ -12,6 +12,12 @@
|
|
|
12
12
|
on top — charts need distinguishable colours, not a greyscale ramp. */
|
|
13
13
|
|
|
14
14
|
:root {
|
|
15
|
+
/* Native UI (scrollbars, form control popups, autofill) follows the OS unless
|
|
16
|
+
told otherwise. The tokens below don't, so pin it to the same switch —
|
|
17
|
+
otherwise a light app in an OS-dark browser gets dark scrollbars and a dark
|
|
18
|
+
`<select>` popup. */
|
|
19
|
+
color-scheme: light;
|
|
20
|
+
|
|
15
21
|
--background: oklch(1 0 0);
|
|
16
22
|
--foreground: oklch(0.145 0 0);
|
|
17
23
|
--card: oklch(1 0 0);
|
|
@@ -51,6 +57,8 @@
|
|
|
51
57
|
|
|
52
58
|
.dark,
|
|
53
59
|
[data-theme="dark"] {
|
|
60
|
+
color-scheme: dark;
|
|
61
|
+
|
|
54
62
|
--background: oklch(0.145 0 0);
|
|
55
63
|
--foreground: oklch(0.985 0 0);
|
|
56
64
|
--card: oklch(0.205 0 0);
|
|
@@ -145,6 +153,17 @@
|
|
|
145
153
|
}
|
|
146
154
|
|
|
147
155
|
/* ------------------------------------------------------- custom variants */
|
|
156
|
+
|
|
157
|
+
/* `dark:` must follow the same switch as the tokens above — the class, not the
|
|
158
|
+
OS setting. Tailwind v4's stock `dark` variant is `@media (prefers-color-scheme:
|
|
159
|
+
dark)`, so leaving it alone splits the theme in two: a browser in OS dark mode
|
|
160
|
+
activates every `dark:` utility while `--background`/`--foreground` stay light,
|
|
161
|
+
because no `.dark` class is present. The result is light-on-light — `dark:text-
|
|
162
|
+
slate-100` over a white card is invisible — and it hits Vantage's own kit too
|
|
163
|
+
(`dark:data-active:bg-input/30` and friends). `:is()` keeps the specificity
|
|
164
|
+
above the unprefixed utility, so `dark:` still wins when the class is set. */
|
|
165
|
+
@custom-variant dark (&:is(.dark, .dark *, [data-theme="dark"], [data-theme="dark"] *));
|
|
166
|
+
|
|
148
167
|
/* Base UI reports state through `data-open`, `data-checked`, … rather than
|
|
149
168
|
Radix's `data-state="open"`. These variants accept both spellings so the
|
|
150
169
|
component classes read the same either way. */
|