create-bestax 4.0.1 → 4.0.2
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/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +17 -0
- package/package.json +1 -1
- package/templates/skills/bestax-form/SKILL.md +49 -19
- package/templates/skills/bestax-form/references/api.md +10 -10
- package/templates/skills/bestax-layout-scaffold/SKILL.md +41 -12
- package/templates/skills/bestax-layout-scaffold/references/layout-components.md +5 -5
- package/templates/skills/bestax-theming/references/css-variables.md +21 -0
- package/templates/skills/bestax-theming/references/themeable-components.md +47 -41
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,SAAS,EAAE,QAAQ,EAG/B,CAAC;AAEF,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AACpD,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,kBAAkB,QAAsB,CAAC;AAEtD,eAAO,MAAM,QAAQ;;;;;;;wCAaQ,MAAM;uCAEP,MAAM;sCACP,MAAM;4CAEA,MAAM;;;;;CAM7B,CAAC;AASX,eAAO,MAAM,WAAW,QAed,CAAC;AAEX,eAAO,MAAM,OAAO;;;;;;CAOV,CAAC;AAOX,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAK9D,CAAC;AAKF,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,SAAS,GACpB,aAAa,MAAM,EACnB,8BAA8B,eAAe,KAC5C,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,SAAS,EAAE,QAAQ,EAG/B,CAAC;AAEF,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AACpD,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,kBAAkB,QAAsB,CAAC;AAEtD,eAAO,MAAM,QAAQ;;;;;;;wCAaQ,MAAM;uCAEP,MAAM;sCACP,MAAM;4CAEA,MAAM;;;;;CAM7B,CAAC;AASX,eAAO,MAAM,WAAW,QAed,CAAC;AAEX,eAAO,MAAM,OAAO;;;;;;CAOV,CAAC;AAOX,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAK9D,CAAC;AAKF,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,SAAS,GACpB,aAAa,MAAM,EACnB,8BAA8B,eAAe,KAC5C,MAkIF,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IAIrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,cAAc,EAAE,WAAW,EA6CvC,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,eAAO,MAAM,aAAa,EAAE,WAAW,EA4CtC,CAAC"}
|
package/dist/constants.js
CHANGED
|
@@ -129,6 +129,7 @@ cases. Before writing \`style\`, translate each declaration with this table:
|
|
|
129
129
|
and \`Tabs.Tab\` has built-in \`icon\`/\`disabled\` props — no nested \`Icon\` needed.
|
|
130
130
|
- Compose existing components before writing custom CSS; theme via \`Theme\` and \`--bulma-*\`
|
|
131
131
|
variables, never hardcoded colors.
|
|
132
|
+
|
|
132
133
|
- \`Navbar.Burger\`/\`Navbar.Menu\` are controlled — wire \`active\` via state on both, and pair
|
|
133
134
|
\`Navbar fixed="top"\` with the \`has-navbar-fixed-top\` class on \`<html>\` (never an inline
|
|
134
135
|
padding offset).
|
|
@@ -144,6 +145,22 @@ cases. Before writing \`style\`, translate each declaration with this table:
|
|
|
144
145
|
(\`pnpm-lock.yaml\` → pnpm, \`package-lock.json\` → npm, \`yarn.lock\` → yarn) — a mismatched
|
|
145
146
|
install fails or forks the lockfile.
|
|
146
147
|
|
|
148
|
+
### Three components Bulma will talk you out of
|
|
149
|
+
|
|
150
|
+
Everything else here gets found because Bulma has no equivalent; these three have a near-miss
|
|
151
|
+
close enough to end the search.
|
|
152
|
+
|
|
153
|
+
- **Confirmation after an action** — \`Toast\`, not \`Notification\`/\`Message\`. Mount
|
|
154
|
+
\`<ToastContainer position="top-right" />\` once at the root, then \`toast.success('Saved')\`.
|
|
155
|
+
- **A confirm or alert** — \`Dialog\`, not \`Modal\`. Mount \`<DialogContainer />\`, then
|
|
156
|
+
\`if (await dialog.confirm({ title, message })) …\`.
|
|
157
|
+
- **A control that reads as text or a link** — \`LinkButton\`
|
|
158
|
+
(\`variant="text" \\| "ghost" \\| "underline"\`), not \`<a href="#">\`, \`<div onClick>\` or
|
|
159
|
+
\`Button color="text"\`.
|
|
160
|
+
|
|
161
|
+
Mounting a container without ever calling \`toast.*\`/\`dialog.*\` does nothing. Both also work
|
|
162
|
+
as controlled components (\`<Toast message … onClose>\`, \`<Dialog isOpen … onConfirm>\`).
|
|
163
|
+
|
|
147
164
|
## AI skills
|
|
148
165
|
|
|
149
166
|
\`.claude/skills/\` contains Agent Skills that teach Claude how to build with this library. They load
|
package/package.json
CHANGED
|
@@ -100,18 +100,18 @@ All import from `@allxsmith/bestax-bulma`. Convenience components auto-wrap Fiel
|
|
|
100
100
|
|
|
101
101
|
Across the convenience inputs (`Input`, `Select`, `TextArea`, and similar):
|
|
102
102
|
|
|
103
|
-
| Prop | Type | Purpose
|
|
104
|
-
| -------------------------------- | --------------------------------------------------------------------- |
|
|
105
|
-
| `color` | `'primary' \| 'link' \| 'info' \| 'success' \| 'warning' \| 'danger'` | Visual state — use `'danger'` for errors, `'success'` for valid.
|
|
106
|
-
| `size` | `'small' \| 'medium' \| 'large'` | Input size.
|
|
107
|
-
| `value` / `onChange` | controlled value + handler | Standard React controlled inputs.
|
|
108
|
-
| `defaultValue` | uncontrolled initial value | When not controlling state.
|
|
109
|
-
| `disabled`, `readOnly` | `boolean` | Native states (`readOnly` on `*Base`).
|
|
110
|
-
| `label` | `ReactNode` | Field label (convenience components).
|
|
111
|
-
| `message` | `ReactNode` | Help / validation text rendered as `<p class="help">`.
|
|
112
|
-
| `messageColor` | a Bulma color | Colors the help text (`'danger'` for errors).
|
|
113
|
-
| `iconLeftName` / `iconRightName` | `string` | Icon shortcuts; pair with `hasIconsLeft/Right`.
|
|
114
|
-
| `isLoading` | `boolean` | Loading indicator on the Control.
|
|
103
|
+
| Prop | Type | Purpose |
|
|
104
|
+
| -------------------------------- | --------------------------------------------------------------------- | -------------------------------------------------------------------- |
|
|
105
|
+
| `color` | `'primary' \| 'link' \| 'info' \| 'success' \| 'warning' \| 'danger'` | Visual state — use `'danger'` for errors, `'success'` for valid. |
|
|
106
|
+
| `size` | `'small' \| 'medium' \| 'large'` | Input size. |
|
|
107
|
+
| `value` / `onChange` | controlled value + handler | Standard React controlled inputs. |
|
|
108
|
+
| `defaultValue` | uncontrolled initial value | When not controlling state. |
|
|
109
|
+
| `disabled`, `readOnly` | `boolean` | Native states (`readOnly` on `*Base`). |
|
|
110
|
+
| `label` | `ReactNode` | Field label (convenience components; auto-associated via `htmlFor`). |
|
|
111
|
+
| `message` | `ReactNode` | Help / validation text rendered as `<p class="help">`. |
|
|
112
|
+
| `messageColor` | a Bulma color | Colors the help text (`'danger'` for errors). |
|
|
113
|
+
| `iconLeftName` / `iconRightName` | `string` | Icon shortcuts; pair with `hasIconsLeft/Right`. |
|
|
114
|
+
| `isLoading` | `boolean` | Loading indicator on the Control. |
|
|
115
115
|
|
|
116
116
|
Plus the full Bulma **helper props** (`m`, `p`, `textColor`, `display`, …) on every component
|
|
117
117
|
via `useBulmaClasses`.
|
|
@@ -119,9 +119,19 @@ via `useBulmaClasses`.
|
|
|
119
119
|
⚠️ Full-width casing is inconsistent across the library: `Select`, `File`, and `Table` take
|
|
120
120
|
`isFullwidth` (lowercase w); `Button` alone takes `isFullWidth`; `Tabs` takes bare `fullwidth`.
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
The `label` prop on the single-control convenience inputs (`Input`, `Select`, `TextArea`,
|
|
123
|
+
`File`, `Numberinput`, `Slider`, `DateInput`, `TimeInput`, `DateTimeInput`, `Autocomplete`,
|
|
124
|
+
`Taginput`) wires `htmlFor`/`id` automatically — your `id` is used when provided, a
|
|
125
|
+
generated one otherwise, and an explicit `labelProps={{ htmlFor }}` wins. The wiring only
|
|
126
|
+
happens when the component renders its own `Field` (nested inside one, the `label` prop is
|
|
127
|
+
dropped); the date/time pickers skip it in `inline` mode and `Taginput` skips it at
|
|
128
|
+
`maxTags` (no visible input to label). The group inputs (`Checkboxes`, `Radios`, `Rate`)
|
|
129
|
+
associate their `label` too, but group-style: the wrapper gets `role="group"`/`"radiogroup"`
|
|
130
|
+
and `aria-labelledby` pointing at the label. Composing `Field` + bases yourself also
|
|
131
|
+
associates: `Field`'s own `label` wires to a single composed `InputBase`/`SelectBase`/
|
|
132
|
+
`TextAreaBase` (skipped for `grouped`/`hasAddons`). Pass `labelProps={{ htmlFor }}` plus a
|
|
133
|
+
matching `id` only when you want a stable id, or `labelProps={{ htmlFor: undefined }}` to
|
|
134
|
+
opt out — e.g. when the labeled `Field` wraps something that is not one of those bases.
|
|
125
135
|
|
|
126
136
|
## Convenience vs composed
|
|
127
137
|
|
|
@@ -168,8 +178,6 @@ function SignupForm() {
|
|
|
168
178
|
message={error}
|
|
169
179
|
messageColor={error ? 'danger' : undefined}
|
|
170
180
|
iconLeftName="envelope"
|
|
171
|
-
id="signup-email"
|
|
172
|
-
labelProps={{ htmlFor: 'signup-email' }}
|
|
173
181
|
/>
|
|
174
182
|
<Button color="primary" type="submit" mt="3">
|
|
175
183
|
Sign up
|
|
@@ -199,6 +207,23 @@ inventory above). **Compose these; don't hand-roll raw `<input class="input">` m
|
|
|
199
207
|
reinvent a control.** If you think a control is missing, check `bulma-ui/src/index.ts` and
|
|
200
208
|
`docs/docs/api/form/` first — it's probably already there under a different name.
|
|
201
209
|
|
|
210
|
+
## What happens after submit
|
|
211
|
+
|
|
212
|
+
A form is not finished at the last field. The two components that carry the result are easy to
|
|
213
|
+
miss because Bulma has something that looks close:
|
|
214
|
+
|
|
215
|
+
- **Confirmation** — `Toast`, not `Notification`/`Message`. Mount
|
|
216
|
+
`<ToastContainer position="top-right" />` once at the app root, then call
|
|
217
|
+
`toast.success('Demo booked')` from the submit handler (`.danger` for a failed submit). It
|
|
218
|
+
self-dismisses; a `Notification` is a static element you place and tear down yourself.
|
|
219
|
+
- **"Are you sure?"** — `Dialog`, not `Modal`. Mount `<DialogContainer />` at the root, then
|
|
220
|
+
`if (await dialog.confirm({ title: 'Delete this key?', message: '…', type: 'danger' })) …`.
|
|
221
|
+
It resolves to a boolean, so a destructive action stays one `if` rather than a state machine.
|
|
222
|
+
`Modal` is an empty shell — with it you rebuild the title, message and button row by hand.
|
|
223
|
+
|
|
224
|
+
Both also work as plain controlled components (`<Toast message … onClose>`,
|
|
225
|
+
`<Dialog isOpen … onConfirm onCancel>`) when the state should live in your component.
|
|
226
|
+
|
|
202
227
|
## Visually inspect it in a browser
|
|
203
228
|
|
|
204
229
|
Forms have layout, spacing, and _stateful_ behavior that types and unit tests don't cover.
|
|
@@ -213,12 +238,17 @@ for the expected classes/states, and say plainly that the visual pass is still o
|
|
|
213
238
|
## Checklist
|
|
214
239
|
|
|
215
240
|
- [ ] Built from the shipped form components (no hand-rolled inputs / reinvented controls).
|
|
216
|
-
- [ ] Every label is programmatically associated
|
|
217
|
-
`
|
|
241
|
+
- [ ] Every label is programmatically associated — the convenience `label` prop, the group
|
|
242
|
+
inputs, and `Field` + single-base composition all do this automatically; pass
|
|
243
|
+
`labelProps={{ htmlFor }}` plus a matching `id` only for a stable id, and label a
|
|
244
|
+
multi-control `Field`'s controls individually (`aria-label`, `aria-labelledby`, or
|
|
245
|
+
a `<label htmlFor>` matching each control's `id`).
|
|
218
246
|
- [ ] Controlled inputs have both `value` and `onChange` (or use `defaultValue` uncontrolled).
|
|
219
247
|
- [ ] Error state shows via `color="danger"` + `message` + `messageColor="danger"`.
|
|
220
248
|
- [ ] Grouped/addon layouts use explicit `Field` + `Control` composition.
|
|
221
249
|
- [ ] No assumption of a built-in validation/form library — state is owned by the app.
|
|
250
|
+
- [ ] Submit feedback is a `Toast` and any "are you sure?" is a `Dialog` — not a hand-placed
|
|
251
|
+
`Notification` or a `Modal` you filled in yourself.
|
|
222
252
|
- [ ] **Rendered and visually inspected in a browser** — layout and the error/validation states
|
|
223
253
|
look right, not just green tests. No browser available? The `renderToString` fallback above
|
|
224
254
|
counts only if you grepped the emitted classes/states **and** said the visual pass is owed.
|
|
@@ -8,16 +8,16 @@ via `useBulmaClasses`.
|
|
|
8
8
|
|
|
9
9
|
Container and layout. Compound parts: `Field.Label`, `Field.Body`.
|
|
10
10
|
|
|
11
|
-
| Prop | Type | Notes
|
|
12
|
-
| ----------------------- | ------------------------------------------------- |
|
|
13
|
-
| `horizontal` | `boolean` | Label + control side by side. Auto-wraps children in `Field.Body`.
|
|
14
|
-
| `grouped` | `boolean \| 'centered' \| 'right' \| 'multiline'` | Controls in a row.
|
|
15
|
-
| `hasAddons` | `boolean \| 'centered' \| 'right'` | Attached controls.
|
|
16
|
-
| `narrow` | `boolean` | Constrain to content width (inside horizontal bodies).
|
|
17
|
-
| `label` | `ReactNode` | Convenience label.
|
|
18
|
-
| `labelSize` | `'small' \| 'normal' \| 'medium' \| 'large'` | Label size.
|
|
19
|
-
| `labelProps` | label attributes | Props for the `<label
|
|
20
|
-
| `textColor` / `bgColor` | Bulma color | Helper colors for the field.
|
|
11
|
+
| Prop | Type | Notes |
|
|
12
|
+
| ----------------------- | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
13
|
+
| `horizontal` | `boolean` | Label + control side by side. Auto-wraps children in `Field.Body`. |
|
|
14
|
+
| `grouped` | `boolean \| 'centered' \| 'right' \| 'multiline'` | Controls in a row. |
|
|
15
|
+
| `hasAddons` | `boolean \| 'centered' \| 'right'` | Attached controls. |
|
|
16
|
+
| `narrow` | `boolean` | Constrain to content width (inside horizontal bodies). |
|
|
17
|
+
| `label` | `ReactNode` | Convenience label; auto-associates with a single composed `InputBase`/`SelectBase`/`TextAreaBase` (skipped for `grouped`/`hasAddons`). |
|
|
18
|
+
| `labelSize` | `'small' \| 'normal' \| 'medium' \| 'large'` | Label size. |
|
|
19
|
+
| `labelProps` | label attributes | Props for the `<label>`. An explicit `htmlFor` (even `undefined`) takes over the association; otherwise it is set automatically. |
|
|
20
|
+
| `textColor` / `bgColor` | Bulma color | Helper colors for the field. |
|
|
21
21
|
|
|
22
22
|
## Control — `form/Control.tsx`
|
|
23
23
|
|
|
@@ -70,11 +70,12 @@ Centered; a collection of items → Card grid. For mixed requests, pick the domi
|
|
|
70
70
|
`textWeight`, `textSize` directly (their `color` prop colors the cell; for muted cell text
|
|
71
71
|
wrap content in `Span textColor="grey"`). Set the app-wide icon library once with
|
|
72
72
|
`<ConfigProvider iconLibrary="…">` at the root rather than `library` on every `<Icon>`.
|
|
73
|
-
- **Decorative CSS is budgeted:
|
|
73
|
+
- **Decorative CSS is budgeted: three compact rules, ≤13 lines per app — comments count:
|
|
74
74
|
at most one short inline note, never a file-header comment block — every value derived
|
|
75
|
-
from `--bulma-*`.** A marketing page gets at most one hero wash
|
|
76
|
-
band, applied via `className` — no resets (Bulma ships one;
|
|
77
|
-
zero) and no grid textures, masks, or multi-layer backdrops;
|
|
75
|
+
from `--bulma-*`.** A marketing page gets at most one hero wash, one alternating section
|
|
76
|
+
band, and one featured-card ring, applied via `className` — no resets (Bulma ships one;
|
|
77
|
+
body/list margins are already zero) and no grid textures, masks, or multi-layer backdrops;
|
|
78
|
+
the components carry the design:
|
|
78
79
|
|
|
79
80
|
```css
|
|
80
81
|
.hero-wash {
|
|
@@ -87,14 +88,19 @@ Centered; a collection of items → Card grid. For mixed requests, pick the domi
|
|
|
87
88
|
.section-alt {
|
|
88
89
|
background: var(--bulma-scheme-main-bis); /* next band: -ter */
|
|
89
90
|
}
|
|
91
|
+
.featured-ring {
|
|
92
|
+
--bulma-shadow: 0 0 0 2px var(--bulma-primary);
|
|
93
|
+
}
|
|
90
94
|
```
|
|
91
95
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
`--bulma-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
The ring works by overriding the **upstream token**, not the component's own var: `.card`
|
|
97
|
+
and `.box` re-declare `--bulma-card-shadow`/`--bulma-box-shadow` from `--bulma-shadow` on
|
|
98
|
+
their own selector, so setting _those_ from an ancestor never wins (same for
|
|
99
|
+
`--bulma-box-radius`; `--bulma-card-radius` is a literal with no ancestor route at all).
|
|
100
|
+
It has to be a CSS rule rather than `<Theme bulmaVars={{ '--bulma-shadow': … }}>`, because
|
|
101
|
+
`bulmaVars` is a closed typed record and `--bulma-shadow` is not one of its keys — that
|
|
102
|
+
exact call **does not compile**, and it was the single most repeated invention across this
|
|
103
|
+
library's cold-start evals. Either way the subtree stays theme- and dark-mode-aware.
|
|
98
104
|
|
|
99
105
|
- **CTAs on a colored hero must stay legible in both schemes.** On a fixed-color surface
|
|
100
106
|
(`Hero color="primary"`, a dark banner), use **filled** buttons — `color="light"` or
|
|
@@ -104,6 +110,26 @@ Centered; a collection of items → Card grid. For mixed requests, pick the domi
|
|
|
104
110
|
`<Theme isRoot colorMode="light">` — so a visitor's OS dark mode can't flip Bulma's text
|
|
105
111
|
colors out from under the fixed palette (details: the `bestax-theming` skill's contrast rules).
|
|
106
112
|
|
|
113
|
+
## Three components core Bulma will talk you out of
|
|
114
|
+
|
|
115
|
+
Most of this library's additions get found on their own, because nothing in Bulma does the
|
|
116
|
+
job. These three do not: each has a Bulma near-miss close enough to stop the search. Across
|
|
117
|
+
44 cold-start builds, `Dialog` was used **zero** times and `LinkButton` in two thirds — and
|
|
118
|
+
every miss shipped the "not this" column instead.
|
|
119
|
+
|
|
120
|
+
| You need | Use | Not this |
|
|
121
|
+
| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
122
|
+
| A brief confirmation after an action, self-dismissing | `Toast` — mount `<ToastContainer position="top-right" />` once at the app root, then `toast.success('Saved')` (also `.danger`/`.warning`/`.info`) from anywhere | `Notification`/`Message` — static page elements you have to place, position and dismiss yourself |
|
|
123
|
+
| A confirm or alert the user must answer before anything | `Dialog` — mount `<DialogContainer />` at the root, then `if (await dialog.confirm({ title, message })) …` | `Modal` — an empty shell; the title, message, button row and confirm/cancel wiring are all yours to rebuild |
|
|
124
|
+
| A control that reads as text or a link but _does_ something | `LinkButton` (`variant="text" \| "ghost" \| "underline"`, optional `color`) | `<a href="#">`/`<div onClick>` (no keyboard or screen-reader support) or `Button color="text"` (still button-shaped) |
|
|
125
|
+
|
|
126
|
+
Mounting a container without ever calling `toast.*`/`dialog.*` is not usage — the container is
|
|
127
|
+
the mount point, the imperative call is the thing that shows something. Both also work as
|
|
128
|
+
ordinary controlled components when you would rather hold the state yourself —
|
|
129
|
+
`<Toast message … duration onClose>`, `<Dialog isOpen title message type onConfirm onCancel>` —
|
|
130
|
+
but in an app with more than one call site the root container plus the imperative helper is
|
|
131
|
+
less wiring, not more.
|
|
132
|
+
|
|
107
133
|
## Inline style → helper prop mapping
|
|
108
134
|
|
|
109
135
|
Look up the declaration you were about to inline. The spacing, typography, and flex helpers
|
|
@@ -157,11 +183,14 @@ inline `style`.
|
|
|
157
183
|
- [ ] Wire `active` state to **both** `Navbar.Burger` and `Navbar.Menu` (they are controlled).
|
|
158
184
|
- [ ] For a fixed navbar, add `has-navbar-fixed-top` to `<html>`.
|
|
159
185
|
- [ ] Do not use `Tile` — it is not shipped.
|
|
186
|
+
- [ ] Action feedback goes through `Toast`, a confirmation through `Dialog`, a text-styled
|
|
187
|
+
action through `LinkButton` — not `Notification`, `Modal` or a bare `<a>`.
|
|
160
188
|
- [ ] Style with helper props, not inline `style` — translate via the mapping table; values
|
|
161
189
|
with no helper get a named class in the stylesheet, never `style={{}}`. No raw Bulma
|
|
162
190
|
`className`s either (`Span`/`Paragraph` wrap bare text; `Th`/`Td` take `textAlign`/`textWeight`).
|
|
163
|
-
- [ ] Decorative CSS ≤
|
|
164
|
-
|
|
191
|
+
- [ ] Decorative CSS ≤13 lines total incl. comments — no file-header comment (hero wash +
|
|
192
|
+
section band + featured-card ring), `--bulma-*`-derived; no resets — Bulma ships one.
|
|
193
|
+
The ring sets `--bulma-shadow` in a CSS rule; `Theme bulmaVars` has no such key.
|
|
165
194
|
- [ ] Set the icon library once via `<ConfigProvider iconLibrary="…">` at the root.
|
|
166
195
|
- [ ] Site built? ~800 KB raw / ~82 KB gzip CSS is the expected default-flavor size — to shrink
|
|
167
196
|
it, run the `bestax-optimize` skill (measure first).
|
|
@@ -58,11 +58,11 @@ Every component also accepts the shared Bulma helper props (`m`/`p` spacing, `te
|
|
|
58
58
|
|
|
59
59
|
`<Hero>` is a full-width banner. Subcomponents: `Hero.Head`, `Hero.Body`, `Hero.Foot`.
|
|
60
60
|
|
|
61
|
-
| Prop | Type
|
|
62
|
-
| ---------------------- |
|
|
63
|
-
| `color` |
|
|
64
|
-
| `size` | `'small' \| 'medium' \| 'large' \| 'fullheight' \| 'fullheight-with-navbar'`
|
|
65
|
-
| `fullheightWithNavbar` | `boolean`
|
|
61
|
+
| Prop | Type |
|
|
62
|
+
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
63
|
+
| `color` | `primary \| link \| info \| success \| warning \| danger \| black \| white \| light \| dark` (CSS-backed). Also accepted but deprecated, no CSS, dev-warn: `black-bis`, `black-ter`, the greys, `inherit`, `current` |
|
|
64
|
+
| `size` | `'small' \| 'medium' \| 'large' \| 'fullheight' \| 'fullheight-with-navbar'` |
|
|
65
|
+
| `fullheightWithNavbar` | `boolean` |
|
|
66
66
|
|
|
67
67
|
```tsx
|
|
68
68
|
<Hero color="primary" size="medium">
|
|
@@ -100,6 +100,27 @@ and numeric shades `--bulma-<c>-00` … `--bulma-<c>-95`.
|
|
|
100
100
|
| `--bulma-size-small` / `-normal` / `-medium` / `-large` | 0.75 / 1 / 1.25 / 1.5rem | via `bulmaVars` |
|
|
101
101
|
| `--bulma-weight-light/normal/medium/semibold/bold/extrabold` | 300 / 400 / 500 / 600 / 700 / 800 | via `bulmaVars` |
|
|
102
102
|
|
|
103
|
+
## Shadow — the one token `bulmaVars` cannot set
|
|
104
|
+
|
|
105
|
+
`--bulma-shadow` is a real Bulma variable (`.box` and `.card` both derive
|
|
106
|
+
`--bulma-box-shadow`/`--bulma-card-shadow` from it), but it is **not a key of `bulmaVars`** —
|
|
107
|
+
that record is a closed union built from an explicit list, and shadow was left out. Writing
|
|
108
|
+
`<Theme bulmaVars={{ '--bulma-shadow': … }}>` is a compile error, and it is the single most
|
|
109
|
+
repeated invention in this library's cold-start evals: every run on every guidance channel
|
|
110
|
+
tried it.
|
|
111
|
+
|
|
112
|
+
Set it in CSS instead, then apply the class to the one element that needs it:
|
|
113
|
+
|
|
114
|
+
```css
|
|
115
|
+
.featured-ring {
|
|
116
|
+
--bulma-shadow: 0 0 0 2px var(--bulma-primary);
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Do **not** reach for `--bulma-box-shadow`/`--bulma-card-shadow` from an ancestor instead —
|
|
121
|
+
those are re-declared on `.box`/`.card` themselves, so an inherited value always loses (the
|
|
122
|
+
same rule as the extras section below).
|
|
123
|
+
|
|
103
124
|
## Extras component variables
|
|
104
125
|
|
|
105
126
|
Every "Beyond Bulma" extra registers its own `--bulma-<component>-*` variables. They are
|
|
@@ -10,9 +10,14 @@ This is the self-contained inventory of the color/size/variant props that matter
|
|
|
10
10
|
values are component-specific (see the table). Example: `<Button color="primary">` → `is-primary`.
|
|
11
11
|
⚠️ Some unions are **typed wider than the CSS Bulma ships** — the class is emitted but no rule
|
|
12
12
|
matches. No component ships `is-grey*`/`is-*-bis`/`is-*-ter` rules at all: those `validColors`
|
|
13
|
-
members typecheck on `Progress`/`Notification`/`Hero` but style nothing
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
members still typecheck on `Progress`/`Notification`/`Hero` but style nothing. They are
|
|
14
|
+
**deprecated**: passing one logs a console warning in development, and they will be removed
|
|
15
|
+
from those unions in the next major (the `has-text-*`/`has-background-*` **helpers** do cover
|
|
16
|
+
all 17). On the `Hero` root, `inherit` and `current` are equally CSS-less and deprecated
|
|
17
|
+
(its `Head`/`Body`/`Foot` sub-components keep them, as text helpers). `Pagination` and
|
|
18
|
+
`Tabs` ship no color CSS for **any** value — their entire `color`
|
|
19
|
+
prop is deprecated. Before relying on an unusual value, grep the shipped CSS:
|
|
20
|
+
`node_modules/@allxsmith/bestax-bulma/dist/bestax.css` for e.g. `.progress.is-grey`.
|
|
16
21
|
2. **Helper color props** (on most components, applied as utility classes):
|
|
17
22
|
- `color` / `textColor` → `has-text-<color>` (text color)
|
|
18
23
|
- `backgroundColor` / `bgColor` → `has-background-<color>` (background)
|
|
@@ -21,7 +26,8 @@ This is the self-contained inventory of the color/size/variant props that matter
|
|
|
21
26
|
Components with a real `is-<color>` modifier (`Button`, `Hero`) drop the `color` helper and
|
|
22
27
|
re-expose it as **`textColor`** / **`bgColor`**. `Box`/`Card`/`Section` ship no `is-<color>`
|
|
23
28
|
rule — their `color` _is_ the text helper (`has-text-<color>`; narrowed to the 6 on
|
|
24
|
-
`Box`/`Card`), so `color` and `textColor` are the same lever there
|
|
29
|
+
`Box`/`Card`), so `color` and `textColor` are the same lever there (prefer `textColor`; it
|
|
30
|
+
takes precedence when both are set). `Tag` and `Td`/`Th` have
|
|
25
31
|
**no text-color prop** — wrap content in `<Span textColor="…">`. `Input` has none either and
|
|
26
32
|
the wrapper trick can't work (it renders a native `<input>`; a child can't color its value):
|
|
27
33
|
recolor via the upstream `--bulma-text-strong-l`, since Bulma re-declares `--bulma-input-*` on
|
|
@@ -40,43 +46,43 @@ Shades (`colorShade` / `backgroundColorShade`): `00, 05, 10, … 95, invert, lig
|
|
|
40
46
|
|
|
41
47
|
## Component `color` / `size` props (verbatim unions)
|
|
42
48
|
|
|
43
|
-
| Component | `color` accepts
|
|
44
|
-
| ------------------ |
|
|
45
|
-
| `Button` | `primary \| link \| info \| success \| warning \| danger \| white \| light \| dark \| black \| text \| ghost`
|
|
46
|
-
| `Notification` | the 17 `validColors` (greys
|
|
47
|
-
| `Tag` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white`
|
|
48
|
-
| `Box` | `primary \| link \| info \| success \| warning \| danger`
|
|
49
|
-
| `Message` | `primary \| link \| info \| success \| warning \| danger`
|
|
50
|
-
| `Input` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white`
|
|
51
|
-
| `Avatar` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white`
|
|
52
|
-
| `Badge` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white`
|
|
53
|
-
| `Title` | — (no `color`; use `textColor`)
|
|
54
|
-
| `SubTitle` | — (no `color`; use `textColor`)
|
|
55
|
-
| `Autocomplete` | `primary \| link \| info \| success \| warning \| danger`
|
|
56
|
-
| `Checkbox` | `primary \| link \| info \| success \| warning \| danger`
|
|
57
|
-
| `DateInput` | `primary \| link \| info \| success \| warning \| danger`
|
|
58
|
-
| `DateTimeInput` | `primary \| link \| info \| success \| warning \| danger`
|
|
59
|
-
| `File` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white`
|
|
60
|
-
| `Hero` | the 17 `validColors` (greys
|
|
61
|
-
| `LinkButton` | `primary \| link \| info \| success \| warning \| danger \| white \| light \| dark \| black`
|
|
62
|
-
| `Loading` | `primary \| link \| info \| success \| warning \| danger`
|
|
63
|
-
| `Navbar` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white`
|
|
64
|
-
| `Numberinput` | `primary \| link \| info \| success \| warning \| danger \| light \| dark`
|
|
65
|
-
| `Pagination` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white`
|
|
66
|
-
| `Panel` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white`
|
|
67
|
-
| `Progress` | the 17 `validColors` (greys
|
|
68
|
-
| `Radio` | `primary \| link \| info \| success \| warning \| danger`
|
|
69
|
-
| `Rate` | `primary \| link \| info \| success \| warning \| danger`
|
|
70
|
-
| `Select` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white`
|
|
71
|
-
| `Slider` | `primary \| link \| info \| success \| warning \| danger`
|
|
72
|
-
| `Steps` | `primary \| link \| info \| success \| warning \| danger`
|
|
73
|
-
| `Switch` | `primary \| link \| info \| success \| warning \| danger`
|
|
74
|
-
| `Tabs` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white`
|
|
75
|
-
| `Taginput` | `primary \| link \| info \| success \| warning \| danger`
|
|
76
|
-
| `TextArea` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white`
|
|
77
|
-
| `TimeInput` | `primary \| link \| info \| success \| warning \| danger`
|
|
78
|
-
| `Tooltip` | `primary \| link \| info \| success \| warning \| danger \| dark \| light`
|
|
79
|
-
| `Tr` / `Td` / `Th` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white`
|
|
49
|
+
| Component | `color` accepts | `size` accepts | Notes |
|
|
50
|
+
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
51
|
+
| `Button` | `primary \| link \| info \| success \| warning \| danger \| white \| light \| dark \| black \| text \| ghost` | `small \| normal \| medium \| large` | adds `text`, `ghost`; also `isLight`, `isOutlined`, `isInverted`, `isRounded` |
|
|
52
|
+
| `Notification` | the 17 `validColors` (`black-bis`, `black-ter`, and greys deprecated: no CSS, dev-warn, removed next major — see ⚠️) | — | also `isLight` |
|
|
53
|
+
| `Tag` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `normal \| medium \| large` | also `isRounded`, `isDelete`, `isHoverable` — **no `isLight`** |
|
|
54
|
+
| `Box` | `primary \| link \| info \| success \| warning \| danger` | — | `color` renders `has-text-<color>`, same as `textColor` (which wins when both are set; no `.box.is-*` ships — tint via `bgColor`); also `hasShadow` |
|
|
55
|
+
| `Message` | `primary \| link \| info \| success \| warning \| danger` | — | the 6 only |
|
|
56
|
+
| `Input` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isRounded`, `isStatic` |
|
|
57
|
+
| `Avatar` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `16x16 \| 24x24 \| 32x32 \| 48x48 \| 64x64 \| 96x96 \| 128x128 \| number` | initials/icon background (auto-derived from `name` when unset); also `shape` |
|
|
58
|
+
| `Badge` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | pill background; default `danger` |
|
|
59
|
+
| `Title` | — (no `color`; use `textColor`) | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | also `isSpaced` |
|
|
60
|
+
| `SubTitle` | — (no `color`; use `textColor`) | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | — |
|
|
61
|
+
| `Autocomplete` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | the 6 only |
|
|
62
|
+
| `Checkbox` | `primary \| link \| info \| success \| warning \| danger` | `small \| normal \| medium \| large` | the 6 only |
|
|
63
|
+
| `DateInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded` |
|
|
64
|
+
| `DateTimeInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded` |
|
|
65
|
+
| `File` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isBoxed`, `isFullwidth` |
|
|
66
|
+
| `Hero` | the 17 `validColors` + `inherit`/`current` (`black-bis`, `black-ter`, greys, `inherit`, `current` deprecated: no CSS, dev-warn, removed next major — see ⚠️) | `small \| medium \| large \| fullheight \| fullheight-with-navbar` | section background |
|
|
67
|
+
| `LinkButton` | `primary \| link \| info \| success \| warning \| danger \| white \| light \| dark \| black` | — | button-styled link; emits `link-button-<color>` — **no `isLight`/`isOutlined`/`isInverted`** |
|
|
68
|
+
| `Loading` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | spinner color; default light grey |
|
|
69
|
+
| `Navbar` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | — |
|
|
70
|
+
| `Numberinput` | `primary \| link \| info \| success \| warning \| danger \| light \| dark` | `small \| medium \| large` | also `inputColor` (the 6) for the inner input |
|
|
71
|
+
| `Pagination` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | **entire `color` prop deprecated** (no CSS ships; dev-warn; removal next major) |
|
|
72
|
+
| `Panel` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | — |
|
|
73
|
+
| `Progress` | the 17 `validColors` (`black-bis`, `black-ter`, and greys deprecated: no CSS, dev-warn, removed next major — see ⚠️) | `small \| medium \| large` | — |
|
|
74
|
+
| `Radio` | `primary \| link \| info \| success \| warning \| danger` | `small \| normal \| medium \| large` | the 6 only |
|
|
75
|
+
| `Rate` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | the 6 only |
|
|
76
|
+
| `Select` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isRounded` |
|
|
77
|
+
| `Slider` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded`, `isCircle` |
|
|
78
|
+
| `Steps` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | the 6 only |
|
|
79
|
+
| `Switch` | `primary \| link \| info \| success \| warning \| danger` | `small \| normal \| medium \| large` | also `isRounded`, `isThin`, `isOutlined` |
|
|
80
|
+
| `Tabs` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | **entire `color` prop deprecated** (no CSS ships; dev-warn; removal next major) |
|
|
81
|
+
| `Taginput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `tagColor` (the 6 + `dark \| light`) for the tags |
|
|
82
|
+
| `TextArea` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isRounded`, `isStatic` |
|
|
83
|
+
| `TimeInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | — |
|
|
84
|
+
| `Tooltip` | `primary \| link \| info \| success \| warning \| danger \| dark \| light` | `small \| medium \| large` | — |
|
|
85
|
+
| `Tr` / `Td` / `Th` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | cell background; cells take `textAlign`/`textWeight`/`textSize` directly |
|
|
80
86
|
|
|
81
87
|
The 6 brand colors (`primary, link, info, success, warning, danger`) are the ones a custom theme
|
|
82
88
|
recolors via the HSL trios (see `css-variables.md`). The greyscale and `white`/`light`/`dark`
|