@keboola/design 3.2.0 → 3.2.3
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/AGENTS.md +427 -0
- package/COMPONENT-API.md +377 -0
- package/README.md +12 -3
- package/dist/index.cjs +25 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -2
- package/dist/index.d.ts +26 -2
- package/dist/index.js +25 -2
- package/dist/index.js.map +1 -1
- package/dist/styles.css +3 -1
- package/dist/testing.cjs +23 -0
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.js +23 -0
- package/dist/testing.js.map +1 -1
- package/package.json +10 -6
- package/src/styles.css +22 -1
package/COMPONENT-API.md
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
# @keboola/design — component API reference
|
|
2
|
+
|
|
3
|
+
> **Generated file — do not edit by hand.** Regenerate with `yarn workspace @keboola/design generate:api` (extracts prop signatures from the TypeScript types via `react-docgen-typescript`).
|
|
4
|
+
|
|
5
|
+
This is the prop-signature contract for the most-used components. For _which_ component to reach for, see [`AGENTS.md`](./AGENTS.md) (the decision tree); for live worked examples, open the colocated `*.stories.tsx` in Storybook (`yarn dev --filter=@keboola/design`).
|
|
6
|
+
|
|
7
|
+
Props listed are the ones each component **declares itself**. Components built on a native element (`Button` on `<button>`, `Link` on `<a>`, `Card` on `<div>`, …) also accept that element's standard attributes — called out in each entry's note.
|
|
8
|
+
|
|
9
|
+
## Actions
|
|
10
|
+
|
|
11
|
+
### `Button`
|
|
12
|
+
|
|
13
|
+
Source: `src/components/Button/Button.tsx`
|
|
14
|
+
|
|
15
|
+
> Icons are composed as children, not an `icon` prop. Plus all native `<button>` attributes.
|
|
16
|
+
|
|
17
|
+
| Prop | Type | Required | Default | Description |
|
|
18
|
+
| ----------- | --------------------------------------------------------------------------------------------------------------------- | -------- | --------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| `argo` | `boolean` | no | `false` | @internal Transitional opt-in; removed once consumers wrap argo sections in `<ThemeProvider>`. |
|
|
20
|
+
| `asChild` | `boolean` | no | `false` | Render as a Radix `Slot` so the parent JSX (e.g. a `react-router` `<Link>`) becomes the button element. |
|
|
21
|
+
| `block` | `boolean \| null` | no | `false` | |
|
|
22
|
+
| `isLoading` | `boolean` | no | `false` | Replaces the leading content with a spinner and disables the button visually. The caller still controls `disabled`. |
|
|
23
|
+
| `size` | `"small" \| "medium" \| "large" \| "icon-lg" \| "icon" \| "icon-sm" \| "icon-xs" \| "icon-2xs" \| "icon-3xs" \| null` | no | `medium` | |
|
|
24
|
+
| `variant` | `"primary" \| "secondary" \| "danger" \| "invisible" \| "outline" \| "inline" \| null` | no | `primary` | |
|
|
25
|
+
|
|
26
|
+
### `ButtonInline`
|
|
27
|
+
|
|
28
|
+
Source: `src/components/Button/ButtonInline.tsx`
|
|
29
|
+
|
|
30
|
+
> Inline text-link-style action. Plus all native `<button>` attributes.
|
|
31
|
+
|
|
32
|
+
| Prop | Type | Required | Default | Description |
|
|
33
|
+
| --------- | ---------------------------------------------- | -------- | ------- | ----------- |
|
|
34
|
+
| `asChild` | `boolean` | no | `false` | |
|
|
35
|
+
| `variant` | `"link" \| "custom" \| "link-reverse" \| null` | no | — | |
|
|
36
|
+
|
|
37
|
+
### `Link`
|
|
38
|
+
|
|
39
|
+
Source: `src/components/Link.tsx`
|
|
40
|
+
|
|
41
|
+
> Defaults `target="_blank"` + `rel="noopener noreferrer"`. Accepts all native `<a>` attributes (`href`, `target`, …) — none are required props.
|
|
42
|
+
|
|
43
|
+
_No own props — see note above for passthrough attributes._
|
|
44
|
+
|
|
45
|
+
## Status surfaces
|
|
46
|
+
|
|
47
|
+
### `Alert`
|
|
48
|
+
|
|
49
|
+
Source: `src/components/Alert/Alert.tsx`
|
|
50
|
+
|
|
51
|
+
> Discriminated by `mode`: `"default"` renders `title`/`children`/`actions`; `"collapsible"` requires `title`+`children` and forbids `actions`. `variant` is a categorical colour contract (`info`/`success`/`warning`/`error`).
|
|
52
|
+
|
|
53
|
+
| Prop | Type | Required | Default | Description |
|
|
54
|
+
| ---------- | ---------------------------- | -------- | --------- | ---------------------------------------------------------------------------------------------- |
|
|
55
|
+
| `actions` | `ReactNode` | no | — | |
|
|
56
|
+
| `argo` | `boolean` | no | — | @internal Transitional opt-in; removed once consumers wrap argo sections in `<ThemeProvider>`. |
|
|
57
|
+
| `hideIcon` | `boolean` | no | `false` | |
|
|
58
|
+
| `icon` | `ReactNode` | no | — | |
|
|
59
|
+
| `mode` | `"collapsible" \| "default"` | no | `default` | |
|
|
60
|
+
| `variant` | `Variant` | no | `info` | |
|
|
61
|
+
|
|
62
|
+
### `Toaster`
|
|
63
|
+
|
|
64
|
+
Source: `src/components/Toast/Toaster.tsx`
|
|
65
|
+
|
|
66
|
+
> Mount ONCE at app root. Wraps `sonner`'s `<Toaster>` — accepts all of sonner's props (`position`, `theme`, `richColors`, …). Fire toasts imperatively with `toast()` / `useNotification`, not by rendering children.
|
|
67
|
+
|
|
68
|
+
_No own props — see note above for passthrough attributes._
|
|
69
|
+
|
|
70
|
+
## Inputs — bare
|
|
71
|
+
|
|
72
|
+
### `TextInput`
|
|
73
|
+
|
|
74
|
+
Source: `src/components/Input/TextInput/TextInput.tsx`
|
|
75
|
+
|
|
76
|
+
> Bare input. Plus all native `<input>` attributes.
|
|
77
|
+
|
|
78
|
+
| Prop | Type | Required | Default | Description |
|
|
79
|
+
| -------------------- | --------------------------------------------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------- |
|
|
80
|
+
| `allowClear` | `boolean` | no | — | |
|
|
81
|
+
| `defaultValue` | `string \| null` | no | — | |
|
|
82
|
+
| `focusVariant` | `"off" \| "on" \| "default" \| null` | no | — | |
|
|
83
|
+
| `leftSuffix` | `ReactNode` | no | — | |
|
|
84
|
+
| `onClear` | `(() => void)` | no | — | |
|
|
85
|
+
| `onValueBlur` | `((value: string) => void)` | no | — | Called with the unwrapped string value on blur. For the raw event use `onBlur`. |
|
|
86
|
+
| `onValueChange` | `((value: string) => void)` | no | — | Called with the unwrapped string value on every change. For the raw event use `onChange`. |
|
|
87
|
+
| `prefix` | `ReactNode` | no | — | |
|
|
88
|
+
| `rightSuffix` | `ReactNode` | no | — | |
|
|
89
|
+
| `rightSuffixVariant` | `"default" \| "addon"` | no | — | |
|
|
90
|
+
| `sizing` | `"small" \| "medium" \| "default" \| null` | no | — | |
|
|
91
|
+
| `state` | `"warning" \| "error" \| "default" \| null` | no | — | |
|
|
92
|
+
| `testId` | `string` | no | — | |
|
|
93
|
+
| `type` | `"text" \| "email" \| "date" \| "datetime-local" \| "password"` | no | `text` | |
|
|
94
|
+
| `value` | `string \| null` | no | — | |
|
|
95
|
+
| `variant` | `"primary" \| "secondary" \| "argo" \| null` | no | — | |
|
|
96
|
+
|
|
97
|
+
### `PasswordInput`
|
|
98
|
+
|
|
99
|
+
Source: `src/blocks/PasswordInput/PasswordInput.tsx`
|
|
100
|
+
|
|
101
|
+
| Prop | Type | Required | Default | Description |
|
|
102
|
+
| --------------------------- | ----------------------------------------------- | -------- | -------------- | ----------- |
|
|
103
|
+
| `allowClear` | `boolean` | no | `false` | |
|
|
104
|
+
| `allowPasswordToggle` | `boolean` | no | `false` | |
|
|
105
|
+
| `autoComplete` | `"off" \| "current-password" \| "new-password"` | no | `new-password` | |
|
|
106
|
+
| `defaultPasswordVisibility` | `boolean` | no | `false` | |
|
|
107
|
+
| `defaultValue` | `string \| null` | no | — | |
|
|
108
|
+
| `focusVariant` | `"off" \| "on" \| "default" \| null` | no | — | |
|
|
109
|
+
| `onValueBlur` | `((value: string) => void)` | no | — | |
|
|
110
|
+
| `onValueChange` | `((value: string) => void)` | no | — | |
|
|
111
|
+
| `sizing` | `"small" \| "medium" \| "default" \| null` | no | — | |
|
|
112
|
+
| `state` | `"warning" \| "error" \| "default" \| null` | no | — | |
|
|
113
|
+
| `value` | `string \| null` | no | — | |
|
|
114
|
+
| `variant` | `"primary" \| "secondary" \| "argo" \| null` | no | — | |
|
|
115
|
+
|
|
116
|
+
### `Textarea`
|
|
117
|
+
|
|
118
|
+
Source: `src/blocks/Textarea/Textarea.tsx`
|
|
119
|
+
|
|
120
|
+
| Prop | Type | Required | Default | Description |
|
|
121
|
+
| -------------------- | --------------------------------------------------------- | -------- | --------- | ----------- |
|
|
122
|
+
| `containerClassName` | `string` | no | — | |
|
|
123
|
+
| `defaultValue` | `string \| null` | no | — | |
|
|
124
|
+
| `disableResize` | `boolean` | no | — | |
|
|
125
|
+
| `focusVariant` | `"off" \| "on" \| "default" \| null` | no | — | |
|
|
126
|
+
| `maxRows` | `number \| "unlimited"` | no | — | |
|
|
127
|
+
| `onValueBlur` | `(((value: string) => void) & ((value: string) => void))` | no | — | |
|
|
128
|
+
| `onValueChange` | `(((value: string) => void) & ((value: string) => void))` | no | — | |
|
|
129
|
+
| `sizing` | `"small" \| "medium" \| "default" \| null` | no | — | |
|
|
130
|
+
| `state` | `"warning" \| "error" \| "default" \| null` | no | `default` | |
|
|
131
|
+
| `value` | `string \| null` | no | — | |
|
|
132
|
+
| `variant` | `"primary" \| "secondary" \| "argo" \| null` | no | — | |
|
|
133
|
+
|
|
134
|
+
## Inputs — FormGroup (label + input + help, shared validation state)
|
|
135
|
+
|
|
136
|
+
### `FormGroup`
|
|
137
|
+
|
|
138
|
+
Source: `src/components/FormGroup/FormGroup.tsx`
|
|
139
|
+
|
|
140
|
+
> `state="error"` propagates to nested `FormGroup.TextInput` / `FormGroup.Help` via context. Subcomponents: `FormGroup.TextInput`, `FormGroup.NumberInput`, `FormGroup.ColorInput`, `FormGroup.Textarea`, `FormGroup.Help`.
|
|
141
|
+
|
|
142
|
+
| Prop | Type | Required | Default | Description |
|
|
143
|
+
| ----------- | --------------- | -------- | ------- | ----------- |
|
|
144
|
+
| `className` | `string` | no | — | |
|
|
145
|
+
| `state` | `ValidityState` | no | — | |
|
|
146
|
+
| `testId` | `string` | no | — | |
|
|
147
|
+
|
|
148
|
+
### `FormGroup.TextInput`
|
|
149
|
+
|
|
150
|
+
Source: `src/components/FormGroup/FormGroupTextInput.tsx`
|
|
151
|
+
|
|
152
|
+
> NO `error` prop — error styling comes from the parent `FormGroup state="error"` via context. `state` is omitted from the surface for the same reason. Plus native `<input>` attributes.
|
|
153
|
+
|
|
154
|
+
| Prop | Type | Required | Default | Description |
|
|
155
|
+
| -------------------- | --------------------------------------------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------- |
|
|
156
|
+
| `allowClear` | `boolean` | no | — | |
|
|
157
|
+
| `defaultValue` | `string \| null` | no | — | |
|
|
158
|
+
| `focusVariant` | `"off" \| "on" \| "default" \| null` | no | — | |
|
|
159
|
+
| `leftSuffix` | `ReactNode` | no | — | |
|
|
160
|
+
| `onClear` | `(() => void)` | no | — | |
|
|
161
|
+
| `onValueBlur` | `((value: string) => void)` | no | — | Called with the unwrapped string value on blur. For the raw event use `onBlur`. |
|
|
162
|
+
| `onValueChange` | `((value: string) => void)` | no | — | Called with the unwrapped string value on every change. For the raw event use `onChange`. |
|
|
163
|
+
| `prefix` | `ReactNode` | no | — | |
|
|
164
|
+
| `rightSuffix` | `ReactNode` | no | — | |
|
|
165
|
+
| `rightSuffixVariant` | `"default" \| "addon"` | no | — | |
|
|
166
|
+
| `sizing` | `"small" \| "medium" \| "default" \| null` | no | — | |
|
|
167
|
+
| `testId` | `string` | no | — | |
|
|
168
|
+
| `type` | `"text" \| "email" \| "date" \| "datetime-local" \| "password"` | no | — | |
|
|
169
|
+
| `value` | `string \| null` | no | — | |
|
|
170
|
+
| `variant` | `"primary" \| "secondary" \| "argo" \| null` | no | — | |
|
|
171
|
+
|
|
172
|
+
### `FormGroup.Help`
|
|
173
|
+
|
|
174
|
+
Source: `src/components/FormGroup/FormGroupHelp.tsx`
|
|
175
|
+
|
|
176
|
+
| Prop | Type | Required | Default | Description |
|
|
177
|
+
| ----------- | -------- | -------- | ------- | ----------- |
|
|
178
|
+
| `className` | `string` | no | — | |
|
|
179
|
+
|
|
180
|
+
## Forms — useAppForm field connectors (accessed as `field.X` inside `form.AppField`)
|
|
181
|
+
|
|
182
|
+
### `field.TextField`
|
|
183
|
+
|
|
184
|
+
Source: `src/blocks/Form/connectors/TextField.tsx`
|
|
185
|
+
|
|
186
|
+
> Value/onChange/onBlur/id/name are wired from the field — do not pass them. Forwards remaining `FormGroup.TextInput` props.
|
|
187
|
+
|
|
188
|
+
| Prop | Type | Required | Default | Description |
|
|
189
|
+
| -------------------- | --------------------------------------------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------- |
|
|
190
|
+
| `allowClear` | `boolean` | no | — | |
|
|
191
|
+
| `className` | `string` | no | — | |
|
|
192
|
+
| `defaultValue` | `string \| null` | no | — | |
|
|
193
|
+
| `focusVariant` | `"off" \| "on" \| "default" \| null` | no | — | |
|
|
194
|
+
| `help` | `ReactNode` | no | — | |
|
|
195
|
+
| `label` | `ReactNode` | no | — | |
|
|
196
|
+
| `leftSuffix` | `ReactNode` | no | — | |
|
|
197
|
+
| `onClear` | `(() => void)` | no | — | |
|
|
198
|
+
| `onValueBlur` | `((value: string) => void)` | no | — | Called with the unwrapped string value on blur. For the raw event use `onBlur`. |
|
|
199
|
+
| `onValueChange` | `((value: string) => void)` | no | — | Called with the unwrapped string value on every change. For the raw event use `onChange`. |
|
|
200
|
+
| `prefix` | `ReactNode` | no | — | |
|
|
201
|
+
| `required` | `boolean` | no | — | |
|
|
202
|
+
| `rightSuffix` | `ReactNode` | no | — | |
|
|
203
|
+
| `rightSuffixVariant` | `"default" \| "addon"` | no | — | |
|
|
204
|
+
| `sizing` | `"small" \| "medium" \| "default" \| null` | no | — | |
|
|
205
|
+
| `testId` | `string` | no | — | |
|
|
206
|
+
| `type` | `"text" \| "email" \| "date" \| "datetime-local" \| "password"` | no | — | |
|
|
207
|
+
| `variant` | `"primary" \| "secondary" \| "argo" \| null` | no | — | |
|
|
208
|
+
|
|
209
|
+
### `field.PasswordField`
|
|
210
|
+
|
|
211
|
+
Source: `src/blocks/Form/connectors/PasswordField.tsx`
|
|
212
|
+
|
|
213
|
+
| Prop | Type | Required | Default | Description |
|
|
214
|
+
| --------------------------- | ----------------------------------------------- | -------- | ------- | ----------- |
|
|
215
|
+
| `allowClear` | `boolean` | no | — | |
|
|
216
|
+
| `allowPasswordToggle` | `boolean` | no | — | |
|
|
217
|
+
| `autoComplete` | `"off" \| "current-password" \| "new-password"` | no | — | |
|
|
218
|
+
| `className` | `string` | no | — | |
|
|
219
|
+
| `defaultPasswordVisibility` | `boolean` | no | — | |
|
|
220
|
+
| `defaultValue` | `string \| null` | no | — | |
|
|
221
|
+
| `focusVariant` | `"off" \| "on" \| "default" \| null` | no | — | |
|
|
222
|
+
| `help` | `ReactNode` | no | — | |
|
|
223
|
+
| `label` | `ReactNode` | no | — | |
|
|
224
|
+
| `onValueBlur` | `((value: string) => void)` | no | — | |
|
|
225
|
+
| `required` | `boolean` | no | — | |
|
|
226
|
+
| `sizing` | `"small" \| "medium" \| "default" \| null` | no | — | |
|
|
227
|
+
| `state` | `"warning" \| "error" \| "default" \| null` | no | — | |
|
|
228
|
+
| `variant` | `"primary" \| "secondary" \| "argo" \| null` | no | — | |
|
|
229
|
+
|
|
230
|
+
### `field.NumberField`
|
|
231
|
+
|
|
232
|
+
Source: `src/blocks/Form/connectors/NumberField.tsx`
|
|
233
|
+
|
|
234
|
+
| Prop | Type | Required | Default | Description |
|
|
235
|
+
| -------------- | -------------------------------------------- | -------- | ------- | ----------- |
|
|
236
|
+
| `className` | `string` | no | — | |
|
|
237
|
+
| `defaultValue` | `number \| null` | no | — | |
|
|
238
|
+
| `focusVariant` | `"off" \| "on" \| "default" \| null` | no | — | |
|
|
239
|
+
| `help` | `ReactNode` | no | — | |
|
|
240
|
+
| `label` | `ReactNode` | no | — | |
|
|
241
|
+
| `onValueBlur` | `((value: number \| null) => void)` | no | — | |
|
|
242
|
+
| `prefix` | `ReactNode` | no | — | |
|
|
243
|
+
| `required` | `boolean` | no | — | |
|
|
244
|
+
| `sizing` | `"small" \| "medium" \| "default" \| null` | no | — | |
|
|
245
|
+
| `suffix` | `ReactNode` | no | — | |
|
|
246
|
+
| `variant` | `"primary" \| "secondary" \| "argo" \| null` | no | — | |
|
|
247
|
+
|
|
248
|
+
### `field.SelectField`
|
|
249
|
+
|
|
250
|
+
Source: `src/blocks/Form/connectors/SelectField.tsx`
|
|
251
|
+
|
|
252
|
+
> `options` is required. Forwards `variant === "argo"` to `Select.Content`.
|
|
253
|
+
|
|
254
|
+
| Prop | Type | Required | Default | Description |
|
|
255
|
+
| ------------------ | -------------------------------------------- | -------- | ------- | ----------- |
|
|
256
|
+
| `options` | `readonly Option[]` | yes | — | |
|
|
257
|
+
| `autoComplete` | `string` | no | — | |
|
|
258
|
+
| `className` | `string` | no | — | |
|
|
259
|
+
| `defaultOpen` | `boolean` | no | — | |
|
|
260
|
+
| `defaultValue` | `string` | no | — | |
|
|
261
|
+
| `dir` | `"rtl" \| "ltr"` | no | — | |
|
|
262
|
+
| `disabled` | `boolean` | no | — | |
|
|
263
|
+
| `form` | `string` | no | — | |
|
|
264
|
+
| `help` | `ReactNode` | no | — | |
|
|
265
|
+
| `label` | `ReactNode` | no | — | |
|
|
266
|
+
| `name` | `string` | no | — | |
|
|
267
|
+
| `onOpenChange` | `((open: boolean) => void)` | no | — | |
|
|
268
|
+
| `open` | `boolean` | no | — | |
|
|
269
|
+
| `placeholder` | `string` | no | — | |
|
|
270
|
+
| `required` | `boolean` | no | — | |
|
|
271
|
+
| `sizing` | `"small" \| "medium" \| "default" \| null` | no | — | |
|
|
272
|
+
| `state` | `"warning" \| "error" \| "default" \| null` | no | — | |
|
|
273
|
+
| `triggerClassName` | `string` | no | — | |
|
|
274
|
+
| `variant` | `"primary" \| "secondary" \| "argo" \| null` | no | — | |
|
|
275
|
+
|
|
276
|
+
### `field.TextAreaField`
|
|
277
|
+
|
|
278
|
+
Source: `src/blocks/Form/connectors/TextAreaField.tsx`
|
|
279
|
+
|
|
280
|
+
| Prop | Type | Required | Default | Description |
|
|
281
|
+
| -------------------- | --------------------------------------------------------- | -------- | ------- | ----------- |
|
|
282
|
+
| `className` | `string` | no | — | |
|
|
283
|
+
| `containerClassName` | `string` | no | — | |
|
|
284
|
+
| `defaultValue` | `string \| null` | no | — | |
|
|
285
|
+
| `disableResize` | `boolean` | no | — | |
|
|
286
|
+
| `focusVariant` | `"off" \| "on" \| "default" \| null` | no | — | |
|
|
287
|
+
| `help` | `ReactNode` | no | — | |
|
|
288
|
+
| `label` | `ReactNode` | no | — | |
|
|
289
|
+
| `maxRows` | `number \| "unlimited"` | no | — | |
|
|
290
|
+
| `onValueBlur` | `(((value: string) => void) & ((value: string) => void))` | no | — | |
|
|
291
|
+
| `required` | `boolean` | no | — | |
|
|
292
|
+
| `sizing` | `"small" \| "medium" \| "default" \| null` | no | — | |
|
|
293
|
+
| `variant` | `"primary" \| "secondary" \| "argo" \| null` | no | — | |
|
|
294
|
+
|
|
295
|
+
### `field.CheckboxField`
|
|
296
|
+
|
|
297
|
+
Source: `src/blocks/Form/connectors/CheckboxField.tsx`
|
|
298
|
+
|
|
299
|
+
| Prop | Type | Required | Default | Description |
|
|
300
|
+
| ------------------ | ---------------------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------- |
|
|
301
|
+
| `argo` | `boolean` | no | — | @internal Transitional opt-in; removed once consumers wrap argo sections in `<ThemeProvider>`. |
|
|
302
|
+
| `asChild` | `boolean` | no | — | |
|
|
303
|
+
| `className` | `string` | no | — | |
|
|
304
|
+
| `description` | `ReactNode` | no | — | |
|
|
305
|
+
| `help` | `ReactNode` | no | — | |
|
|
306
|
+
| `label` | `ReactNode` | no | — | |
|
|
307
|
+
| `position` | `"start" \| "end"` | no | — | |
|
|
308
|
+
| `tooltip` | `ReactNode` | no | — | |
|
|
309
|
+
| `tooltipPlacement` | `"top" \| "right" \| "bottom" \| "left"` | no | — | |
|
|
310
|
+
| `variant` | `"default" \| "boxed" \| null` | no | — | |
|
|
311
|
+
|
|
312
|
+
### `field.SwitchField`
|
|
313
|
+
|
|
314
|
+
Source: `src/blocks/Form/connectors/SwitchField.tsx`
|
|
315
|
+
|
|
316
|
+
| Prop | Type | Required | Default | Description |
|
|
317
|
+
| ------------- | ---------------------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------- |
|
|
318
|
+
| `argo` | `boolean` | no | — | @internal Transitional opt-in; removed once consumers wrap argo sections in `<ThemeProvider>`. |
|
|
319
|
+
| `className` | `string` | no | — | |
|
|
320
|
+
| `description` | `ReactNode` | no | — | |
|
|
321
|
+
| `help` | `ReactNode` | no | — | |
|
|
322
|
+
| `label` | `ReactNode` | no | — | |
|
|
323
|
+
| `position` | `"start" \| "end"` | no | — | |
|
|
324
|
+
| `size` | `"small" \| "medium" \| "large" \| null` | no | — | |
|
|
325
|
+
| `variant` | `"default" \| "boxed" \| null` | no | — | |
|
|
326
|
+
|
|
327
|
+
## Data display — Card (compound)
|
|
328
|
+
|
|
329
|
+
### `Card`
|
|
330
|
+
|
|
331
|
+
Source: `src/components/Card/Card.tsx`
|
|
332
|
+
|
|
333
|
+
> Subcomponents that EXIST: `Card.Header`, `Card.Title`, `Card.Content`. There is NO `Card.Description` and NO `Card.Footer`. Plus native `<div>` attributes.
|
|
334
|
+
|
|
335
|
+
| Prop | Type | Required | Default | Description |
|
|
336
|
+
| ---------- | -------------------------------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------- |
|
|
337
|
+
| `argo` | `boolean` | no | `false` | @internal Transitional opt-in; removed once consumers wrap argo sections in `<ThemeProvider>`. |
|
|
338
|
+
| `bordered` | `boolean \| null` | no | `false` | |
|
|
339
|
+
| `padding` | `"small" \| "medium" \| "large" \| "none" \| null` | no | `small` | |
|
|
340
|
+
|
|
341
|
+
### `Card.Header`
|
|
342
|
+
|
|
343
|
+
Source: `src/components/Card/CardHeader.tsx`
|
|
344
|
+
|
|
345
|
+
> Native `<div>` attributes only.
|
|
346
|
+
|
|
347
|
+
_No own props — see note above for passthrough attributes._
|
|
348
|
+
|
|
349
|
+
### `Card.Title`
|
|
350
|
+
|
|
351
|
+
Source: `src/components/Card/CardTitle.tsx`
|
|
352
|
+
|
|
353
|
+
> Native `<div>` attributes only.
|
|
354
|
+
|
|
355
|
+
_No own props — see note above for passthrough attributes._
|
|
356
|
+
|
|
357
|
+
### `Card.Content`
|
|
358
|
+
|
|
359
|
+
Source: `src/components/Card/CardContent.tsx`
|
|
360
|
+
|
|
361
|
+
> Native `<div>` attributes only.
|
|
362
|
+
|
|
363
|
+
_No own props — see note above for passthrough attributes._
|
|
364
|
+
|
|
365
|
+
## Theming
|
|
366
|
+
|
|
367
|
+
### `ThemeProvider`
|
|
368
|
+
|
|
369
|
+
Source: `src/components/ThemeProvider/ThemeProvider.tsx`
|
|
370
|
+
|
|
371
|
+
> Wrap the app root. `brand` defaults to the canonical `keboola` brand. Pair with `useTheme()` to read/flip the brand at runtime.
|
|
372
|
+
|
|
373
|
+
| Prop | Type | Required | Default | Description |
|
|
374
|
+
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
375
|
+
| `brand` | `{ id: string; name: string; colors: { foreground: string; background: string; muted: string; mutedForeground: string; border: string; primary: string; primaryForeground: string; destructive: string; destructiveForeground: string; accent?: string; accentForeground?: string; }; ... 6 more ...; ...` | no | — | Brand whose tokens drive the chrome (`@keboola/design`'s semantic CSS variables) inside this provider's subtree. Defaults to the canonical `keboola` brand so existing apps that mount `<ThemeProvider>` without a `brand` prop continue to render as today. |
|
|
376
|
+
| `colorScheme` | `ColorScheme` | no | `light` | Light/dark mode. `'system'` follows `prefers-color-scheme` and updates reactively. Defaults to `'light'` so existing mounts don't drift. Only the ROOT provider applies this (sets `data-theme`, owns the media listener); a nested provider inherits the root's resolved mode. |
|
|
377
|
+
| `setBrand` | `((brand: { id: string; name: string; colors: { foreground: string; background: string; muted: string; mutedForeground: string; border: string; primary: string; primaryForeground: string; destructive: string; destructiveForeground: string; accent?: string; accentForeground?: string; }; ... 6 m...` | no | — | Optional setter exposed through `useTheme()` so consumers can flip brands at runtime (Storybook toolbar, a customer-impersonation switch). |
|
package/README.md
CHANGED
|
@@ -7,9 +7,18 @@ The Keboola design system — shadcn-aligned, Radix-underneath, Lucide icons.
|
|
|
7
7
|
|
|
8
8
|
📦 **Storybook:** https://design-keboola.vercel.app/
|
|
9
9
|
|
|
10
|
-
📖 **Decision tree:** [`AGENTS.md`](./AGENTS.md) — which component to use when.
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
📖 **Decision tree:** [`AGENTS.md`](./AGENTS.md) — which component to use when (ships in the tarball).
|
|
11
|
+
🔧 **Prop signatures:** [`COMPONENT-API.md`](./COMPONENT-API.md) — generated, version-pinned (ships in the tarball).
|
|
12
|
+
|
|
13
|
+
## For agents and consumers: read the installed package's AGENTS.md first
|
|
14
|
+
|
|
15
|
+
Before writing UI with this design system, read the contract that ships with the version you installed:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
node_modules/@keboola/design/AGENTS.md
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
It is version-pinned to your lockfile, so it always matches the components you actually have — read it rather than relying on the published Storybook or these docs, which track `main`. More generally, before building against any installed `@keboola/*` package, read that package's `node_modules/@keboola/<name>/AGENTS.md` when present.
|
|
13
22
|
|
|
14
23
|
## Install
|
|
15
24
|
|
package/dist/index.cjs
CHANGED
|
@@ -10331,6 +10331,29 @@ var brandToCssVars = (brand, resolvedMode) => {
|
|
|
10331
10331
|
vars["--color-primary-foreground"] = colors8.primaryForeground;
|
|
10332
10332
|
vars["--color-destructive"] = colors8.destructive;
|
|
10333
10333
|
vars["--color-destructive-foreground"] = colors8.destructiveForeground;
|
|
10334
|
+
if (colors8.accent !== void 0) vars["--color-accent"] = colors8.accent;
|
|
10335
|
+
if (colors8.accentForeground !== void 0)
|
|
10336
|
+
vars["--color-accent-foreground"] = colors8.accentForeground;
|
|
10337
|
+
}
|
|
10338
|
+
const sidebar = resolvedMode === "dark" ? brand.sidebarColorsDark : brand.sidebarColors;
|
|
10339
|
+
if (sidebar) {
|
|
10340
|
+
const sidebarVars = {
|
|
10341
|
+
"--color-sidebar": sidebar.sidebar,
|
|
10342
|
+
"--color-sidebar-foreground": sidebar.sidebarForeground,
|
|
10343
|
+
"--color-sidebar-primary": sidebar.sidebarPrimary,
|
|
10344
|
+
"--color-sidebar-primary-foreground": sidebar.sidebarPrimaryForeground,
|
|
10345
|
+
"--color-sidebar-accent": sidebar.sidebarAccent,
|
|
10346
|
+
"--color-sidebar-accent-foreground": sidebar.sidebarAccentForeground,
|
|
10347
|
+
"--color-sidebar-border": sidebar.sidebarBorder,
|
|
10348
|
+
"--color-sidebar-ring": sidebar.sidebarRing
|
|
10349
|
+
};
|
|
10350
|
+
for (const [name, value] of Object.entries(sidebarVars)) {
|
|
10351
|
+
if (value !== void 0) vars[name] = value;
|
|
10352
|
+
}
|
|
10353
|
+
}
|
|
10354
|
+
const fontFamily = brand.typography?.fontFamily?.trim();
|
|
10355
|
+
if (fontFamily) {
|
|
10356
|
+
vars["--font-sans"] = fontFamily;
|
|
10334
10357
|
}
|
|
10335
10358
|
if (brand.radii) {
|
|
10336
10359
|
vars["--radius-sm"] = brand.radii.sm;
|
|
@@ -10418,7 +10441,7 @@ var useTheme = () => {
|
|
|
10418
10441
|
const context = react.use(ThemeContext);
|
|
10419
10442
|
if (context === null) {
|
|
10420
10443
|
throw new Error(
|
|
10421
|
-
"useTheme must be used within a <ThemeProvider>. Wrap your app root with <ThemeProvider
|
|
10444
|
+
"useTheme must be used within a <ThemeProvider>. Wrap your app root with <ThemeProvider> from @keboola/design."
|
|
10422
10445
|
);
|
|
10423
10446
|
}
|
|
10424
10447
|
return context;
|
|
@@ -10427,7 +10450,7 @@ var useColorScheme = () => {
|
|
|
10427
10450
|
const context = react.use(ThemeContext);
|
|
10428
10451
|
if (context === null) {
|
|
10429
10452
|
throw new Error(
|
|
10430
|
-
"useColorScheme must be used within a <ThemeProvider>. Wrap your app root with <ThemeProvider
|
|
10453
|
+
"useColorScheme must be used within a <ThemeProvider>. Wrap your app root with <ThemeProvider> from @keboola/design."
|
|
10431
10454
|
);
|
|
10432
10455
|
}
|
|
10433
10456
|
return { colorScheme: context.colorScheme, resolvedMode: context.resolvedMode };
|