@box-kite/react 2.0.1 → 2.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/.claude/rules/box-kite-rules.md +24 -2
- package/.claude/skills/box-kite/SKILL.md +27 -5
- package/.claude/skills/box-kite/references/components.md +8 -3
- package/.claude/skills/box-kite/references/patterns.md +24 -1
- package/.claude/skills/box-kite/references/styling.md +23 -0
- package/.cursor/rules/box-kite.mdc +25 -3
- package/AGENTS.md +28 -3
- package/BOX_AI_CONTEXT.md +732 -12
- package/BOX_KITE_AI_CONTEXT.md +732 -12
- package/README.md +41 -9
- package/box.cjs +1 -1
- package/box.d.ts +13 -2
- package/box.mjs +25 -18
- package/catalog.cjs +1 -0
- package/catalog.d.ts +8 -0
- package/catalog.mjs +2347 -0
- package/client.cjs +1 -1
- package/client.mjs +59 -53
- package/components/agent.cjs +1 -0
- package/components/agent.d.ts +215 -0
- package/components/agent.mjs +405 -0
- package/components/button.cjs +1 -1
- package/components/button.mjs +10 -14
- package/components/chart.d.ts +1 -0
- package/components/dashboard.cjs +1 -0
- package/components/dashboard.d.ts +121 -0
- package/components/dashboard.mjs +690 -0
- package/components/dataGrid/components/dataGridBody.d.ts +2 -1
- package/components/dataGrid/components/dataGridDetailRow.d.ts +13 -2
- package/components/dataGrid/components/dataGridGroupRow.d.ts +13 -2
- package/components/dataGrid/components/dataGridRow.d.ts +13 -2
- package/components/dataGrid/contracts/dataGridContract.d.ts +66 -2
- package/components/dataGrid/models/cellModel.d.ts +3 -0
- package/components/dataGrid/models/editModel.d.ts +27 -0
- package/components/dataGrid/models/exportModel.d.ts +2 -1
- package/components/dataGrid/models/gridModel.d.ts +3 -0
- package/components/dataGrid/models/rangeModel.d.ts +119 -0
- package/components/dataGrid/models/viewportModel.d.ts +23 -2
- package/components/dataGrid/useGridNavigation.d.ts +10 -2
- package/components/dataGrid.cjs +4 -1
- package/components/dataGrid.d.ts +3 -0
- package/components/dataGrid.mjs +1056 -765
- package/components/flex.cjs +1 -1
- package/components/flex.mjs +10 -13
- package/components/form.cjs +1 -1
- package/components/form.mjs +7 -7
- package/components/grid.cjs +1 -1
- package/components/grid.mjs +10 -13
- package/components/markdown.cjs +1 -0
- package/components/markdown.d.ts +55 -0
- package/components/markdown.mjs +179 -0
- package/components/menu.cjs +1 -1
- package/components/menu.mjs +16 -16
- package/components/overlay.cjs +1 -1
- package/components/overlay.mjs +35 -34
- package/components/popover.cjs +1 -1
- package/components/popover.mjs +4 -4
- package/components/semantics.cjs +1 -1
- package/components/semantics.d.ts +29 -29
- package/components/semantics.mjs +9 -13
- package/components/skeleton.cjs +1 -0
- package/components/skeleton.d.ts +34 -0
- package/components/skeleton.mjs +25 -0
- package/components/svg.cjs +1 -1
- package/components/svg.mjs +38 -44
- package/components/textarea.cjs +1 -1
- package/components/textarea.mjs +12 -16
- package/components/textbox.cjs +1 -1
- package/components/textbox.mjs +12 -16
- package/components/toaster.cjs +1 -1
- package/components/toaster.mjs +42 -43
- package/components/visuallyHidden.cjs +1 -1
- package/components/visuallyHidden.mjs +10 -13
- package/dashboardSchema.cjs +1 -0
- package/dashboardSchema.mjs +78 -0
- package/docs/a11y.md +2 -3
- package/docs/catalog.md +451 -0
- package/docs/components.md +4 -0
- package/docs/index.md +3 -0
- package/docs/interop.md +237 -0
- package/docs/mcp.md +70 -0
- package/docs/props.md +135 -23
- package/interop.cjs +1 -0
- package/interop.d.ts +51 -0
- package/interop.mjs +454 -0
- package/layer.cjs +1 -1
- package/layer.mjs +61 -59
- package/mcp/src/data.d.ts +88 -0
- package/mcp/src/data.test.d.ts +1 -0
- package/mcp/src/engine.d.ts +23 -0
- package/mcp/src/index.d.ts +1 -0
- package/mcp/src/search.d.ts +26 -0
- package/mcp/src/search.test.d.ts +1 -0
- package/mcp/src/server.d.ts +18 -0
- package/mcp/src/server.test.d.ts +1 -0
- package/mcp/src/styles.d.ts +27 -0
- package/mcp/src/styles.test.d.ts +1 -0
- package/mcp/src/tools.d.ts +18 -0
- package/mcp/src/vocabulary.d.ts +41 -0
- package/package.json +170 -37
- package/react/boxComponent.d.ts +10 -0
- package/react/popover/useTopLayer.d.ts +17 -0
- package/react/spec/renderSpec.d.ts +51 -0
- package/react/spec/specBoundary.d.ts +25 -0
- package/react/spec/specRegistry.d.ts +42 -0
- package/react/spec/specRenderer.d.ts +10 -0
- package/react/theme/theme.d.ts +10 -0
- package/react/useStyles.d.ts +2 -0
- package/react-shared.cjs +1 -1
- package/react-shared.mjs +44 -37
- package/registry/blocks/dashboard-shell/dashboard-shell.d.ts +22 -0
- package/registry/blocks/dashboard-shell/dashboard-stats.d.ts +13 -0
- package/registry/blocks/data-grid/invoice-rows.d.ts +15 -0
- package/registry/blocks/data-grid/invoices-grid.d.ts +1 -0
- package/registry/blocks/settings-form/settings-form.d.ts +17 -0
- package/rsc.cjs +1 -1
- package/rsc.d.ts +11 -1
- package/rsc.mjs +15 -12
- package/spec.cjs +2 -0
- package/spec.d.ts +12 -0
- package/spec.mjs +382 -0
- package/specData.cjs +1 -0
- package/specData.mjs +69 -0
- package/specDefs.cjs +1 -0
- package/specDefs.mjs +33 -0
- package/specSchema.cjs +1 -0
- package/specSchema.mjs +88 -0
- package/ssg.cjs +1 -1
- package/ssg.d.ts +8 -2
- package/ssg.mjs +13 -9
- package/utils/agent/agentUtils.d.ts +81 -0
- package/utils/catalog/catalogContracts.d.ts +19 -0
- package/utils/catalog/catalogManifest.d.ts +8 -0
- package/utils/dashboard/dashboardSchema.d.ts +18 -0
- package/utils/dashboard/dashboardUtils.d.ts +97 -0
- package/utils/environment/environmentUtils.d.ts +5 -0
- package/utils/interop/a2uiInterop.d.ts +82 -0
- package/utils/interop/assistantUiInterop.d.ts +34 -0
- package/utils/interop/toolInterop.d.ts +30 -0
- package/utils/spec/specData.d.ts +19 -0
- package/utils/spec/specDefs.d.ts +11 -0
- package/utils/spec/specProps.d.ts +15 -0
- package/utils/spec/specSchema.d.ts +23 -0
- package/utils/spec/specTypes.d.ts +71 -0
- package/utils/spec/specValidate.d.ts +10 -0
package/docs/interop.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Ecosystem interop
|
|
2
|
+
|
|
3
|
+
`@box-kite/react/interop` is this library's shapes and four other runtimes' shapes, mapped onto each
|
|
4
|
+
other. It is framework-free, carries no engine, and depends on none of them — an adapter that imported a
|
|
5
|
+
runtime would be choosing it for the app, and the app has already chosen.
|
|
6
|
+
|
|
7
|
+
There are two things every agentic runtime describes, in words of its own:
|
|
8
|
+
|
|
9
|
+
- **A tool call.** Where it is, what it was given, what it answered, and whether it is waiting on a
|
|
10
|
+
person. `<ToolCallCard>` and `<ApprovalCard>` (`components/agent`) draw the two halves of it.
|
|
11
|
+
- **A tree of components.** A name resolved against an allow-list the app owns, JSON props, children.
|
|
12
|
+
`catalog()` says what may be in it and `<SpecRenderer>` renders it.
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { toolPart, a2uiApplyAll, a2uiSurface, a2uiToSpec, a2uiCatalog } from '@box-kite/react/interop';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## The tool state, in one vocabulary
|
|
19
|
+
|
|
20
|
+
`toolPart(part)` reads a part from AI SDK, assistant-ui or CopilotKit and answers in this library's
|
|
21
|
+
words: `{ kind, status, decision, input, output, error }`, where `kind` is `'call'` or `'approval'` and
|
|
22
|
+
`status` is the `pending`/`running`/`success`/`error` a `<ToolCallCard>` takes.
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { toolPart } from '@box-kite/react/interop';
|
|
26
|
+
import { ToolCallCard, ApprovalCard } from '@box-kite/react/components/agent';
|
|
27
|
+
|
|
28
|
+
function Part({ part }: { part: unknown }) {
|
|
29
|
+
const mapped = toolPart(part);
|
|
30
|
+
|
|
31
|
+
if (!mapped) return null;
|
|
32
|
+
if (mapped.kind === 'approval') return <ApprovalCard title="Approve this call?" onDecisionChange={respond} />;
|
|
33
|
+
|
|
34
|
+
return <ToolCallCard name="searchOrders" status={mapped.status} input={mapped.input} output={mapped.output} />;
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**A decision is not a stage a call passes through, it is a question somebody answers** — which is why
|
|
39
|
+
two components cover what AI SDK reports as six states, and why the runtimes that report four are the
|
|
40
|
+
ones whose human-in-the-loop lives on a second channel:
|
|
41
|
+
|
|
42
|
+
| Runtime | What it reports | Where the question is |
|
|
43
|
+
| ------------ | -------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
|
|
44
|
+
| AI SDK 6/7 | `input-streaming`, `input-available`, `output-available`, `output-error`, `approval-requested`, `approval-responded` | Two of the six states, with `approval.approved` |
|
|
45
|
+
| assistant-ui | `status: { type: 'running' \| 'complete' \| 'incomplete' \| 'requires-action' }` | `requires-action`, under either of its two reasons |
|
|
46
|
+
| CopilotKit | `status: 'inProgress' \| 'executing' \| 'complete'` | `renderAndWaitForResponse`, which hands you `respond` |
|
|
47
|
+
| AG-UI | `TOOL_CALL_START` / `_ARGS` / `_END` / `_RESULT` events | `INTERRUPT` |
|
|
48
|
+
|
|
49
|
+
**AG-UI is the odd one out, and it is worth knowing why**: it reports _events_, not parts, so its cards
|
|
50
|
+
need a fold rather than a mapping. `applyToolEvent(parts, event)` is that fold — one call per event,
|
|
51
|
+
oldest first, keyed by `toolCallId`.
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { applyToolEvent } from '@box-kite/react/interop';
|
|
55
|
+
|
|
56
|
+
const parts = events.reduce(applyToolEvent, {});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## A2UI
|
|
60
|
+
|
|
61
|
+
[A2UI](https://a2ui.org/) is the declarative UI protocol Google published, and the one CopilotKit and
|
|
62
|
+
Oracle converged on. Its wire shape is the only one in this family that is genuinely different: a **flat
|
|
63
|
+
adjacency list** of components referring to each other by id, arriving one message at a time, with a data
|
|
64
|
+
model of its own per surface. `<SpecRenderer>` renders a tree, so this is a real adapter rather than a
|
|
65
|
+
rename.
|
|
66
|
+
|
|
67
|
+
### Their messages, rendered here
|
|
68
|
+
|
|
69
|
+
`a2uiApplyAll` folds a message stream into the surfaces it names, and `a2uiToSpec` turns one surface's
|
|
70
|
+
adjacency list into the tree the renderer takes. Both v0.8 and v0.9 are read; the fold is **pure and
|
|
71
|
+
hands the same state back when a message changed nothing**, so holding it in `useState` re-renders when
|
|
72
|
+
the surface moved and not when a message arrived for a different one.
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import { useState } from 'react';
|
|
76
|
+
import { a2uiApply, a2uiEmpty, a2uiSurface, a2uiToSpec } from '@box-kite/react/interop';
|
|
77
|
+
import SpecRenderer from '@box-kite/react/spec';
|
|
78
|
+
|
|
79
|
+
function Surface({ registry, catalog }) {
|
|
80
|
+
const [state, setState] = useState(a2uiEmpty);
|
|
81
|
+
|
|
82
|
+
useA2uiStream((message) => setState((current) => a2uiApply(current, message)));
|
|
83
|
+
|
|
84
|
+
const surface = a2uiSurface(state);
|
|
85
|
+
|
|
86
|
+
return <SpecRenderer spec={a2uiToSpec(surface, { catalog })} registry={registry} data={surface?.data} onAction={run} />;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Three things the two models already agreed on, each a special case that did not have to be written:
|
|
91
|
+
|
|
92
|
+
- **A2UI's data binding is already ours.** `{ "path": "/user/email" }` is a JSON Pointer, and `$data` has
|
|
93
|
+
taken a JSON Pointer since it was written, so a binding is a rename rather than a parse. The surface's
|
|
94
|
+
own data model is what goes in `<SpecRenderer data>`.
|
|
95
|
+
- **A template is a `repeat`.** `children: { componentId, path }` is one node per item of an array, which
|
|
96
|
+
is exactly what `repeat` means, so a list that streams costs nothing extra.
|
|
97
|
+
- **A half-arrived surface is the ordinary case.** An agent streams a leaf before the branch that holds
|
|
98
|
+
it; a component nothing reaches from the root is simply not rendered yet, and appears when the message
|
|
99
|
+
naming it does. A cycle in the id graph is cut rather than walked.
|
|
100
|
+
|
|
101
|
+
What A2UI owns rather than the component — `id`, `component`, `child`, `children`, `action` — never
|
|
102
|
+
reaches the registry as a prop. **`action` becomes an `on` binding under that name**, because what it
|
|
103
|
+
means belongs to the component it lands on: an app registering Box components under A2UI's own names
|
|
104
|
+
(`Text`, `Button`, `Row`) declares `events: ['action']` on them.
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
createSpecRegistry({
|
|
108
|
+
components: {
|
|
109
|
+
Button: { component: Button, events: ['action'], props: BUTTON_PROPS },
|
|
110
|
+
Column: { component: Flex, props: COLUMN_PROPS },
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Where the agent generated against _this library's_ catalog instead, pass it — then a prop the catalog
|
|
116
|
+
calls an event is bound as one and the rest are values:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
a2uiToSpec(surface, { catalog: catalog({ include: ['Flex', 'H2', 'Button'] }) });
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Our components, generated for
|
|
123
|
+
|
|
124
|
+
`a2uiCatalog(catalog())` is `catalog()` as an A2UI catalog document — the same components and the same
|
|
125
|
+
values their props take, in the shape around them that an adjacency list needs: a component carries its
|
|
126
|
+
own `id`, its type is a property rather than the key above it, and its children are **ids** rather than
|
|
127
|
+
nested nodes. Every event becomes a string, because a JSON message cannot carry a function: what an agent
|
|
128
|
+
writes is the name of an action, and `onAction` is where the host decides what it does.
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
import { catalog } from '@box-kite/react/catalog';
|
|
132
|
+
import { a2uiCatalog } from '@box-kite/react/interop';
|
|
133
|
+
|
|
134
|
+
export const document = a2uiCatalog(catalog({ include: ['Flex', 'H2', 'Sparkline'], styleProps: ['p', 'gap', 'bgColor'] }), {
|
|
135
|
+
catalogId: 'https://example.com/a2ui/box-kite.json',
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Serve it at the `catalogId` you gave it**, which is what an agent's `createSurface` names.
|
|
140
|
+
|
|
141
|
+
## CopilotKit
|
|
142
|
+
|
|
143
|
+
Two surfaces, and they want opposite directions.
|
|
144
|
+
|
|
145
|
+
**Its A2UI renderer** (`@copilotkit/a2ui-renderer`) takes a catalog built from Zod schemas and React
|
|
146
|
+
renderers. `z.fromJSONSchema` is the whole of the bridge — which is why `catalog()` emits JSON Schema at
|
|
147
|
+
all. One trap, measured against zod 4.6: **a `$ref` resolves against the document, not against the piece
|
|
148
|
+
you lifted out of it**, so converting a component on its own throws `Reference not found: #/$defs/color`.
|
|
149
|
+
`a2uiComponentSchema(document, name)` is that component with the document's definitions attached.
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
import { createCatalog } from '@copilotkit/a2ui-renderer';
|
|
153
|
+
import * as z from 'zod';
|
|
154
|
+
import { a2uiCatalog, a2uiComponentSchema } from '@box-kite/react/interop';
|
|
155
|
+
|
|
156
|
+
const document = a2uiCatalog(catalog({ include: ['Flex', 'H2', 'P'] }));
|
|
157
|
+
const names = Object.keys(document.components);
|
|
158
|
+
|
|
159
|
+
const definitions = Object.fromEntries(
|
|
160
|
+
names.map((name) => [name, { props: z.fromJSONSchema(a2uiComponentSchema(document, name)), description: '' }]),
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
// Their renderer hands a component its resolved props and a `children(id)` — the adjacency list again.
|
|
164
|
+
const renderers = { Flex: ({ props, children }) => <Flex {...props}>{props.children?.map(children)}</Flex> };
|
|
165
|
+
|
|
166
|
+
export const boxKiteCatalog = createCatalog(definitions, renderers, { catalogId: document.catalogId });
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Its actions** (`useCopilotAction`) take a render function, so the cards go in as they are. `render` is a
|
|
170
|
+
call being shown; `renderAndWaitForResponse` is a question, and the `respond` it hands you is what
|
|
171
|
+
`onDecisionChange` calls.
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
useCopilotAction({
|
|
175
|
+
name: 'refundOrder',
|
|
176
|
+
parameters: [{ name: 'orderId', type: 'number' }],
|
|
177
|
+
renderAndWaitForResponse: ({ args, respond }) => (
|
|
178
|
+
<ApprovalCard title={`Refund order ${args.orderId}`} onDecisionChange={(decision) => respond?.(decision === 'approved')} />
|
|
179
|
+
),
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## assistant-ui
|
|
184
|
+
|
|
185
|
+
Its `GenerativeUISpec` and this library's `SpecNode` are the same idea arrived at twice. Three
|
|
186
|
+
differences, and they are the whole adapter: the name is `component` rather than `type`, a child may be a
|
|
187
|
+
bare string that renders as text, and their nodes carry no data binding, no repeat and no action channel
|
|
188
|
+
— in their design those are the tool's job rather than the spec's.
|
|
189
|
+
|
|
190
|
+
`fromGenerativeUi(spec)` reads theirs and gives back an array of `SpecNode` (several roots stay several
|
|
191
|
+
roots; wrapping them in a container nobody asked for would change the layout). `toGenerativeUi(spec)`
|
|
192
|
+
goes the other way, and **reports what it could not carry** rather than emitting a tree that renders half
|
|
193
|
+
a view in silence:
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
const { spec, losses } = toGenerativeUi(node);
|
|
197
|
+
// losses: [{ code: 'data-binding' | 'repeat' | 'event', path }]
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Its Tool UI** is a component per tool name, and the cards go in as they are:
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
import { makeAssistantToolUI } from '@assistant-ui/react';
|
|
204
|
+
import { ToolCallCard } from '@box-kite/react/components/agent';
|
|
205
|
+
import { toolPart } from '@box-kite/react/interop';
|
|
206
|
+
|
|
207
|
+
export const SearchOrdersUI = makeAssistantToolUI({
|
|
208
|
+
toolName: 'searchOrders',
|
|
209
|
+
render: (part) => <ToolCallCard name="searchOrders" {...toolPart(part)} />,
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## json-render
|
|
214
|
+
|
|
215
|
+
[`@json-render/react`](https://json-render.dev) wants a Zod schema per component, and `z.fromJSONSchema`
|
|
216
|
+
is again the whole adapter — the recipe is in
|
|
217
|
+
[generative-ui.md](generative-ui.md#rendering-it-somewhere-else-json-render), with the measured caveat
|
|
218
|
+
that its own `validate` lets any props through once a catalog holds more than one component, so each
|
|
219
|
+
node still wants checking against its own schema.
|
|
220
|
+
|
|
221
|
+
## What is verified, and how
|
|
222
|
+
|
|
223
|
+
Every runtime named here is a devDependency of this repository, and `src/interop.test.tsx` runs the
|
|
224
|
+
adapters against the published packages rather than against a memory of them:
|
|
225
|
+
|
|
226
|
+
| Claim | Checked against |
|
|
227
|
+
| ------------------------------------------------------------ | ------------------------------------------------ |
|
|
228
|
+
| `toGenerativeUi` emits their `GenerativeUISpec` | `@assistant-ui/core`'s own type |
|
|
229
|
+
| `fromGenerativeUi` reads their `GenerativeUINode` | the same |
|
|
230
|
+
| every member of their `ToolCallMessagePartStatus` union maps | the same |
|
|
231
|
+
| `a2uiCatalog` is a document their `createCatalog` accepts | `@copilotkit/a2ui-renderer`'s published function |
|
|
232
|
+
| a surface generated against it renders here | the fold and `a2uiToSpec`, end to end |
|
|
233
|
+
| the catalog is one json-render accepts, and validates a spec | `@json-render/react`, in `src/catalog.test.tsx` |
|
|
234
|
+
|
|
235
|
+
The two cases A2UI's own conformance suite keeps for a message processor — that an update lands on the
|
|
236
|
+
surface it names and nowhere else, and that each surface owns its data model — are in
|
|
237
|
+
`src/utils/interop/a2uiInterop.test.ts` in the vocabulary that suite uses.
|
package/docs/mcp.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# @box-kite/mcp
|
|
2
|
+
|
|
3
|
+
The [Box Kite](https://www.box-kite.dev) MCP server: the retrieval channel for an agent writing Box
|
|
4
|
+
Kite code. Six tools, at capability level — what may I write, what does this component take, and the
|
|
5
|
+
one no documentation mirror can answer: **does this value actually work.**
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @box-kite/mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
No key, no network, no state. Everything it answers with was built into it from the library's own
|
|
12
|
+
repository at the version you install, including the styling engine itself. Node 22 or newer.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
**Claude Code**
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
claude mcp add box-kite -- npx -y @box-kite/mcp
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Cursor, VS Code, Codex, Zed** — anything that speaks stdio:
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"mcpServers": {
|
|
27
|
+
"box-kite": { "command": "npx", "args": ["-y", "@box-kite/mcp"] }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## The tools
|
|
33
|
+
|
|
34
|
+
| tool | what it answers |
|
|
35
|
+
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
36
|
+
| `search_docs` | The prop, component, nesting key or rule for what you are trying to build — ranked across all four, so a goal finds the answer without its name. |
|
|
37
|
+
| `get_props` | A style prop's whole record: the CSS it writes, every value it accepts, a measured example, and for a numeric prop its scale measured at 1/2/4/8. |
|
|
38
|
+
| `get_component` | One component's contract: props and defaults, sub-parts, the keyboard map and the ARIA it writes. |
|
|
39
|
+
| `check_styles` | A prop bag through the real engine: the CSS each prop writes, or why it wrote none. |
|
|
40
|
+
| `get_rules` | The rules the library is written by, as an index or in full. |
|
|
41
|
+
| `get_blocks` | Whole sections the `shadcn` CLI installs — a data-grid page, a settings form, a dashboard shell. |
|
|
42
|
+
|
|
43
|
+
## Why `check_styles` exists
|
|
44
|
+
|
|
45
|
+
Box Kite accepts a closed set of values per prop, and **a value it does not accept produces no rule
|
|
46
|
+
and no class name**, by design, because a typo must not emit a broken declaration. A development
|
|
47
|
+
build warns in the console once the page renders; a production one says nothing at all. The way to
|
|
48
|
+
answer "does `bgColor="blue-550"` work" before anything renders is to hand it to the engine:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
check_styles { "props": { "p": 4, "bgColor": "blue-550", "fontSize": 14, "lineHeight": 1.5, "href": "/about" } }
|
|
52
|
+
|
|
53
|
+
✅ `p` → `.p-4{padding:1rem}`
|
|
54
|
+
❌ `bgColor` does not accept "blue-550" — no rule and no class name were written.
|
|
55
|
+
✅ `fontSize` → `.fontSize-14{font-size:0.875rem}`
|
|
56
|
+
⚠️ `lineHeight` → `.lineHeight-1\.5{line-height:1.5px}` — lineHeight={1.5} is a 1.5px line: lineHeight is direct pixels, …
|
|
57
|
+
⚠️ `href` an HTML attribute, not a style prop. It goes in `props={{ "href": … }}`.
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The dividers differ per prop — spacing is ÷4, `fontSize` is ÷16, border width is direct px — which is
|
|
61
|
+
why `get_props` measures a scale rather than describing one.
|
|
62
|
+
|
|
63
|
+
## What else the library ships for agents
|
|
64
|
+
|
|
65
|
+
- `AGENTS.md` and `docs/` inside the published `@box-kite/react` package
|
|
66
|
+
- The skill and rules file: `npx skills add box-kite/box-kite`
|
|
67
|
+
- Every documentation page as markdown at `https://www.box-kite.dev/<route>.md`, indexed by
|
|
68
|
+
[llms.txt](https://www.box-kite.dev/llms.txt)
|
|
69
|
+
|
|
70
|
+
MIT © Box Kite
|
package/docs/props.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Every prop (
|
|
1
|
+
# Every prop (235)
|
|
2
2
|
|
|
3
3
|
Generated from the prop registry of `@box-kite/react`. The description is the prop's own doc comment and the example is **measured** — the CSS beside a value is what the engine emits for it, not what a doc claims. Alphabetical; the registry's own order is what decides the cascade and is not this.
|
|
4
4
|
|
|
@@ -14,7 +14,7 @@ The accent-color CSS property tints the parts of a native control the page does
|
|
|
14
14
|
|
|
15
15
|
- Writes: `accent-color`
|
|
16
16
|
- Values: 304 named values, anything else the types allow
|
|
17
|
-
- Example: `accentColor="sky-500"` → `accent-color: var(--sky-500)`
|
|
17
|
+
- Example: `accentColor="sky-500"` → `accent-color: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
18
18
|
|
|
19
19
|
### `ai`
|
|
20
20
|
|
|
@@ -112,6 +112,38 @@ The animation-play-state CSS property sets whether an animation is running or pa
|
|
|
112
112
|
- Values: `running` · `paused`
|
|
113
113
|
- Example: `animationPlayState="running"` → `animation-play-state: running`
|
|
114
114
|
|
|
115
|
+
### `animationRange`
|
|
116
|
+
|
|
117
|
+
The shorthand that sets both ends of the range at once: one value sets the start and leaves the end at `normal`, two set both. `entry` is the whole of the element coming into view, `cover 0% cover 50%` the first half of its pass across the scrollport. Only meaningful beside a view timeline.
|
|
118
|
+
|
|
119
|
+
- Writes: `animation-range`
|
|
120
|
+
- Values: whatever the types allow
|
|
121
|
+
- Example: `animationRange="entry"` → `animation-range: entry`
|
|
122
|
+
|
|
123
|
+
### `animationRangeEnd`
|
|
124
|
+
|
|
125
|
+
Where along the timeline the animation finishes: a named part of the pass (`cover`, `contain`, `entry`, `exit`, `entry-crossing`, `exit-crossing`), an offset into one, or a plain length.
|
|
126
|
+
|
|
127
|
+
- Writes: `animation-range-end`
|
|
128
|
+
- Values: whatever the types allow
|
|
129
|
+
- Example: `animationRangeEnd="exit"` → `animation-range-end: exit`
|
|
130
|
+
|
|
131
|
+
### `animationRangeStart`
|
|
132
|
+
|
|
133
|
+
Where along the timeline the animation starts. Same values as the end, and the pair is what turns "when this element is scrolled past" into "while it is entering, and no longer".
|
|
134
|
+
|
|
135
|
+
- Writes: `animation-range-start`
|
|
136
|
+
- Values: whatever the types allow
|
|
137
|
+
- Example: `animationRangeStart="entry 25%"` → `animation-range-start: entry 25%`
|
|
138
|
+
|
|
139
|
+
### `animationTimeline`
|
|
140
|
+
|
|
141
|
+
What drives the animation — a scroll position rather than a clock, so there is no rAF loop, no scroll listener and no state. `scroll()` is the nearest scrollport's progress (`scroll(root)` the page's), `view()` this element's progress through it; both need nothing declared anywhere else. A name is a timeline `scrollTimeline`/`viewTimeline` declared elsewhere. Two things to know. **It is declared after `animation`**, because the CSS shorthand resets this property to `auto` — the registry's order is what stops `animation="spin"` quietly undoing it. And a scroll-driven animation has **no duration**, so `--transitionTime` cannot reach it and reduced motion needs saying out loud: `motionReduce={{ animation: 'none' }}`.
|
|
142
|
+
|
|
143
|
+
- Writes: `animation-timeline`
|
|
144
|
+
- Values: `none` · `auto`, anything else the types allow
|
|
145
|
+
- Example: `animationTimeline="scroll()"` → `animation-timeline: scroll()`
|
|
146
|
+
|
|
115
147
|
### `animationTimingFunction`
|
|
116
148
|
|
|
117
149
|
How an animation progresses through each cycle: a keyword, one of the four sampled springs, or a curve of your own — `cubic-bezier()`, `steps()` and `linear()` are values. A spring names its duration too.
|
|
@@ -254,7 +286,7 @@ The background-color CSS property sets the background color of an element.
|
|
|
254
286
|
|
|
255
287
|
- Writes: `background-color`
|
|
256
288
|
- Values: 304 named values, anything else the types allow
|
|
257
|
-
- Example: `bgColor="sky-500"` → `background-color: var(--sky-500)`
|
|
289
|
+
- Example: `bgColor="sky-500"` → `background-color: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
258
290
|
|
|
259
291
|
### `bgGradient`
|
|
260
292
|
|
|
@@ -262,7 +294,7 @@ A gradient written as a value: the key names the kind and carries its geometry (
|
|
|
262
294
|
|
|
263
295
|
- Writes: `background-image`
|
|
264
296
|
- Values: whatever the types allow
|
|
265
|
-
- Example: `bgGradient={{ linear: 'r', colors: ['blue-500', 'pink-500'] }}` → `background-image: linear-gradient(to right,var(--blue-500),var(--pink-500))`
|
|
297
|
+
- Example: `bgGradient={{ linear: 'r', colors: ['blue-500', 'pink-500'] }}` → `background-image: linear-gradient(to right,var(--blue-500,oklch(62.3% .214 259.8)),var(--pink-500,oklch(65.6% .241 354.3)))`
|
|
266
298
|
|
|
267
299
|
### `bgImage`
|
|
268
300
|
|
|
@@ -270,7 +302,7 @@ The background-image CSS property sets one or more background images on an eleme
|
|
|
270
302
|
|
|
271
303
|
- Writes: `background-image`
|
|
272
304
|
- Values: `gradient-primary` · `gradient-aurora-light` · `gradient-aurora-dark` · `gradient-accent` · `bg-img-checked` · `bg-img-indeterminate` · `bg-img-radio` · `none`
|
|
273
|
-
- Example: `bgImage="gradient-primary"` → `background-image: var(--gradient-primary)`
|
|
305
|
+
- Example: `bgImage="gradient-primary"` → `background-image: var(--gradient-primary,linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #a855f7 100%))`
|
|
274
306
|
|
|
275
307
|
### `bl`
|
|
276
308
|
|
|
@@ -282,7 +314,7 @@ The border-left-width CSS property sets the width of the left border of an eleme
|
|
|
282
314
|
|
|
283
315
|
### `blur`
|
|
284
316
|
|
|
285
|
-
How far the element's own pixels are blurred: a step of
|
|
317
|
+
How far the element's own pixels are blurred: a step of the named scale (`xs` 4px through `xxxl` 64px) or a radius in px. One of nine functions that compose into a single `filter`, so a blur and a `brightness` coexist; `none` clears this one and leaves the rest.
|
|
286
318
|
|
|
287
319
|
- Writes: `--boxBlur`, `filter`
|
|
288
320
|
- Values: `xs` · `sm` · `md` · `lg` · `xl` · `xxl` · `xxxl` · `none`, a number
|
|
@@ -302,7 +334,7 @@ The border-color shorthand CSS property sets the color of an element's border.
|
|
|
302
334
|
|
|
303
335
|
- Writes: `border-color`
|
|
304
336
|
- Values: 304 named values, anything else the types allow
|
|
305
|
-
- Example: `borderColor="sky-500"` → `border-color: var(--sky-500)`
|
|
337
|
+
- Example: `borderColor="sky-500"` → `border-color: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
306
338
|
|
|
307
339
|
### `borderRadius`
|
|
308
340
|
|
|
@@ -510,7 +542,7 @@ The caret-color CSS property sets the colour of the insertion caret in a text fi
|
|
|
510
542
|
|
|
511
543
|
- Writes: `caret-color`
|
|
512
544
|
- Values: 304 named values, anything else the types allow
|
|
513
|
-
- Example: `caretColor="sky-500"` → `caret-color: var(--sky-500)`
|
|
545
|
+
- Example: `caretColor="sky-500"` → `caret-color: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
514
546
|
|
|
515
547
|
### `clipPath`
|
|
516
548
|
|
|
@@ -526,7 +558,7 @@ The color CSS property sets the foreground color value of an element's text and
|
|
|
526
558
|
|
|
527
559
|
- Writes: `color`
|
|
528
560
|
- Values: 304 named values, anything else the types allow
|
|
529
|
-
- Example: `color="sky-500"` → `color: var(--sky-500)`
|
|
561
|
+
- Example: `color="sky-500"` → `color: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
530
562
|
|
|
531
563
|
### `colorScheme`
|
|
532
564
|
|
|
@@ -662,7 +694,7 @@ What colour `dropShadow` draws in. Shows nothing on its own.
|
|
|
662
694
|
|
|
663
695
|
- Writes: `--boxDropShadowColor`
|
|
664
696
|
- Values: 304 named values, anything else the types allow
|
|
665
|
-
- Example: `dropShadowColor="sky-500"` → `--boxDropShadowColor: var(--sky-500)`
|
|
697
|
+
- Example: `dropShadowColor="sky-500"` → `--boxDropShadowColor: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
666
698
|
|
|
667
699
|
### `fieldSizing`
|
|
668
700
|
|
|
@@ -678,7 +710,7 @@ The fill CSS property defines how SVG text content and the interior canvas of SV
|
|
|
678
710
|
|
|
679
711
|
- Writes: `fill`
|
|
680
712
|
- Values: 304 named values, anything else the types allow
|
|
681
|
-
- Example: `fill="sky-500"` → `fill: var(--sky-500)`
|
|
713
|
+
- Example: `fill="sky-500"` → `fill: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
682
714
|
|
|
683
715
|
### `fillOpacity`
|
|
684
716
|
|
|
@@ -894,7 +926,7 @@ What colour `insetRing` draws in. `currentColor` otherwise.
|
|
|
894
926
|
|
|
895
927
|
- Writes: `--boxInsetRingColor`
|
|
896
928
|
- Values: 304 named values, anything else the types allow
|
|
897
|
-
- Example: `insetRingColor="sky-500"` → `--boxInsetRingColor: var(--sky-500)`
|
|
929
|
+
- Example: `insetRingColor="sky-500"` → `--boxInsetRingColor: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
898
930
|
|
|
899
931
|
### `insetShadow`
|
|
900
932
|
|
|
@@ -910,7 +942,7 @@ What colour `insetShadow` draws in. Shows nothing on its own.
|
|
|
910
942
|
|
|
911
943
|
- Writes: `--boxInsetShadowColor`
|
|
912
944
|
- Values: 304 named values, anything else the types allow
|
|
913
|
-
- Example: `insetShadowColor="sky-500"` → `--boxInsetShadowColor: var(--sky-500)`
|
|
945
|
+
- Example: `insetShadowColor="sky-500"` → `--boxInsetShadowColor: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
914
946
|
|
|
915
947
|
### `insetStart`
|
|
916
948
|
|
|
@@ -1022,7 +1054,7 @@ What the element is masked by: the alpha channel of an image decides which of it
|
|
|
1022
1054
|
|
|
1023
1055
|
- Writes: `mask-image`
|
|
1024
1056
|
- Values: `none`, anything else the types allow
|
|
1025
|
-
- Example: `maskImage={{ linear: 'b', colors: ['black', 'transparent'] }}` → `mask-image: linear-gradient(to bottom,var(--black),var(--transparent))`
|
|
1057
|
+
- Example: `maskImage={{ linear: 'b', colors: ['black', 'transparent'] }}` → `mask-image: linear-gradient(to bottom,var(--black,#000),var(--transparent,transparent))`
|
|
1026
1058
|
|
|
1027
1059
|
### `maxHeight`
|
|
1028
1060
|
|
|
@@ -1158,7 +1190,7 @@ The outline-color CSS property sets the color of an element's outline.
|
|
|
1158
1190
|
|
|
1159
1191
|
- Writes: `outline-color`
|
|
1160
1192
|
- Values: 304 named values, anything else the types allow
|
|
1161
|
-
- Example: `outlineColor="sky-500"` → `outline-color: var(--sky-500)`
|
|
1193
|
+
- Example: `outlineColor="sky-500"` → `outline-color: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
1162
1194
|
|
|
1163
1195
|
### `outlineOffset`
|
|
1164
1196
|
|
|
@@ -1386,11 +1418,11 @@ A hard-edged shadow outside the border box, in px — `ring={2}`. Unlike `outlin
|
|
|
1386
1418
|
|
|
1387
1419
|
### `ringColor`
|
|
1388
1420
|
|
|
1389
|
-
What colour `ring` draws in. `currentColor` otherwise
|
|
1421
|
+
What colour `ring` draws in. `currentColor` otherwise.
|
|
1390
1422
|
|
|
1391
1423
|
- Writes: `--boxRingColor`
|
|
1392
1424
|
- Values: 304 named values, anything else the types allow
|
|
1393
|
-
- Example: `ringColor="sky-500"` → `--boxRingColor: var(--sky-500)`
|
|
1425
|
+
- Example: `ringColor="sky-500"` → `--boxRingColor: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
1394
1426
|
|
|
1395
1427
|
### `rotate`
|
|
1396
1428
|
|
|
@@ -1446,7 +1478,7 @@ The scrollbar-color CSS property sets the color of the scrollbar thumb and track
|
|
|
1446
1478
|
|
|
1447
1479
|
- Writes: `scrollbar-color`
|
|
1448
1480
|
- Values: `currentColor,transparent,green,red,blue,gray,black,white,vi,slate-50,slate-100,slate-200,slate-300,slate-400,slate-500,slate-600,slate-700,slate-800,slate-900,slate-950,gray-50,gray-100,gray-200,gray-300,gray-400,gray-500,gray-600,gray-700,gray-800,gray-900,gray-950,zinc-50,zinc-100,zinc-200,zinc-300,zinc-400,zinc-500,zinc-600,zinc-700,zinc-800,zinc-900,zinc-950,neutral-50,neutral-100,neutral-200,neutral-300,neutral-400,neutral-500,neutral-600,neutral-700,neutral-800,neutral-900,neutral-950,stone-50,stone-100,stone-200,stone-300,stone-400,stone-500,stone-600,stone-700,stone-800,stone-900,stone-950,mauve-50,mauve-100,mauve-200,mauve-300,mauve-400,mauve-500,mauve-600,mauve-700,mauve-800,mauve-900,mauve-950,mist-50,mist-100,mist-200,mist-300,mist-400,mist-500,mist-600,mist-700,mist-800,mist-900,mist-950,olive-50,olive-100,olive-200,olive-300,olive-400,olive-500,olive-600,olive-700,olive-800,olive-900,olive-950,taupe-50,taupe-100,taupe-200,taupe-300,taupe-400,taupe-500,taupe-600,taupe-700,taupe-800,taupe-900,taupe-950,red-50,red-100,red-200,red-300,red-400,red-500,red-600,red-700,red-800,red-900,red-950,orange-50,orange-100,orange-200,orange-300,orange-400,orange-500,orange-600,orange-700,orange-800,orange-900,orange-950,amber-50,amber-100,amber-200,amber-300,amber-400,amber-500,amber-600,amber-700,amber-800,amber-900,amber-950,yellow-50,yellow-100,yellow-200,yellow-300,yellow-400,yellow-500,yellow-600,yellow-700,yellow-800,yellow-900,yellow-950,lime-50,lime-100,lime-200,lime-300,lime-400,lime-500,lime-600,lime-700,lime-800,lime-900,lime-950,green-50,green-100,green-200,green-300,green-400,green-500,green-600,green-700,green-800,green-900,green-950,emerald-50,emerald-100,emerald-200,emerald-300,emerald-400,emerald-500,emerald-600,emerald-700,emerald-800,emerald-900,emerald-950,teal-50,teal-100,teal-200,teal-300,teal-400,teal-500,teal-600,teal-700,teal-800,teal-900,teal-950,cyan-50,cyan-100,cyan-200,cyan-300,cyan-400,cyan-500,cyan-600,cyan-700,cyan-800,cyan-900,cyan-950,sky-50,sky-100,sky-200,sky-300,sky-400,sky-500,sky-600,sky-700,sky-800,sky-900,sky-950,blue-50,blue-100,blue-200,blue-300,blue-400,blue-500,blue-600,blue-700,blue-800,blue-900,blue-950,indigo-50,indigo-100,indigo-200,indigo-300,indigo-400,indigo-500,indigo-600,indigo-700,indigo-800,indigo-900,indigo-950,violet-50,violet-100,violet-200,violet-300,violet-400,violet-500,violet-600,violet-700,violet-800,violet-900,violet-950,purple-50,purple-100,purple-200,purple-300,purple-400,purple-500,purple-600,purple-700,purple-800,purple-900,purple-950,fuchsia-50,fuchsia-100,fuchsia-200,fuchsia-300,fuchsia-400,fuchsia-500,fuchsia-600,fuchsia-700,fuchsia-800,fuchsia-900,fuchsia-950,pink-50,pink-100,pink-200,pink-300,pink-400,pink-500,pink-600,pink-700,pink-800,pink-900,pink-950,rose-50,rose-100,rose-200,rose-300,rose-400,rose-500,rose-600,rose-700,rose-800,rose-900,rose-950,none`
|
|
1449
|
-
- Example: `scrollbarColor={['gray-400', 'gray-100']}` → `scrollbar-color: var(--gray-400) var(--gray-100)`
|
|
1481
|
+
- Example: `scrollbarColor={['gray-400', 'gray-100']}` → `scrollbar-color: var(--gray-400,oklch(70.7% .022 261.3)) var(--gray-100,oklch(96.7% .003 264.5))`
|
|
1450
1482
|
|
|
1451
1483
|
### `scrollbarGutter`
|
|
1452
1484
|
|
|
@@ -1464,6 +1496,30 @@ How wide a scrollbar the browser draws. `none` hides it without taking the scrol
|
|
|
1464
1496
|
- Values: `auto` · `thin` · `none`
|
|
1465
1497
|
- Example: `scrollbarWidth="auto"` → `scrollbar-width: auto`
|
|
1466
1498
|
|
|
1499
|
+
### `scrollTimeline`
|
|
1500
|
+
|
|
1501
|
+
Declares a named scroll timeline on this scroller — the shorthand, `<name>` or `<name> <axis>`, and the one to reach for: the longhands exist to override half of it. The name is written with or without the `--`, the way an anchor's is. Anything inside this element can then name it on `animationTimeline`; anything outside needs a `timelineScope` on a common ancestor.
|
|
1502
|
+
|
|
1503
|
+
- Writes: `scroll-timeline`
|
|
1504
|
+
- Values: `none`, anything else the types allow
|
|
1505
|
+
- Example: `scrollTimeline="page block"` → `scroll-timeline: --page block`
|
|
1506
|
+
|
|
1507
|
+
### `scrollTimelineAxis`
|
|
1508
|
+
|
|
1509
|
+
Which axis of this scroller the named timeline follows. `block`/`inline` are the writing mode's, so a timeline declared on the block axis is the vertical one in English and still correct in Japanese.
|
|
1510
|
+
|
|
1511
|
+
- Writes: `scroll-timeline-axis`
|
|
1512
|
+
- Values: `block` · `inline` · `x` · `y`
|
|
1513
|
+
- Example: `scrollTimelineAxis="block"` → `scroll-timeline-axis: block`
|
|
1514
|
+
|
|
1515
|
+
### `scrollTimelineName`
|
|
1516
|
+
|
|
1517
|
+
The name half of `scrollTimeline`, on its own.
|
|
1518
|
+
|
|
1519
|
+
- Writes: `scroll-timeline-name`
|
|
1520
|
+
- Values: `none`, anything else the types allow
|
|
1521
|
+
- Example: `scrollTimelineName="page"` → `scroll-timeline-name: --page`
|
|
1522
|
+
|
|
1467
1523
|
### `sepia`
|
|
1468
1524
|
|
|
1469
1525
|
How far the element is pushed towards sepia, as a percentage.
|
|
@@ -1474,7 +1530,7 @@ How far the element is pushed towards sepia, as a percentage.
|
|
|
1474
1530
|
|
|
1475
1531
|
### `shadow`
|
|
1476
1532
|
|
|
1477
|
-
The elevation of the box: `xxs` through `xxl` on
|
|
1533
|
+
The elevation of the box: `xxs` through `xxl` on the elevation scale, or one of the three original presets (`small`, `medium`, `large`, which carry their own colour). `shadowColor` recolours the scale, and the shadow stacks with `ring`, `insetRing` and `insetShadow` rather than replacing them.
|
|
1478
1534
|
|
|
1479
1535
|
- Writes: `--boxShadow`, `box-shadow`
|
|
1480
1536
|
- Values: `xxs` · `xs` · `sm` · `md` · `lg` · `xl` · `xxl` · `none` · `small` · `medium` · `large`
|
|
@@ -1486,7 +1542,7 @@ What colour `shadow` draws in — the scale's own translucent black otherwise. S
|
|
|
1486
1542
|
|
|
1487
1543
|
- Writes: `--boxShadowColor`
|
|
1488
1544
|
- Values: 304 named values, anything else the types allow
|
|
1489
|
-
- Example: `shadowColor="sky-500"` → `--boxShadowColor: var(--sky-500)`
|
|
1545
|
+
- Example: `shadowColor="sky-500"` → `--boxShadowColor: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
1490
1546
|
|
|
1491
1547
|
### `shapeRendering`
|
|
1492
1548
|
|
|
@@ -1502,7 +1558,7 @@ The stroke CSS property defines the color or SVG paint server used to draw an el
|
|
|
1502
1558
|
|
|
1503
1559
|
- Writes: `stroke`
|
|
1504
1560
|
- Values: 304 named values, anything else the types allow
|
|
1505
|
-
- Example: `stroke="sky-500"` → `stroke: var(--sky-500)`
|
|
1561
|
+
- Example: `stroke="sky-500"` → `stroke: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
1506
1562
|
|
|
1507
1563
|
### `strokeDasharray`
|
|
1508
1564
|
|
|
@@ -1614,7 +1670,7 @@ What colour `textShadow` draws in. Shows nothing on its own.
|
|
|
1614
1670
|
|
|
1615
1671
|
- Writes: `--boxTextShadowColor`
|
|
1616
1672
|
- Values: 304 named values, anything else the types allow
|
|
1617
|
-
- Example: `textShadowColor="sky-500"` → `--boxTextShadowColor: var(--sky-500)`
|
|
1673
|
+
- Example: `textShadowColor="sky-500"` → `--boxTextShadowColor: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
1618
1674
|
|
|
1619
1675
|
### `textTransform`
|
|
1620
1676
|
|
|
@@ -1632,6 +1688,14 @@ The text-wrap CSS shorthand property controls how text inside an element is wrap
|
|
|
1632
1688
|
- Values: `wrap` · `nowrap` · `balance` · `pretty`
|
|
1633
1689
|
- Example: `textWrap="wrap"` → `text-wrap: wrap`
|
|
1634
1690
|
|
|
1691
|
+
### `timelineScope`
|
|
1692
|
+
|
|
1693
|
+
Makes the named timelines below this element reachable from anywhere else below it. A timeline is otherwise visible only to the declaring element's own descendants, so a progress bar that is not inside the article it tracks needs their common ancestor to declare the scope. Comma-separated.
|
|
1694
|
+
|
|
1695
|
+
- Writes: `timeline-scope`
|
|
1696
|
+
- Values: `none`, anything else the types allow
|
|
1697
|
+
- Example: `timelineScope="page"` → `timeline-scope: --page`
|
|
1698
|
+
|
|
1635
1699
|
### `top`
|
|
1636
1700
|
|
|
1637
1701
|
The top CSS property sets the vertical position of a positioned element. This inset property has no effect on non-positioned elements. It also takes `anchor()`, an inset measured to one of the anchor's own edges.
|
|
@@ -1710,7 +1774,7 @@ CSS custom properties on this element, inherited by everything inside it: `vars=
|
|
|
1710
1774
|
|
|
1711
1775
|
- Writes: `--color-revenue`
|
|
1712
1776
|
- Values: whatever the types allow
|
|
1713
|
-
- Example: `vars={{ 'color-revenue': 'sky-500' }}` → `--color-revenue: var(--sky-500)`
|
|
1777
|
+
- Example: `vars={{ 'color-revenue': 'sky-500' }}` → `--color-revenue: var(--sky-500,oklch(68.5% .169 237.3))`
|
|
1714
1778
|
|
|
1715
1779
|
### `vectorEffect`
|
|
1716
1780
|
|
|
@@ -1720,6 +1784,54 @@ How an SVG element's stroke reacts to the transforms above it: `non-scaling-stro
|
|
|
1720
1784
|
- Values: `none` · `non-scaling-stroke`
|
|
1721
1785
|
- Example: `vectorEffect="none"` → `vector-effect: none`
|
|
1722
1786
|
|
|
1787
|
+
### `viewTimeline`
|
|
1788
|
+
|
|
1789
|
+
Declares a named view timeline on this element — its own progress across the scrollport, rather than the scroller's progress through its content. Same shorthand shape as `scrollTimeline`, and the same rule about who can see the name.
|
|
1790
|
+
|
|
1791
|
+
- Writes: `view-timeline`
|
|
1792
|
+
- Values: `none`, anything else the types allow
|
|
1793
|
+
- Example: `viewTimeline="card block"` → `view-timeline: --card block`
|
|
1794
|
+
|
|
1795
|
+
### `viewTimelineAxis`
|
|
1796
|
+
|
|
1797
|
+
Which axis this element's pass across the scrollport is measured on.
|
|
1798
|
+
|
|
1799
|
+
- Writes: `view-timeline-axis`
|
|
1800
|
+
- Values: `block` · `inline` · `x` · `y`
|
|
1801
|
+
- Example: `viewTimelineAxis="block"` → `view-timeline-axis: block`
|
|
1802
|
+
|
|
1803
|
+
### `viewTimelineInset`
|
|
1804
|
+
|
|
1805
|
+
Shrinks the scrollport the timeline measures against, so the pass starts and ends somewhere other than the viewport edges: one value for both ends, two for the start and the end. A positive inset moves the edge inwards, which is what makes an element count as "in view" before it really is.
|
|
1806
|
+
|
|
1807
|
+
- Writes: `view-timeline-inset`
|
|
1808
|
+
- Values: whatever the types allow
|
|
1809
|
+
- Example: `viewTimelineInset="20%"` → `view-timeline-inset: 20%`
|
|
1810
|
+
|
|
1811
|
+
### `viewTimelineName`
|
|
1812
|
+
|
|
1813
|
+
The name half of `viewTimeline`, on its own.
|
|
1814
|
+
|
|
1815
|
+
- Writes: `view-timeline-name`
|
|
1816
|
+
- Values: `none`, anything else the types allow
|
|
1817
|
+
- Example: `viewTimelineName="card"` → `view-timeline-name: --card`
|
|
1818
|
+
|
|
1819
|
+
### `viewTransitionClass`
|
|
1820
|
+
|
|
1821
|
+
A class shared by several named elements, so one rule styles the lot of them: `::view-transition-group(.card)` reaches every element carrying `viewTransitionClass="card"`. Space separated for more than one.
|
|
1822
|
+
|
|
1823
|
+
- Writes: `view-transition-class`
|
|
1824
|
+
- Values: `none`, anything else the types allow
|
|
1825
|
+
- Example: `viewTransitionClass="card"` → `view-transition-class: card`
|
|
1826
|
+
|
|
1827
|
+
### `viewTransitionName`
|
|
1828
|
+
|
|
1829
|
+
Names this element for a view transition, which is what makes the browser animate it from where it was to where it is rather than cross-fading the whole page over it. A name has to be **unique in the document while the transition runs** — two elements sharing one is how a transition silently does nothing — so a list wants a name per item, and that is a rule per item this library would never free: write those with `props={{ style: { viewTransitionName: id } }}`, the exception `useAnchorPosition` already takes. This prop is for the handful of names a layout has (`header`, `main`, `sidebar`).
|
|
1830
|
+
|
|
1831
|
+
- Writes: `view-transition-name`
|
|
1832
|
+
- Values: `none` · `auto` · `match-element`, anything else the types allow
|
|
1833
|
+
- Example: `viewTransitionName="header"` → `view-transition-name: header`
|
|
1834
|
+
|
|
1723
1835
|
### `visibility`
|
|
1724
1836
|
|
|
1725
1837
|
The visibility CSS property shows or hides an element without changing the layout of a document. The property can also hide rows or columns in a <table>.
|