create-bestax 4.2.11 → 4.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/dist/cli.d.ts +2 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -2
- package/dist/constants.d.ts +7 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +19 -4
- package/dist/file-system.d.ts +7 -0
- package/dist/file-system.d.ts.map +1 -1
- package/dist/file-system.js +15 -0
- package/dist/project-creator.d.ts +21 -1
- package/dist/project-creator.d.ts.map +1 -1
- package/dist/project-creator.js +84 -51
- package/dist/prompts.d.ts +7 -2
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +8 -3
- package/dist/validators.d.ts +7 -0
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +13 -1
- package/package.json +6 -3
- package/templates/skills/bestax-custom-component/SKILL.md +21 -4
- package/templates/skills/bestax-custom-component/examples/stat-card.tsx +1 -2
- package/templates/skills/bestax-custom-component/references/api.md +103 -11
- package/templates/skills/bestax-custom-component/references/component-catalog.md +12 -5
- package/templates/skills/bestax-custom-component/references/library-contributor.md +23 -0
- package/templates/skills/bestax-form/SKILL.md +28 -17
- package/templates/skills/bestax-form/references/api.md +83 -23
- package/templates/skills/bestax-form/references/patterns.md +19 -0
- package/templates/skills/bestax-layout-scaffold/SKILL.md +17 -4
- package/templates/skills/bestax-layout-scaffold/references/layout-components.md +22 -15
- package/templates/skills/bestax-migrate/SKILL.md +32 -14
- package/templates/skills/bestax-migrate/references/bloomer/prop-map.md +9 -9
- package/templates/skills/bestax-migrate/references/bloomer/unmappables.md +19 -2
- package/templates/skills/bestax-migrate/references/bulma-classes/component-map.md +337 -0
- package/templates/skills/bestax-migrate/references/bulma-classes/prop-map.md +230 -0
- package/templates/skills/bestax-migrate/references/bulma-classes/unmappables.md +348 -0
- package/templates/skills/bestax-migrate/references/css-migration.md +8 -1
- package/templates/skills/bestax-migrate/references/rbx/component-map.md +15 -15
- package/templates/skills/bestax-migrate/references/rbx/prop-map.md +17 -19
- package/templates/skills/bestax-migrate/references/rbx/unmappables.md +17 -0
- package/templates/skills/bestax-migrate/references/react-bulma-components/component-map.md +34 -34
- package/templates/skills/bestax-migrate/references/react-bulma-components/unmappables.md +34 -7
- package/templates/skills/bestax-optimize/SKILL.md +3 -2
- package/templates/skills/bestax-optimize/references/modular-build.md +25 -5
- package/templates/skills/bestax-theming/SKILL.md +4 -3
- package/templates/skills/bestax-theming/examples/dark-mode.tsx +4 -3
- package/templates/skills/bestax-theming/references/css-variables.md +49 -8
- package/templates/skills/bestax-theming/references/themeable-components.md +12 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-bestax",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.13",
|
|
4
4
|
"description": "Create a new bestax-bulma project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -39,7 +39,9 @@
|
|
|
39
39
|
"figures": "^6.1.0",
|
|
40
40
|
"fs-extra": "^11.4.0",
|
|
41
41
|
"prompts": "^2.4.2",
|
|
42
|
-
"
|
|
42
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
43
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
44
|
+
"@allxsmith/bestax-bulma": "^5.27.0"
|
|
43
45
|
},
|
|
44
46
|
"devDependencies": {
|
|
45
47
|
"@jest/globals": "^30.0.0",
|
|
@@ -50,6 +52,7 @@
|
|
|
50
52
|
"@types/prompts": "^2.4.9",
|
|
51
53
|
"@types/wait-on": "^5.3.4",
|
|
52
54
|
"jest": "^30.2.0",
|
|
55
|
+
"semver": "^7.8.5",
|
|
53
56
|
"ts-jest": "^29.4.12",
|
|
54
57
|
"typescript": "^6.0.3",
|
|
55
58
|
"wait-on": "^9.1.0"
|
|
@@ -75,5 +78,5 @@
|
|
|
75
78
|
"clean": "rimraf dist",
|
|
76
79
|
"release": "npx semantic-release"
|
|
77
80
|
},
|
|
78
|
-
"readme": "# create-bestax\n\n[](https://www.npmjs.com/package/create-bestax)\n[](https://www.npmjs.com/package/create-bestax)\n[](https://opensource.org/licenses/MIT)\n[](https://socket.dev/npm/package/create-bestax/overview)\n[](https://scorecard.dev/viewer/?uri=github.com/allxsmith/bestax)\n[](https://www.bestpractices.dev/projects/14361)\n[](https://www.npmjs.com/package/create-bestax#provenance)\n[](https://github.com/allxsmith/bestax/blob/main/SECURITY.md)\n\nThe scaffolder for [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma) — spin up a Vite app pre-wired for the **Bulma v1** React component library in one command. Picks your framework (JS or TypeScript), CSS flavor, and icon library, and can drop in the bestax **AI skills** so an agent like Claude Code knows the library from the first prompt.\n\nPart of the [bestax monorepo](https://github.com/allxsmith/bestax) — see also [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma) for the components themselves.\n\n## Requirements\n\n- **Node.js 22 or newer.** Node 18 and 20 are both past end-of-life. On an older runtime the\n CLI exits immediately with an explicit upgrade message.\n- npm 10 or newer (ships with Node 22), or yarn/pnpm.\n\n## Usage\n\n### Quick Start\n\n```bash\n# Using npm\nnpm create bestax@latest my-app\n\n# Using npx\nnpx create-bestax@latest my-app\n\n# Alternative naming\nnpm create bestax-bulma@latest my-app\n```\n\n### Interactive Mode\n\nRunning without arguments will prompt you for all options:\n\n```bash\nnpm create bestax@latest\n```\n\nYou'll be asked to:\n\n1. Enter a project name\n2. Select a framework (Vite or Vite + TypeScript)\n3. Choose a Bulma CSS flavor (Complete or Minimal)\n4. Select an icon library (Font Awesome, Material Icons, etc.)\n5. Choose whether to install the bestax AI skills into `.claude/skills/`\n\nEvery prompt has a flag equivalent, so the whole flow is scriptable and CI-friendly — see the options below.\n\n### Command Line Options\n\n```bash\nnpm create bestax@latest [project-directory] [options]\n```\n\n**Arguments:**\n\n- `[project-directory]` - Optional project directory name
|
|
81
|
+
"readme": "# create-bestax\n\n[](https://www.npmjs.com/package/create-bestax)\n[](https://www.npmjs.com/package/create-bestax)\n[](https://opensource.org/licenses/MIT)\n[](https://socket.dev/npm/package/create-bestax/overview)\n[](https://scorecard.dev/viewer/?uri=github.com/allxsmith/bestax)\n[](https://www.bestpractices.dev/projects/14361)\n[](https://www.npmjs.com/package/create-bestax#provenance)\n[](https://github.com/allxsmith/bestax/blob/main/SECURITY.md)\n\nThe scaffolder for [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma) — spin up a Vite app pre-wired for the **Bulma v1** React component library in one command. Picks your framework (JS or TypeScript), CSS flavor, and icon library, and can drop in the bestax **AI skills** so an agent like Claude Code knows the library from the first prompt.\n\nPart of the [bestax monorepo](https://github.com/allxsmith/bestax) — see also [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma) for the components themselves.\n\n## Requirements\n\n- **Node.js 22 or newer.** Node 18 and 20 are both past end-of-life. On an older runtime the\n CLI exits immediately with an explicit upgrade message.\n- npm 10 or newer (ships with Node 22), or yarn/pnpm.\n\n## Usage\n\n### Quick Start\n\n```bash\n# Using npm\nnpm create bestax@latest my-app\n\n# Using npx\nnpx create-bestax@latest my-app\n\n# Alternative naming\nnpm create bestax-bulma@latest my-app\n```\n\n### Interactive Mode\n\nRunning without arguments will prompt you for all options:\n\n```bash\nnpm create bestax@latest\n```\n\nYou'll be asked to:\n\n1. Enter a project name (and, if that directory already holds files, confirm removing them;\n nothing is removed until you have answered the last question)\n2. Select a framework (Vite or Vite + TypeScript)\n3. Choose a Bulma CSS flavor (Complete or Minimal)\n4. Select an icon library (Font Awesome, Material Icons, etc.)\n5. Choose whether to install the bestax AI skills into `.claude/skills/`\n\nEvery prompt has a flag equivalent, so the whole flow is scriptable and CI-friendly — see the options below.\n\n### Command Line Options\n\n```bash\nnpm create bestax@latest [project-directory] [options]\n```\n\n**Arguments:**\n\n- `[project-directory]` - Optional project directory name. It also becomes the `package.json`\n name, lower-cased the way `npm init` does and without a leading `_`, since npm rejects both.\n\n**Options:**\n\n- `-t, --template <template>` - Template to use: `vite` or `vite-ts` \n **Default:** `vite`\n- `-b, --bulma <flavor>` - Bulma CSS flavor:\n - `complete` - Full Bulma CSS with all components and helpers\n - `prefixed` - Prefixed version for compatibility\n - `no-helpers` - Without helper classes\n - `no-helpers-prefixed` - Prefixed without helpers\n - `no-dark-mode` - Without dark mode support \n **Default:** `complete`\n- `-i, --icon <library>` - Icon library:\n - `none` - No icon library\n - `fontawesome` - Font Awesome\n - `mdi` - Material Design Icons\n - `ionicons` - Ionicons\n - `material-icons` - Material Icons\n - `material-symbols` - Material Symbols \n **Default:** `none`\n- `--skills` / `--no-skills` - Install (or skip) the bestax AI skills into\n `.claude/skills/` (with a `CLAUDE.md`) so a Claude Code session picks them up\n automatically. When omitted you're prompted; with `-y` the default is to install.\n- `-y, --yes` - Skip prompts and use defaults or provided options. \n When used, the following defaults are selected unless overridden by flags:\n - Template: `vite`\n - Bulma flavor: `complete`\n - Icon library: `none`\n - AI skills: installed (pass `--no-skills` to opt out)\n\n `-y` never deletes files. If the target directory is not empty, the run stops, lists what is\n there, and changes nothing; add `--overwrite` to empty it first. Earlier versions emptied the\n directory under `-y` alone, so a script that relied on that now needs `--overwrite`.\n\n- `--overwrite` - Remove existing files if the target directory is not empty, without asking.\n Every other flag is checked first, so a typo stops the run before anything is deleted.\n\n**Example:**\n\n```bash\n# Create a TypeScript project with Font Awesome icons\nnpm create bestax@latest my-app -t vite-ts -i fontawesome -b complete\n\n# Use all defaults (skip prompts)\nnpm create bestax@latest my-app -y\n```\n\n## Templates\n\nAvailable templates:\n\n- `vite` - Vite + JavaScript\n- `vite-ts` - Vite + TypeScript\n\nEach template includes:\n\n- Pre-configured bestax-bulma integration (React 19)\n- The latest `@allxsmith/bestax-bulma`, which ships Bulma v1 automatically\n- Icon library support (Font Awesome, Material Design, etc.)\n- Sample components demonstrating library usage\n- Development and build scripts\n\n## For AI Tools\n\nScaffolding for an AI agent? Pass `--skills` (or accept the prompt) to drop the bestax\nAgent Skills and a `CLAUDE.md` into the new project so Claude Code, Cursor, or Copilot\nbuild the bestax way from the start. The library also ships LLM-optimized docs:\n\n- [LLMs guide](https://bestax.io/docs/guides/llms) — using bestax with Claude Code, Cursor, Copilot\n- [Agent Skills](https://bestax.io/docs/skills/intro) — teach your agent the bestax conventions\n- [llms.txt](https://bestax.io/llms.txt) (curated index) · [llms-full.txt](https://bestax.io/llms-full.txt) (full docs)\n\n## Development\n\n```bash\nnpm run build # Build the CLI\nnpm run dev # Watch mode\nnpm test # Run tests\nnpm run lint # Lint CLI source code\nnpm run typecheck # Type check CLI source code\n```\n\n**Note on Templates:** Template files in `templates/` are excluded from linting. They should be manually validated by scaffolding a test project and running lint/build there before releasing.\n\n## Hardened by default\n\nA scaffolder runs with write access to your filesystem and picks your starting dependencies, so how it is built and published matters:\n\n- **Signed provenance** — every release carries a sigstore attestation linking the tarball to the exact commit and CI run that built it. Check the **Provenance** section on the [npm page](https://www.npmjs.com/package/create-bestax#provenance), or run `npm audit signatures`.\n- **npm OIDC trusted publishing** — short-lived, per-run credentials; no long-lived `NPM_TOKEN` exists to be stolen. Release commits and tags are GPG-signed.\n- **Socket.dev scans every PR** for malware, install scripts, obfuscated code, and privilege escalation before it can reach `main`.\n- **Dependencies are a deliberate act** — install scripts are blocked unless individually allow-listed, freshly published versions are refused for 3 days, and CI installs only what the reviewed lockfile resolves.\n- **Every GitHub Action is pinned to a full commit SHA**, so a compromised action release can't roll silently into a build of this CLI.\n- **CodeQL, Dependency Review, and Dependabot** run continuously, alongside a high-severity `pnpm audit` gate.\n- **Layered AI review before merge** — [CodeRabbit](https://coderabbit.ai) plus an independent adversarial Claude review (a different model from the one writing AI-authored changes), on top of required green CI, an approving review, and a human merge.\n\nFull detail: [`SECURITY.md`](https://github.com/allxsmith/bestax/blob/main/SECURITY.md) · [Security guide](https://bestax.io/docs/guides/security)\n\n## Telemetry\n\n`create-bestax` can send one **anonymous** usage event after a successful\nscaffold — only if you opt in when asked (once, at the end of a scaffold). The\nevent is just the choices you made — template, Bulma flavor, icon library,\nskills, package manager — plus the CLI version, Node major version, and OS\nplatform; never names, IPs, machine IDs, paths, or file contents, and no\nidentifier exists that could link two events together. Opt out any time with\n`--no-telemetry`, `BESTAX_TELEMETRY=0`, or `DO_NOT_TRACK=1`.\n\nFull disclosure of every field and control: [Telemetry guide](https://bestax.io/docs/guides/telemetry)\n\n## Publishing\n\nThis package uses semantic-release with scope-based rules. Only commits with `feat(create-bestax)` or `fix(create-bestax)` will trigger releases.\n"
|
|
79
82
|
}
|
|
@@ -58,6 +58,24 @@ so put helper props on the parent or on an element inside them, never invent the
|
|
|
58
58
|
(`Card.*` sub-parts do take helper props, like `Table.*`/`Menu.*`/`Hero.*`.) Most "custom components" are a composition function — zero new styles.
|
|
59
59
|
See `examples/stat-card.tsx` for a complete worked example.
|
|
60
60
|
|
|
61
|
+
Rendering something only the browser knows (the reader's time zone, a `localStorage` value)?
|
|
62
|
+
Wrap it in the library's `ClientOnly` rather than checking `typeof window`: it renders a fallback
|
|
63
|
+
until the page has hydrated, so the server and client markup match. `references/api.md` has the
|
|
64
|
+
details.
|
|
65
|
+
|
|
66
|
+
A panel opened from a button (a filter form, share options, an inline edit) is `Popover`: use
|
|
67
|
+
it rather than building one. It anchors the panel, moves focus in and back, and closes on
|
|
68
|
+
Escape and outside presses.
|
|
69
|
+
|
|
70
|
+
Building something else that floats (a command palette)? Render it through the library's
|
|
71
|
+
`Portal` rather than `createPortal`: it renders nothing on the server and during hydration, so
|
|
72
|
+
the server and client markup match. `references/api.md` has the details.
|
|
73
|
+
|
|
74
|
+
Building some other overlay that holds focus until it is dismissed (a command palette)? Use the
|
|
75
|
+
library's `useFocusTrap` rather than a hand-rolled Tab handler: it finds the tab stops the
|
|
76
|
+
browser visits and hands focus back on close. `references/api.md` has the signature and a worked
|
|
77
|
+
panel.
|
|
78
|
+
|
|
61
79
|
## The component spine
|
|
62
80
|
|
|
63
81
|
Same shape the library itself uses, with all imports from the package. Every reusable
|
|
@@ -112,10 +130,8 @@ free. `references/api.md` documents the helpers.
|
|
|
112
130
|
## Styling ladder — use the lowest rung that works
|
|
113
131
|
|
|
114
132
|
**Rung 1 — helper props only (default).** House rules: never `style={{}}`. Layout with
|
|
115
|
-
`Block`/`Box` and `display="flex"`, `flexDirection`, `alignItems`, `justifyContent
|
|
116
|
-
|
|
117
|
-
`Columns` take a `gap` prop). Before writing `style={{ … }}` anywhere, translate each
|
|
118
|
-
declaration:
|
|
133
|
+
`Block`/`Box` and `display="flex"`, `flexDirection`, `alignItems`, `justifyContent`, and space
|
|
134
|
+
the children with `gap`. Before writing `style={{ … }}` anywhere, translate each declaration:
|
|
119
135
|
|
|
120
136
|
| Inline style you're about to write | Helper props instead |
|
|
121
137
|
| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -129,6 +145,7 @@ declaration:
|
|
|
129
145
|
| `display: 'flex'` + flex properties | same-named props: `display="flex"`, `flexDirection`, `justifyContent`, `alignItems`, `flexWrap` |
|
|
130
146
|
| `height: '100%'` on a flex child | `flexGrow="1"` |
|
|
131
147
|
| `display: 'none'` | `visibility="hidden"`, or responsive `display*` props (`displayMobile`, `displayTablet`, …) |
|
|
148
|
+
| `gap: '1rem'` (flex or grid) | `gap="2"`, or one axis: `columnGap`, `rowGap`; gap scale: `1`=0.5rem, `2`=1rem, `4`=2rem, half steps (`"1.5"`) |
|
|
132
149
|
|
|
133
150
|
Spacing, typography, and flex helpers are on every component; `textColor`/`bgColor` are on
|
|
134
151
|
the content components you'll compose with (`Box`, `Block`, `Title`, `Content`, `Card`, …) —
|
|
@@ -55,6 +55,7 @@ export function StatCard({
|
|
|
55
55
|
// Rung 1: layout entirely with helper props — no style={{}}, no CSS.
|
|
56
56
|
display="flex"
|
|
57
57
|
alignItems="center"
|
|
58
|
+
gap="2"
|
|
58
59
|
p="4"
|
|
59
60
|
{...rest}
|
|
60
61
|
>
|
|
@@ -63,7 +64,6 @@ export function StatCard({
|
|
|
63
64
|
name={icon}
|
|
64
65
|
size="large"
|
|
65
66
|
textColor={color}
|
|
66
|
-
mr="4"
|
|
67
67
|
// Decorative: the label below already says it, so hide it from AT —
|
|
68
68
|
// Icon otherwise emits its default aria-label="icon". (To *label* an
|
|
69
69
|
// icon, use Icon's own camelCase `ariaLabel`; most components take
|
|
@@ -71,7 +71,6 @@ export function StatCard({
|
|
|
71
71
|
aria-hidden="true"
|
|
72
72
|
/>
|
|
73
73
|
)}
|
|
74
|
-
{/* No `gap` helper exists — space siblings with margin props (mr above). */}
|
|
75
74
|
<div>
|
|
76
75
|
{/* as="p": the sizes are visual scale, not document structure — a bare
|
|
77
76
|
<Title size> renders a heading and breaks the page outline. */}
|
|
@@ -32,14 +32,14 @@ on the root element with `mergeBulmaStyles(bulmaHelperStyles, style)`
|
|
|
32
32
|
`BulmaClassesProps` is the union of all helper prop groups, composed from per-concern hooks
|
|
33
33
|
that can also be used on their own:
|
|
34
34
|
|
|
35
|
-
| Group | Hook | Representative props
|
|
36
|
-
| ---------- | ---------------------- |
|
|
37
|
-
| Color | `useColorClasses` | `color`, `colorShade`, `backgroundColor`, `backgroundColorShade`
|
|
38
|
-
| Spacing | `useSpacingClasses` | `m`, `mt`, `mr`, `mb`, `ml`, `mx`, `my`, `p`, `pt`, `pr`, `pb`, `pl`, `px`, `py`
|
|
39
|
-
| Typography | `useTypographyClasses` | `textSize`, `textAlign`, `textTransform`, `textWeight`, `fontFamily` (+ responsive variants)
|
|
40
|
-
| Visibility | `useVisibilityClasses` | `display`, `visibility` (+ per-viewport variants)
|
|
41
|
-
| Flexbox | `useFlexboxClasses` | `flexDirection`, `flexWrap`, `justifyContent`, `alignItems`, `alignContent`, `alignSelf`, `flexGrow`, `flexShrink`
|
|
42
|
-
| Other | `useOtherClasses` | `float`, `overflow`, `radius`, `shadow`, `interaction`, `cursor`, `skeleton`, `clearfix`, `relative`, `fullHeight`, `responsive` |
|
|
35
|
+
| Group | Hook | Representative props |
|
|
36
|
+
| ---------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
37
|
+
| Color | `useColorClasses` | `color`, `colorShade`, `backgroundColor`, `backgroundColorShade` |
|
|
38
|
+
| Spacing | `useSpacingClasses` | `m`, `mt`, `mr`, `mb`, `ml`, `mx`, `my`, `p`, `pt`, `pr`, `pb`, `pl`, `px`, `py`, `gap`, `columnGap`, `rowGap`, `gapless` |
|
|
39
|
+
| Typography | `useTypographyClasses` | `textSize`, `textAlign`, `textTransform`, `textWeight`, `fontFamily` (+ responsive variants) |
|
|
40
|
+
| Visibility | `useVisibilityClasses` | `display`, `visibility` (+ per-viewport variants) |
|
|
41
|
+
| Flexbox | `useFlexboxClasses` | `flexDirection`, `flexWrap`, `justifyContent`, `alignItems`, `alignContent`, `alignSelf`, `flexGrow`, `flexShrink` |
|
|
42
|
+
| Other | `useOtherClasses` | `float`, `overflow`, `overflowX`, `overflowY`, `radius`, `shadow`, `interaction`, `cursor`, `skeleton`, `clearfix`, `pos`, `relative`, `fullHeight`, `aspectRatio`, `responsive` |
|
|
43
43
|
|
|
44
44
|
Because the component destructures these into `bulmaHelperClasses`, callers get the full Bulma
|
|
45
45
|
helper surface for free on every component built this way, and `rest` stays clean for DOM
|
|
@@ -68,13 +68,13 @@ de-dupes. Related exports:
|
|
|
68
68
|
Re-exported through `useBulmaClasses`. Use them to type component-specific props and to drive
|
|
69
69
|
Storybook `argTypes`/tests:
|
|
70
70
|
|
|
71
|
-
`validColors`, `validColorShades`, `validSchemeColors`, `validSizes`, `validTextSizes`,
|
|
71
|
+
`validColors`, `validColorShades`, `validSchemeColors`, `validSizes`, `validGaps`, `validTextSizes`,
|
|
72
72
|
`validAlignments`, `validTextTransforms`, `validTextWeights`, `validFontFamilies`,
|
|
73
73
|
`validDisplays`, `validVisibilities`, `validFlexDirections`, `validFlexWraps`,
|
|
74
74
|
`validJustifyContents`, `validAlignContents`, `validAlignItems`, `validAlignSelfs`,
|
|
75
75
|
`validFlexGrowShrink`, `validViewports`, `validFloats`, `validOverflows`,
|
|
76
|
-
`validInteractions`, `validCursors`, `validRadii`,
|
|
77
|
-
`validResponsives`.
|
|
76
|
+
`validAxisOverflows`, `validInteractions`, `validCursors`, `validRadii`,
|
|
77
|
+
`validShadows`, `validResponsives`, `validPositions`, `validAspectRatios`.
|
|
78
78
|
|
|
79
79
|
```ts
|
|
80
80
|
export type MyColor = (typeof validColors)[number];
|
|
@@ -94,6 +94,98 @@ overrides `--bulma-*` custom properties at runtime —
|
|
|
94
94
|
which is exactly why component SCSS must register its vars via `cv.register-vars` rather than
|
|
95
95
|
hard-coding values.
|
|
96
96
|
|
|
97
|
+
## Browser-only content: `ClientOnly` / `useIsHydrated`
|
|
98
|
+
|
|
99
|
+
- `<ClientOnly fallback?>` (`helpers/ClientOnly.tsx`) renders its children only after hydration,
|
|
100
|
+
and `fallback` on the server and while hydrating. Pass the children as a function to keep
|
|
101
|
+
browser-only expressions off the server. Use it rather than a `typeof window` check, which
|
|
102
|
+
makes the server and client markup differ.
|
|
103
|
+
- `useIsHydrated()` (`helpers/useIsHydrated.ts`) is the hook underneath: `false` on the server and
|
|
104
|
+
during the hydrating render, `true` from the commit after.
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
<ClientOnly fallback={<Skeleton variant="lines" lines={1} />}>
|
|
108
|
+
{() => (
|
|
109
|
+
<p>Times are in {Intl.DateTimeFormat().resolvedOptions().timeZone}.</p>
|
|
110
|
+
)}
|
|
111
|
+
</ClientOnly>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Floating content: `Portal`
|
|
115
|
+
|
|
116
|
+
A panel anchored to the button that opens it is `Popover`, which already portals
|
|
117
|
+
(`appendToBody`), traps focus and dismisses itself. `Portal` is for the overlays it doesn't
|
|
118
|
+
cover.
|
|
119
|
+
|
|
120
|
+
`<Portal container?>` (`helpers/portal.tsx`) renders its children into `document.body`, or into
|
|
121
|
+
`container` (an element or a selector), so floating content escapes an ancestor's `overflow`,
|
|
122
|
+
`transform` or stacking context. It renders nothing on the server and during hydration, so the
|
|
123
|
+
first client render matches; `disabled` renders in place instead. Use it rather than calling
|
|
124
|
+
`createPortal` yourself, which React's server renderer can't render.
|
|
125
|
+
|
|
126
|
+
Focus follows the DOM, not the React tree: portaled content comes last in the Tab order, so move
|
|
127
|
+
focus into it when it opens and back to its trigger when it closes. To trap portaled content,
|
|
128
|
+
put the trap's ref on the element inside the `Portal`, as below with
|
|
129
|
+
`useFocusTrap(panelRef, { active: open, restoreFocus: buttonRef })`. A focus trap doesn't cover
|
|
130
|
+
what a `Portal` inside it renders, so render nested overlays inside the trapped element.
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
{
|
|
134
|
+
open && (
|
|
135
|
+
<Portal>
|
|
136
|
+
<div ref={panelRef} role="dialog" aria-label="Filters" tabIndex={-1}>
|
|
137
|
+
…
|
|
138
|
+
</div>
|
|
139
|
+
</Portal>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Holding focus: `useFocusTrap`
|
|
145
|
+
|
|
146
|
+
`useFocusTrap(ref, { active, initialFocusRef, restoreFocus })` (`helpers/useFocusTrap.ts`) moves
|
|
147
|
+
focus into `ref` when `active` turns on, wraps Tab at the first and last tab stops (the ones the
|
|
148
|
+
browser visits, so hidden, disabled, inert and `tabIndex={-1}` elements are skipped and a radio
|
|
149
|
+
group counts once) and restores focus when it turns off. It handles Tab only: wire Escape to
|
|
150
|
+
close. Pass the trigger's ref as `restoreFocus` for a panel opened from a button. It looks for
|
|
151
|
+
the container again each time the component calling it renders, so `active` can follow `open`
|
|
152
|
+
alone even when the panel mounts a render later, as portaled content can. The example below
|
|
153
|
+
shows the hook's wiring; for a real filter panel opened from a button, use `Popover`, which does
|
|
154
|
+
all of this.
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
function FilterPanel({ children }: { children: React.ReactNode }) {
|
|
158
|
+
const [open, setOpen] = useState(false);
|
|
159
|
+
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
160
|
+
const panelRef = useRef<HTMLDivElement>(null);
|
|
161
|
+
useFocusTrap(panelRef, { active: open, restoreFocus: buttonRef });
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
<>
|
|
165
|
+
<Button
|
|
166
|
+
ref={buttonRef}
|
|
167
|
+
aria-haspopup="dialog"
|
|
168
|
+
aria-expanded={open}
|
|
169
|
+
onClick={() => setOpen(o => !o)}
|
|
170
|
+
>
|
|
171
|
+
Filters
|
|
172
|
+
</Button>
|
|
173
|
+
{open && (
|
|
174
|
+
<div
|
|
175
|
+
ref={panelRef}
|
|
176
|
+
role="dialog"
|
|
177
|
+
aria-label="Filters"
|
|
178
|
+
tabIndex={-1}
|
|
179
|
+
onKeyDown={e => e.key === 'Escape' && setOpen(false)}
|
|
180
|
+
>
|
|
181
|
+
{children}
|
|
182
|
+
</div>
|
|
183
|
+
)}
|
|
184
|
+
</>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
97
189
|
## SCSS utilities — from the `bulma` package
|
|
98
190
|
|
|
99
191
|
```scss
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!-- GENERATED by scripts/gen-component-catalog.mjs — do not edit by hand. -->
|
|
2
|
-
<!-- Regenerate with `
|
|
2
|
+
<!-- Regenerate with `pnpm gen:catalog`. Source: docs/docs/api/**. -->
|
|
3
3
|
|
|
4
4
|
# Component catalog
|
|
5
5
|
|
|
@@ -37,7 +37,7 @@ instead of hand-writing markup.
|
|
|
37
37
|
- Raw `*Base` form exports (`InputBase`, `SelectBase`, `TextAreaBase`, …) are
|
|
38
38
|
escape-hatch variants of the convenience wrappers above them; see the Form docs.
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
94 documented components. Generated from the API docs — every exported
|
|
41
41
|
component is guaranteed to appear (the generator fails if one lacks an API page).
|
|
42
42
|
|
|
43
43
|
## Elements
|
|
@@ -58,6 +58,7 @@ component is guaranteed to appear (the generator fails if one lacks an API page)
|
|
|
58
58
|
- [Link](https://bestax.io/docs/api/elements/link) — The `Link` component renders a styled anchor (`<a>`) element with Bulma helper class integration.
|
|
59
59
|
- [LinkButton](https://bestax.io/docs/api/elements/linkbutton) — The `LinkButton` component renders a `<button>` that visually looks like text or a link.
|
|
60
60
|
- [ListItem](https://bestax.io/docs/api/elements/listitem) — The `ListItem` component renders a styled list item (`<li>`) element with Bulma helper class integration.
|
|
61
|
+
- [Loader](https://bestax.io/docs/api/elements/loader) — The `Loader` component renders Bulma's `.loader`, a small spinning ring for inline loading states.
|
|
61
62
|
- [Notification](https://bestax.io/docs/api/elements/notification) — The `Notification` component is a Bulma-styled alert/message area for providing feedback, warnings, or information to users.
|
|
62
63
|
- [OrderedList](https://bestax.io/docs/api/elements/orderedlist) — The `OrderedList` component renders a styled ordered list (`<ol>`) element with Bulma helper class integration.
|
|
63
64
|
- [Paragraph](https://bestax.io/docs/api/elements/paragraph) — The `Paragraph` component renders a styled `<p>` element with Bulma helper class integration.
|
|
@@ -82,6 +83,7 @@ component is guaranteed to appear (the generator fails if one lacks an API page)
|
|
|
82
83
|
- [Card](https://bestax.io/docs/api/components/card) — The `Card` component renders a Bulma-styled card with optional header, image, content, and footer.
|
|
83
84
|
- [Carousel](https://bestax.io/docs/api/components/carousel) — The `Carousel` component provides an image/content slider with navigation arrows and indicators.
|
|
84
85
|
- [Collapse](https://bestax.io/docs/api/components/collapse) — The `Collapse` component provides an expandable/collapsible content panel.
|
|
86
|
+
- [Collapses](https://bestax.io/docs/api/components/collapses) — The `Collapses` component groups `Collapse` items into an accordion that keeps one item open at a time, or any number with `multiple`.
|
|
85
87
|
- [Dialog](https://bestax.io/docs/api/components/dialog) — The `Dialog` component provides ready-made confirm and alert dialogs, so a destructive action stays one `await dialog.confirm()` call away.
|
|
86
88
|
- [Dropdown](https://bestax.io/docs/api/components/dropdown) — The `Dropdown` component provides Bulma's versatile dropdown menu for your Bulma React UI.
|
|
87
89
|
- [Loading](https://bestax.io/docs/api/components/loading) — The `Loading` component provides a loading overlay with a spinner animation.
|
|
@@ -91,6 +93,7 @@ component is guaranteed to appear (the generator fails if one lacks an API page)
|
|
|
91
93
|
- [Navbar](https://bestax.io/docs/api/components/navbar) — The `Navbar` component implements Bulma's powerful, responsive navigation bar for your Bulma React UI.
|
|
92
94
|
- [Pagination](https://bestax.io/docs/api/components/pagination) — The `Pagination` component provides a flexible, composable Bulma pagination navigation for your Bulma React UI.
|
|
93
95
|
- [Panel](https://bestax.io/docs/api/components/panel) — The `Panel` component implements Bulma's versatile panel block for React.
|
|
96
|
+
- [Popover](https://bestax.io/docs/api/components/popover) — The `Popover` component opens a panel of interactive content, such as a filter form or a set of share options, anchored to the element that toggles it.
|
|
94
97
|
- [Reveal](https://bestax.io/docs/api/components/reveal) — The `Reveal` component animates its content into view as it scrolls into the viewport, backed by `IntersectionObserver`.
|
|
95
98
|
- [Sidebar](https://bestax.io/docs/api/components/sidebar) — The `Sidebar` component provides a slide-out navigation panel that appears from the left or right side of the screen.
|
|
96
99
|
- [Steps](https://bestax.io/docs/api/components/steps) — The `Steps` component provides a multi-step progress indicator for wizard flows, checkout processes, or any multi-step workflow.
|
|
@@ -105,10 +108,11 @@ component is guaranteed to appear (the generator fails if one lacks an API page)
|
|
|
105
108
|
- [Checkboxes](https://bestax.io/docs/api/form/checkboxes) — The `Checkboxes` component wraps multiple `Checkbox` components in a Bulma-styled group.
|
|
106
109
|
- [Control](https://bestax.io/docs/api/form/control) — The `Control` component is a Bulma-styled wrapper for form controls (`Input`, `Select`, `TextArea`, etc.), supporting icons (left/right), loading state…
|
|
107
110
|
- [DateInput](https://bestax.io/docs/api/form/datetime/dateinput) — The `DateInput` component is a form input that opens a popover calendar for date selection.
|
|
111
|
+
- [DateRangeInput](https://bestax.io/docs/api/form/datetime/daterangeinput) — The `DateRangeInput` component is a form input for a start and end date, picked from one popover calendar or typed into two segmented inputs.
|
|
108
112
|
- [DateTimeInput](https://bestax.io/docs/api/form/datetime/datetimeinput) — The `DateTimeInput` combines a calendar and a time **wheel spinner** in a single popover — an iOS-style layout.
|
|
109
113
|
- [Field](https://bestax.io/docs/api/form/field) — The `Field` component is a Bulma-styled form field container.
|
|
110
114
|
- [File](https://bestax.io/docs/api/form/file) — The `File` component provides a Bulma-styled file input, supporting color, size, boxed/fullwidth/align styles, icons, "has name", and filename display.
|
|
111
|
-
- [Input](https://bestax.io/docs/api/form/input) — The `Input` component provides a Bulma-styled text input, supporting colors, sizes, rounded corners, static
|
|
115
|
+
- [Input](https://bestax.io/docs/api/form/input) — The `Input` component provides a Bulma-styled text input, supporting colors, sizes, rounded corners, static state, hover/focus/loading states…
|
|
112
116
|
- [Numberinput](https://bestax.io/docs/api/form/numberinput) — The `Numberinput` component provides a number input with increment/decrement buttons.
|
|
113
117
|
- [Radio](https://bestax.io/docs/api/form/radio) — The `Radio` component provides a Bulma-styled radio button input with flexible labels and helper classes.
|
|
114
118
|
- [Radios](https://bestax.io/docs/api/form/radios) — The `Radios` component wraps multiple `Radio` components in a Bulma-styled group.
|
|
@@ -117,7 +121,7 @@ component is guaranteed to appear (the generator fails if one lacks an API page)
|
|
|
117
121
|
- [Slider](https://bestax.io/docs/api/form/slider) — The `Slider` component provides a range slider input for selecting values within a range.
|
|
118
122
|
- [Switch](https://bestax.io/docs/api/form/switch) — The `Switch` component provides a toggle switch for boolean on/off states.
|
|
119
123
|
- [Taginput](https://bestax.io/docs/api/form/taginput) — The `Taginput` component provides a tag/chip input field for managing multiple tags.
|
|
120
|
-
- [TextArea](https://bestax.io/docs/api/form/textarea) — The `TextArea` component provides a Bulma-styled multi-line text input, supporting color, size,
|
|
124
|
+
- [TextArea](https://bestax.io/docs/api/form/textarea) — The `TextArea` component provides a Bulma-styled multi-line text input, supporting color, size, hover/focus/loading states, fixed size…
|
|
121
125
|
- [TimeInput](https://bestax.io/docs/api/form/datetime/timeinput) — The `TimeInput` component is a form input that opens a popover spinner for time-of-day selection.
|
|
122
126
|
|
|
123
127
|
## Columns
|
|
@@ -141,9 +145,12 @@ component is guaranteed to appear (the generator fails if one lacks an API page)
|
|
|
141
145
|
|
|
142
146
|
## Helpers
|
|
143
147
|
|
|
148
|
+
- [ClientOnly](https://bestax.io/docs/api/helpers/clientonly) — `ClientOnly` renders its children only in the browser, after hydration, and a `fallback` until then…
|
|
144
149
|
- [ConfigProvider](https://bestax.io/docs/api/helpers/config) — The `ConfigProvider` component provides a React context for configuring global settings across all Bulma UI components.
|
|
150
|
+
- [Portal](https://bestax.io/docs/api/helpers/portal) — `Portal` renders its children into another part of the page, `document.body` unless `container` says otherwise…
|
|
145
151
|
- [Theme](https://bestax.io/docs/api/helpers/theme) — The `Theme` component provides a powerful way to customize Bulma's appearance using CSS custom properties (CSS variables).
|
|
146
|
-
- [Valid value constants](https://bestax.io/docs/api/helpers/valid-values) — The
|
|
152
|
+
- [Valid value constants](https://bestax.io/docs/api/helpers/valid-values) — The helper tuples enumerate the core accepted values for the shared Bulma helper props — public API for building prop types and validation.
|
|
147
153
|
- [classNames](https://bestax.io/docs/api/helpers/classnames) — `classNames` is a utility function for conditionally joining class names together.
|
|
148
154
|
- [useBulmaClasses](https://bestax.io/docs/api/helpers/usebulmaclasses) — `useBulmaClasses` is a custom React hook that generates Bulma helper class strings from a set of props.
|
|
155
|
+
- [useFocusTrap](https://bestax.io/docs/api/helpers/usefocustrap) — `useFocusTrap` keeps keyboard focus inside a container while it is active: focus moves in when the trap turns on…
|
|
149
156
|
- [usePrefixedClassNames](https://bestax.io/docs/api/helpers/useprefixedclassnames) — `usePrefixedClassNames` builds a component class string that honors the `classPrefix` from `ConfigProvider` — the hook every bestax component uses for its own…
|
|
@@ -159,6 +159,23 @@ Rules that keep components consistent:
|
|
|
159
159
|
Run `pnpm exec prettier --write` on your new files (or `pnpm format` from the repo root) before
|
|
160
160
|
`pnpm lint`. Copy snippets as a starting point, then let Prettier normalize them.
|
|
161
161
|
|
|
162
|
+
- **Browser-only work waits for hydration.** A component that measures or reads browser-only
|
|
163
|
+
state while rendering uses `useIsHydrated` (`helpers/useIsHydrated.ts`) rather than a
|
|
164
|
+
`typeof document` check, so the first client render matches the server markup. Test that with
|
|
165
|
+
`renderToString` plus `hydrateRoot` and a `console.error` spy, as `ClientOnly.test.tsx` does.
|
|
166
|
+
|
|
167
|
+
- **Floating content portals through `Portal`.** A new component that renders outside its own
|
|
168
|
+
place in the DOM uses `Portal` (`helpers/portal.tsx`) rather than its own `createPortal` and
|
|
169
|
+
`typeof document` check. `Portal` renders nothing on the server or during hydration, so the
|
|
170
|
+
first client render matches the server markup. Test that with `renderToString` plus
|
|
171
|
+
`hydrateRoot` and a `console.error` spy, as `portal.test.tsx` does.
|
|
172
|
+
|
|
173
|
+
- **Focus management builds on `useFocusTrap`.** A new component that holds focus while it is
|
|
174
|
+
open uses `useFocusTrap` (`helpers/useFocusTrap.ts`) rather than its own Tab handler, so it
|
|
175
|
+
gets the same tab-stop rules (hidden, disabled, inert, radio groups, shadow roots) as the rest
|
|
176
|
+
of the library. It waits for hydration, so it also traps a container that only appears after
|
|
177
|
+
hydration.
|
|
178
|
+
|
|
162
179
|
See `api.md` for the full helper API and `patterns.md` for the complete Dialog walkthrough.
|
|
163
180
|
|
|
164
181
|
## SCSS pattern (required)
|
|
@@ -223,6 +240,12 @@ Register **all** themable values — durations and offsets included — and pref
|
|
|
223
240
|
tokens (`scheme-main`, `text`, `border`). When the component is themeable, add rows to
|
|
224
241
|
`skills/bestax-theming/references/themeable-components.md` and `css-variables.md` in the same PR.
|
|
225
242
|
|
|
243
|
+
The reduced-motion rule has to outrank every rule that starts the animation. On the same
|
|
244
|
+
selector it wins by coming later; when the animation sits on a more specific selector, such as
|
|
245
|
+
a state class (`.mycomponent.is-active`), make the stop `animation: none !important`. A styles
|
|
246
|
+
test reads every animation out of each published stylesheet and fails on one that still plays
|
|
247
|
+
under reduced motion.
|
|
248
|
+
|
|
226
249
|
The canonical reference file is `bulma-ui/src/scss/components/_dialog.scss`.
|
|
227
250
|
|
|
228
251
|
## Stories
|
|
@@ -94,7 +94,8 @@ All import from `@allxsmith/bestax-bulma`. Convenience components auto-wrap Fiel
|
|
|
94
94
|
| `Numberinput` | Numeric input with increment/decrement, min/max, step, stepper. |
|
|
95
95
|
| `Rate` | Star rating; `max`, `precision` (half/quarter), custom icons, `disabled`. |
|
|
96
96
|
| `Taginput` | Tag/chip input; suggestions, confirm keys, closable tags. |
|
|
97
|
-
| `DateInput` / `TimeInput` / `DateTimeInput` (+ `*Base`) | Date / time / datetime pickers
|
|
97
|
+
| `DateInput` / `TimeInput` / `DateTimeInput` (+ `*Base`) | Date / time / datetime pickers; month or year via `granularity`. |
|
|
98
|
+
| `DateRangeInput` (+ `*Base`) | Start and end date: `[Date \| null, Date \| null]`, one calendar. |
|
|
98
99
|
|
|
99
100
|
(`NumberInput` and `TagInput` also exist as deprecated aliases of `Numberinput`/`Taginput` —
|
|
100
101
|
same components; prefer the lowercase-second-word spellings.)
|
|
@@ -103,18 +104,18 @@ same components; prefer the lowercase-second-word spellings.)
|
|
|
103
104
|
|
|
104
105
|
Across the convenience inputs (`Input`, `Select`, `TextArea`, and similar):
|
|
105
106
|
|
|
106
|
-
| Prop | Type | Purpose
|
|
107
|
-
| -------------------------------- | --------------------------------------------------------------------- |
|
|
108
|
-
| `color` | `'primary' \| 'link' \| 'info' \| 'success' \| 'warning' \| 'danger'` | Visual state — use `'danger'` for errors, `'success'` for valid.
|
|
109
|
-
| `size` | `'small' \| 'medium' \| 'large'` | Input size.
|
|
110
|
-
| `value` / `onChange` | controlled value + handler | Standard React controlled inputs.
|
|
111
|
-
| `defaultValue` | uncontrolled initial value | When not controlling state.
|
|
112
|
-
| `disabled`, `readOnly` | `boolean` | Native states (`readOnly` on `*Base`).
|
|
113
|
-
| `label` | `ReactNode` | Field label (convenience components; auto-associated via `htmlFor`).
|
|
114
|
-
| `message` | `ReactNode` | Help / validation text rendered as `<p class="help">`.
|
|
115
|
-
| `messageColor` | a Bulma color | Colors the help text (`'danger'` for errors).
|
|
116
|
-
| `iconLeftName` / `iconRightName` | `string` | Icon shortcuts; pair with `hasIconsLeft/Right`.
|
|
117
|
-
| `isLoading` | `boolean` | Loading
|
|
107
|
+
| Prop | Type | Purpose |
|
|
108
|
+
| -------------------------------- | --------------------------------------------------------------------- | -------------------------------------------------------------------------- |
|
|
109
|
+
| `color` | `'primary' \| 'link' \| 'info' \| 'success' \| 'warning' \| 'danger'` | Visual state — use `'danger'` for errors, `'success'` for valid. |
|
|
110
|
+
| `size` | `'small' \| 'medium' \| 'large'` | Input size. |
|
|
111
|
+
| `value` / `onChange` | controlled value + handler | Standard React controlled inputs. |
|
|
112
|
+
| `defaultValue` | uncontrolled initial value | When not controlling state. |
|
|
113
|
+
| `disabled`, `readOnly` | `boolean` | Native states (`readOnly` on `*Base`). |
|
|
114
|
+
| `label` | `ReactNode` | Field label (convenience components; auto-associated via `htmlFor`). |
|
|
115
|
+
| `message` | `ReactNode` | Help / validation text rendered as `<p class="help">`. |
|
|
116
|
+
| `messageColor` | a Bulma color | Colors the help text (`'danger'` for errors). |
|
|
117
|
+
| `iconLeftName` / `iconRightName` | `string` | Icon shortcuts; pair with `hasIconsLeft/Right`. |
|
|
118
|
+
| `isLoading` | `boolean` | Loading spinner on the Control; `Select` draws it in place of the chevron. |
|
|
118
119
|
|
|
119
120
|
Plus the full Bulma **helper props** (`m`, `p`, `textColor`, `display`, …) on every component
|
|
120
121
|
via `useBulmaClasses`.
|
|
@@ -130,8 +131,8 @@ The `label` prop on the single-control convenience inputs (`Input`, `Select`, `T
|
|
|
130
131
|
generated one otherwise, and an explicit `labelProps={{ htmlFor }}` wins. The wiring only
|
|
131
132
|
happens when the component renders its own `Field` (nested inside one, the `label` prop is
|
|
132
133
|
dropped); the date/time pickers skip it in `inline` mode and `Taginput` skips it at
|
|
133
|
-
`maxTags` (no visible input to label). The group inputs (`Checkboxes`, `Radios`, `Rate
|
|
134
|
-
associate their `label` too, but group-style: the wrapper gets `role="group"`/`"radiogroup"`
|
|
134
|
+
`maxTags` (no visible input to label). The group inputs (`Checkboxes`, `Radios`, `Rate`,
|
|
135
|
+
`DateRangeInput`) associate their `label` too, but group-style: the wrapper gets `role="group"`/`"radiogroup"`
|
|
135
136
|
and `aria-labelledby` pointing at the label. Composing `Field` + bases yourself also
|
|
136
137
|
associates: `Field`'s own `label` wires to a single composed `InputBase`/`SelectBase`/
|
|
137
138
|
`TextAreaBase` (skipped for `grouped`/`hasAddons`). Pass `labelProps={{ htmlFor }}` plus a
|
|
@@ -144,7 +145,17 @@ opt out — e.g. when the labeled `Field` wraps something that is not one of tho
|
|
|
144
145
|
lines, auto-wrapping, built-in `message`/`messageColor`. Default to this.
|
|
145
146
|
- **Composed** (`Field` + `Control` + `InputBase`) — when you need grouped controls, addons,
|
|
146
147
|
multiple controls per field, or custom layout. The convenience components detect they're
|
|
147
|
-
already inside a `Field`/`Control` and won't double-wrap, so you can mix the two.
|
|
148
|
+
already inside a `Field`/`Control` and won't double-wrap, so you can mix the two. Inside a
|
|
149
|
+
`Control` they render no `Control` of their own, so set their Control-level props, such as
|
|
150
|
+
the icon props, `isLoading` and `controlSize`, on that `Control`: given to the input there,
|
|
151
|
+
they do nothing and warn in development. `Select` draws its own `isLoading`, so that one
|
|
152
|
+
stays on the `Select`. Inside a `Control` they render no `Field` either, so a convenience
|
|
153
|
+
input you place in a `Control` (for icons, say) takes its `label`, `horizontal` and class
|
|
154
|
+
name from a `Field` wrapped around that `Control`. Given `label`, `message`, `horizontal` or `fieldClassName` in a
|
|
155
|
+
`Control` with no `Field` around it, it renders its own `Field` inside the `.control`,
|
|
156
|
+
which Bulma's styles don't expect, and warns in development. `Autocomplete` and
|
|
157
|
+
`Numberinput` are the exception: in a bare `Control` they always render their own `Field`,
|
|
158
|
+
so give that `Control` a `Field` around it.
|
|
148
159
|
|
|
149
160
|
## Validation without a library
|
|
150
161
|
|
|
@@ -220,7 +231,7 @@ miss because Bulma has something that looks close:
|
|
|
220
231
|
- **Confirmation** — `Toast`, not `Notification`/`Message`. Mount
|
|
221
232
|
`<ToastContainer position="top-right" />` once at the app root, then call
|
|
222
233
|
`toast.success('Demo booked')` from the submit handler (`.danger` for a failed submit). It
|
|
223
|
-
self-dismisses
|
|
234
|
+
self-dismisses.
|
|
224
235
|
- **"Are you sure?"** — `Dialog`, not `Modal`. Mount `<DialogContainer />` at the root, then
|
|
225
236
|
`if (await dialog.confirm({ title: 'Delete this key?', message: '…', type: 'danger' })) …`.
|
|
226
237
|
It resolves to a boolean, so a destructive action stays one `if` rather than a state machine.
|