create-bestax 4.2.13 → 4.2.14
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 -7
- package/dist/cli.d.ts +11 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +17 -2
- package/dist/index.js +2 -2
- package/package.json +3 -3
- package/templates/skills/bestax-custom-component/examples/stat-card.tsx +2 -2
- package/templates/skills/bestax-icons/SKILL.md +8 -6
- package/templates/skills/bestax-icons/examples/icon-usage.tsx +3 -3
- package/templates/skills/bestax-icons/references/icon-libraries.md +3 -3
- package/templates/skills/bestax-layout-scaffold/examples/app-shell.tsx +1 -1
- package/templates/skills/bestax-layout-scaffold/examples/card-grid.tsx +0 -1
- package/templates/skills/bestax-layout-scaffold/examples/centered.tsx +0 -1
- package/templates/skills/bestax-layout-scaffold/examples/content-page.tsx +0 -1
- package/templates/skills/bestax-layout-scaffold/examples/landing.tsx +1 -1
- package/templates/skills/bestax-migrate/references/bulma-classes/component-map.md +5 -4
- package/templates/skills/bestax-migrate/references/bulma-classes/unmappables.md +5 -1
- package/templates/skills/bestax-optimize/SKILL.md +10 -6
- package/templates/skills/bestax-optimize/references/modular-build.md +4 -1
- package/templates/skills/bestax-theming/examples/dark-mode.tsx +1 -1
- package/templates/skills/bestax-theming/examples/theme-config.tsx +2 -2
- package/templates/skills/bestax-theming/references/css-variables.md +3 -1
package/README.md
CHANGED
|
@@ -29,9 +29,6 @@ npm create bestax@latest my-app
|
|
|
29
29
|
|
|
30
30
|
# Using npx
|
|
31
31
|
npx create-bestax@latest my-app
|
|
32
|
-
|
|
33
|
-
# Alternative naming
|
|
34
|
-
npm create bestax-bulma@latest my-app
|
|
35
32
|
```
|
|
36
33
|
|
|
37
34
|
### Interactive Mode
|
|
@@ -47,7 +44,7 @@ You'll be asked to:
|
|
|
47
44
|
1. Enter a project name (and, if that directory already holds files, confirm removing them;
|
|
48
45
|
nothing is removed until you have answered the last question)
|
|
49
46
|
2. Select a framework (Vite or Vite + TypeScript)
|
|
50
|
-
3. Choose a Bulma CSS flavor (
|
|
47
|
+
3. Choose a Bulma CSS flavor (the `--bulma` options below)
|
|
51
48
|
4. Select an icon library (Font Awesome, Material Icons, etc.)
|
|
52
49
|
5. Choose whether to install the bestax AI skills into `.claude/skills/`
|
|
53
50
|
|
|
@@ -56,9 +53,13 @@ Every prompt has a flag equivalent, so the whole flow is scriptable and CI-frien
|
|
|
56
53
|
### Command Line Options
|
|
57
54
|
|
|
58
55
|
```bash
|
|
59
|
-
npm create bestax@latest [project-directory] [options]
|
|
56
|
+
npm create bestax@latest [project-directory] -- [options]
|
|
60
57
|
```
|
|
61
58
|
|
|
59
|
+
Put the options after `--`. npm needs it to pass them on at all, and so does bun, whose
|
|
60
|
+
`bun create` rejects short flags such as `-t` and `-y` itself. pnpm and Yarn 1 accept the options
|
|
61
|
+
with or without it.
|
|
62
|
+
|
|
62
63
|
**Arguments:**
|
|
63
64
|
|
|
64
65
|
- `[project-directory]` - Optional project directory name. It also becomes the `package.json`
|
|
@@ -104,10 +105,13 @@ npm create bestax@latest [project-directory] [options]
|
|
|
104
105
|
|
|
105
106
|
```bash
|
|
106
107
|
# Create a TypeScript project with Font Awesome icons
|
|
107
|
-
npm create bestax@latest my-app -t vite-ts -i fontawesome -b complete
|
|
108
|
+
npm create bestax@latest my-app -- -t vite-ts -i fontawesome -b complete
|
|
108
109
|
|
|
109
110
|
# Use all defaults (skip prompts)
|
|
110
|
-
npm create bestax@latest my-app -y
|
|
111
|
+
npm create bestax@latest my-app -- -y
|
|
112
|
+
|
|
113
|
+
# The same with bun
|
|
114
|
+
bun create bestax@latest my-app -- -y
|
|
111
115
|
```
|
|
112
116
|
|
|
113
117
|
## Templates
|
package/dist/cli.d.ts
CHANGED
|
@@ -16,5 +16,15 @@ export declare function copyTemplate(templatePath: string, targetPath: string):
|
|
|
16
16
|
export declare function createProject(projectDir?: string, options?: CLIOptions): Promise<void>;
|
|
17
17
|
export declare function createCLI(): Command;
|
|
18
18
|
export declare function isMainModule(importMetaUrl: string, argv1: string): boolean;
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* pnpm, bun and bunx hand a `--` to the scaffolder as it was typed, where npm
|
|
21
|
+
* and Yarn 1 strip it, so `pnpm create bestax my-app -- -t vite-ts` arrives as
|
|
22
|
+
* `my-app -- -t vite-ts`. Commander reads `--` as the end of the options, and
|
|
23
|
+
* every flag after it became an extra argument: "too many arguments" (#950).
|
|
24
|
+
* Bun users need that `--`, because `bun create` rejects short flags such as
|
|
25
|
+
* `-t` and `-y` itself. So the first `--` after the script path is dropped
|
|
26
|
+
* before parsing, and a second keeps its usual meaning.
|
|
27
|
+
*/
|
|
28
|
+
export declare function dropForwardedSeparator(argv: readonly string[]): string[];
|
|
29
|
+
export declare function runCLI(argv?: readonly string[]): Promise<void>;
|
|
20
30
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EACL,cAAc,EACd,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC3B,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC1E,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACtE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGzE,OAAO,EAAE,cAAc,EAAE,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,cAAc,IAAI,cAAc,EAChC,iBAAiB,IAAI,iBAAiB,EACtC,iBAAiB,IAAI,iBAAiB,GACvC,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,aAAa,EACb,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,wBAAsB,cAAc,CAClC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGxB;AAED,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,CAAC,CAGhC;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,aAAa,CACjC,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,UAAU,GACnB,OAAO,CAAC,IAAI,CAAC,CAGf;AAcD,wBAAgB,SAAS,IAAI,OAAO,CAsCnC;AAED,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAE1E;AAED,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EACL,cAAc,EACd,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC3B,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC1E,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACtE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGzE,OAAO,EAAE,cAAc,EAAE,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,cAAc,IAAI,cAAc,EAChC,iBAAiB,IAAI,iBAAiB,EACtC,iBAAiB,IAAI,iBAAiB,GACvC,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,aAAa,EACb,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,wBAAsB,cAAc,CAClC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGxB;AAED,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,CAAC,CAGhC;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,aAAa,CACjC,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,UAAU,GACnB,OAAO,CAAC,IAAI,CAAC,CAGf;AAcD,wBAAgB,SAAS,IAAI,OAAO,CAsCnC;AAED,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAE1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAKxE;AAED,wBAAsB,MAAM,CAC1B,IAAI,GAAE,SAAS,MAAM,EAAiB,GACrC,OAAO,CAAC,IAAI,CAAC,CAGf"}
|
package/dist/cli.js
CHANGED
|
@@ -71,9 +71,24 @@ export function createCLI() {
|
|
|
71
71
|
export function isMainModule(importMetaUrl, argv1) {
|
|
72
72
|
return importMetaUrl === `file://${argv1}`;
|
|
73
73
|
}
|
|
74
|
-
|
|
74
|
+
/**
|
|
75
|
+
* pnpm, bun and bunx hand a `--` to the scaffolder as it was typed, where npm
|
|
76
|
+
* and Yarn 1 strip it, so `pnpm create bestax my-app -- -t vite-ts` arrives as
|
|
77
|
+
* `my-app -- -t vite-ts`. Commander reads `--` as the end of the options, and
|
|
78
|
+
* every flag after it became an extra argument: "too many arguments" (#950).
|
|
79
|
+
* Bun users need that `--`, because `bun create` rejects short flags such as
|
|
80
|
+
* `-t` and `-y` itself. So the first `--` after the script path is dropped
|
|
81
|
+
* before parsing, and a second keeps its usual meaning.
|
|
82
|
+
*/
|
|
83
|
+
export function dropForwardedSeparator(argv) {
|
|
84
|
+
const separator = argv.indexOf('--', 2);
|
|
85
|
+
return separator === -1
|
|
86
|
+
? [...argv]
|
|
87
|
+
: [...argv.slice(0, separator), ...argv.slice(separator + 1)];
|
|
88
|
+
}
|
|
89
|
+
export async function runCLI(argv = process.argv) {
|
|
75
90
|
const program = createCLI();
|
|
76
|
-
await program.parseAsync();
|
|
91
|
+
await program.parseAsync(dropForwardedSeparator(argv));
|
|
77
92
|
}
|
|
78
93
|
// Only run if this is the main module
|
|
79
94
|
/* istanbul ignore next */
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,6 @@ if (majorVersion < MINIMUM_NODE_VERSION) {
|
|
|
14
14
|
`Please upgrade your Node.js version.`);
|
|
15
15
|
process.exit(1);
|
|
16
16
|
}
|
|
17
|
-
const {
|
|
18
|
-
await
|
|
17
|
+
const { runCLI } = await import('./cli.js');
|
|
18
|
+
await runCLI();
|
|
19
19
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-bestax",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.14",
|
|
4
4
|
"description": "Create a new bestax-bulma project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"prompts": "^2.4.2",
|
|
42
42
|
"react": "^18.0.0 || ^19.0.0",
|
|
43
43
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
44
|
-
"@allxsmith/bestax-bulma": "^5.27.
|
|
44
|
+
"@allxsmith/bestax-bulma": "^5.27.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@jest/globals": "^30.0.0",
|
|
@@ -78,5 +78,5 @@
|
|
|
78
78
|
"clean": "rimraf dist",
|
|
79
79
|
"release": "npx semantic-release"
|
|
80
80
|
},
|
|
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
|
|
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\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 (the `--bulma` options below)\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\nPut the options after `--`. npm needs it to pass them on at all, and so does bun, whose\n`bun create` rejects short flags such as `-t` and `-y` itself. pnpm and Yarn 1 accept the options\nwith or without it.\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# The same with bun\nbun 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"
|
|
82
82
|
}
|
|
@@ -64,8 +64,8 @@ export function StatCard({
|
|
|
64
64
|
name={icon}
|
|
65
65
|
size="large"
|
|
66
66
|
textColor={color}
|
|
67
|
-
// Decorative: the label below already says it, so
|
|
68
|
-
// Icon
|
|
67
|
+
// Decorative: the label below already says it, so it stays hidden
|
|
68
|
+
// from AT, as an Icon with no `ariaLabel` is anyway. (To *label* an
|
|
69
69
|
// icon, use Icon's own camelCase `ariaLabel`; most components take
|
|
70
70
|
// the plain aria-label attribute.)
|
|
71
71
|
aria-hidden="true"
|
|
@@ -89,16 +89,18 @@ to `iconLeftName`/`iconRightName` if one is given, otherwise leaving the icon co
|
|
|
89
89
|
|
|
90
90
|
## Accessibility
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
An `Icon` is decorative unless it is named: with no `ariaLabel` it renders `aria-hidden="true"`
|
|
93
|
+
and no name. Name it with its camelCase `ariaLabel` prop, and it renders `role="img"` with that
|
|
94
|
+
`aria-label`. Only a few components declare that prop (`Icon`, `Delete`, `Slider`, `Carousel`):
|
|
95
|
+
everything else takes the standard `aria-label` attribute, e.g.
|
|
96
|
+
`<Navbar.Burger aria-label="menu" />`.
|
|
95
97
|
|
|
96
98
|
- **Meaningful icon** (stands alone, conveys information): pass a descriptive
|
|
97
99
|
`ariaLabel="Delete item"`.
|
|
98
100
|
- **Decorative icon** (next to visible text that says the same thing, e.g. inside `IconText`
|
|
99
|
-
or a labeled `Button`):
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
or a labeled `Button`): leave `ariaLabel` off, and the icon stays out of the accessible
|
|
102
|
+
name. An explicit `aria-hidden="true"`, as in the examples here, says the same thing.
|
|
103
|
+
- **Icon-only control:** name the control (`<Button aria-label="Delete item">`), not the icon.
|
|
102
104
|
|
|
103
105
|
## References
|
|
104
106
|
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
// Set the library ONCE on ConfigProvider ('fa' | 'mdi' | 'ion' |
|
|
7
7
|
// 'material-icons' | 'material-symbols' — Ionicons is 'ion', NOT 'ionicons');
|
|
8
8
|
// every <Icon> below then omits `library`.
|
|
9
|
-
import React from 'react';
|
|
10
9
|
import {
|
|
11
10
|
ConfigProvider,
|
|
12
11
|
Icon,
|
|
@@ -22,7 +21,7 @@ export function IconShowcase() {
|
|
|
22
21
|
<Box>
|
|
23
22
|
<Title size="5">Meaningful icons carry their own label</Title>
|
|
24
23
|
{/* Standalone icons convey information — give them a descriptive
|
|
25
|
-
ariaLabel
|
|
24
|
+
ariaLabel, which also makes the icon an image. */}
|
|
26
25
|
<Icon
|
|
27
26
|
name="triangle-exclamation"
|
|
28
27
|
textColor="warning"
|
|
@@ -34,7 +33,8 @@ export function IconShowcase() {
|
|
|
34
33
|
Decorative icons hide from screen readers
|
|
35
34
|
</Title>
|
|
36
35
|
{/* Next to visible text the icon repeats the message — aria-hidden
|
|
37
|
-
|
|
36
|
+
keeps a duplicate from being announced. An Icon with no ariaLabel
|
|
37
|
+
renders it anyway; writing it out says so. */}
|
|
38
38
|
<IconText iconProps={{ name: 'star', 'aria-hidden': 'true' }}>
|
|
39
39
|
Starred
|
|
40
40
|
</IconText>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Facts an agent can act on for each of the five libraries `Icon` supports. The library ships no
|
|
4
4
|
icon fonts: the app must install the chosen library (the `npm create bestax` scaffold's
|
|
5
|
-
`--icon` flag
|
|
5
|
+
`--icon` flag wires it in; in an existing app, follow Setup below).
|
|
6
6
|
|
|
7
7
|
## How `Icon` renders
|
|
8
8
|
|
|
@@ -126,5 +126,5 @@ Multiple segments via `items`:
|
|
|
126
126
|
/>
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
-
Icons inside `IconText` sit next to their visible text
|
|
130
|
-
`aria-hidden` (see SKILL.md's accessibility rules).
|
|
129
|
+
Icons inside `IconText` sit next to their visible text, so leave them decorative: no
|
|
130
|
+
`ariaLabel`, or an explicit `aria-hidden` (see SKILL.md's accessibility rules).
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
//
|
|
11
11
|
// `ConfigProvider` wraps the shell once at the root to set the app-wide icon
|
|
12
12
|
// library (so <Icon> needs no `library` prop) and, optionally, a class prefix.
|
|
13
|
-
import
|
|
13
|
+
import { useEffect, useState } from 'react';
|
|
14
14
|
import {
|
|
15
15
|
ConfigProvider,
|
|
16
16
|
Navbar,
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
// it (flexGrow="1"), so short blurbs don't leave ragged card bottoms.
|
|
6
6
|
// (`height: 100%` on the card would NOT work — it resolves against auto
|
|
7
7
|
// height. For uniform grids, Grid/Cell gives equal heights for free.)
|
|
8
|
-
import React from 'react';
|
|
9
8
|
import {
|
|
10
9
|
Section,
|
|
11
10
|
Container,
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// also needs the `has-navbar-fixed-top` class on <html> so the page is padded
|
|
11
11
|
// below it (never an inline padding offset) — Bulma requires this and the
|
|
12
12
|
// library does NOT add it for you.
|
|
13
|
-
import
|
|
13
|
+
import { useEffect, useState } from 'react';
|
|
14
14
|
import {
|
|
15
15
|
Navbar,
|
|
16
16
|
Hero,
|
|
@@ -145,7 +145,8 @@ A `.tabs` converts around its `<ul>`, and the `<li>`s and `<a>`s inside stay as
|
|
|
145
145
|
renders its own `<a>` with tab roles and puts its label in a `<span>`, so converting the tabs
|
|
146
146
|
themselves is by hand (something that sat beside the text in the `<a>`, a `Tag` say, then wants a
|
|
147
147
|
`Span display="flex" alignItems="center"` around it and the label). A `.icon` converts around the
|
|
148
|
-
`<i>` inside it when it carries
|
|
148
|
+
`<i>` inside it when it carries the attribute `Icon` writes otherwise: `aria-hidden` with no name,
|
|
149
|
+
no `role` and no `tabIndex`, and `role="img"` beside an `aria-label` or `aria-labelledby`.
|
|
149
150
|
|
|
150
151
|
A `.menu` converts with its `.menu-label`s and `.menu-list`s, and so do the items in a list. An
|
|
151
152
|
item has no class to go by, so the codemod finds it by where it sits: a `<li>` whose nearest
|
|
@@ -264,20 +265,20 @@ as `items`.
|
|
|
264
265
|
|
|
265
266
|
```jsx
|
|
266
267
|
<span className="icon-text">
|
|
267
|
-
<span className="icon" aria-
|
|
268
|
+
<span className="icon" aria-hidden="true">
|
|
268
269
|
<i className="fas fa-home"></i>
|
|
269
270
|
</span>
|
|
270
271
|
<span>Home</span>
|
|
271
272
|
</span>
|
|
272
273
|
// becomes
|
|
273
|
-
<IconText iconProps={{ library: "fa", name: "home",
|
|
274
|
+
<IconText iconProps={{ library: "fa", name: "home", "aria-hidden": "true" }}>Home</IconText>
|
|
274
275
|
```
|
|
275
276
|
|
|
276
277
|
The glyph is read from the `<i>`: its Font Awesome style class (`fas`, `far`, `fa-solid`, ...) or
|
|
277
278
|
`mdi`, the one class that names the glyph (`fa-home` as `name: "home"`), and the rest as
|
|
278
279
|
`features`. `library` is always written, so a `ConfigProvider` with another `iconLibrary` doesn't
|
|
279
280
|
change what renders. The `.icon`'s own classes and attributes join the glyph's props as they
|
|
280
|
-
would on `Icon`,
|
|
281
|
+
would on `Icon`, under their own names.
|
|
281
282
|
|
|
282
283
|
It converts only when every `.icon` inside converts to `Icon` on its own and holds a bare, empty
|
|
283
284
|
`<i>` naming a Font Awesome or Material Design Icons glyph, and the only other children are those
|
|
@@ -76,7 +76,11 @@ attributes you want (usually both, with a real label), then re-run. `Navbar` ren
|
|
|
76
76
|
`role="navigation"` and `aria-label="main navigation"`, which Bulma's own navbar markup carries;
|
|
77
77
|
give the `<nav>` both, with your own label if you like. `Breadcrumb` renders
|
|
78
78
|
`aria-label="breadcrumbs"`, so give its `<nav>` an `aria-label`, whatever it says.
|
|
79
|
-
`Icon`
|
|
79
|
+
`Icon` hides an icon with no name, no `role` and no `tabIndex`, with `aria-hidden="true"`, and
|
|
80
|
+
makes one named by `aria-label` or `aria-labelledby` an image, with `role="img"`. Give a decorative
|
|
81
|
+
`.icon` `aria-hidden="true"`, and a meaningful one an `aria-label` that says what it means and
|
|
82
|
+
`role="img"`. One whose name is an expression may render with no name, so it needs a `role` of its
|
|
83
|
+
own.
|
|
80
84
|
`Pagination` renders Bulma's own `role="navigation"` and `aria-label="pagination"`, and
|
|
81
85
|
`Pagination.Previous`, `Pagination.Next` and `Pagination.Link` render `tabIndex={0}`, so give each
|
|
82
86
|
element the attribute it's missing.
|
|
@@ -6,7 +6,7 @@ license: MIT
|
|
|
6
6
|
|
|
7
7
|
# Optimizing CSS size with @allxsmith/bestax-bulma
|
|
8
8
|
|
|
9
|
-
The JS side is tree-shakable (the **entire** library is ~
|
|
9
|
+
The JS side is tree-shakable (the **entire** library is ~65 KB min+gzip). The stylesheet is
|
|
10
10
|
not: a prebuilt flavor ships all of Bulma + the bestax extras regardless of which components
|
|
11
11
|
the app renders. Judge stylesheet weight by the **gzipped** transfer size — never the raw
|
|
12
12
|
`dist/` number.
|
|
@@ -77,10 +77,14 @@ recommending it, grep the app's source for helper props on bestax components:
|
|
|
77
77
|
|
|
78
78
|
## Lever 2 — modular Sass build
|
|
79
79
|
|
|
80
|
-
Compile only the Bulma modules + bestax extras partials the app actually uses. Needs
|
|
81
|
-
|
|
80
|
+
Compile only the Bulma modules + bestax extras partials the app actually uses. Needs `bulma`
|
|
81
|
+
as a dependency of the app itself (under pnpm, the app's Sass can only load what the app lists)
|
|
82
|
+
and the `sass` compiler as a dev dependency (Bulma's own build tool — Vite compiles `.scss`
|
|
83
|
+
natively):
|
|
82
84
|
|
|
83
85
|
```sh
|
|
86
|
+
# with the project's own package manager (pnpm add, yarn add) if it isn't npm
|
|
87
|
+
npm install bulma
|
|
84
88
|
npm install -D sass
|
|
85
89
|
```
|
|
86
90
|
|
|
@@ -114,9 +118,9 @@ partial inventory, and a worked example are in `references/modular-build.md`.
|
|
|
114
118
|
|
|
115
119
|
## Lever 3 — import & icon-asset hygiene (minor)
|
|
116
120
|
|
|
117
|
-
- **Named imports.** `import * as Bestax from '@allxsmith/bestax-bulma'`
|
|
118
|
-
|
|
119
|
-
|
|
121
|
+
- **Named imports.** Convert `import * as Bestax from '@allxsmith/bestax-bulma'` to named
|
|
122
|
+
imports (`import { Button, Card } from …`). Any saving is on the JS side, so report it
|
|
123
|
+
honestly as minor.
|
|
120
124
|
- **Unused icon libraries.** Scaffolded apps may carry an icon library the app never uses:
|
|
121
125
|
icon-font packages in `package.json` (`@fortawesome/fontawesome-free`, `@mdi/font`,
|
|
122
126
|
`material-icons`, `material-symbols`) with their CSS imports in `src/main.*`, or Ionicons
|
|
@@ -7,11 +7,14 @@ This is the "Option C" pattern from the
|
|
|
7
7
|
## Prerequisites
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
+
# with the project's own package manager (pnpm add, yarn add) if it isn't npm
|
|
11
|
+
npm install bulma
|
|
10
12
|
npm install -D sass
|
|
11
13
|
```
|
|
12
14
|
|
|
13
15
|
`sass` is Bulma's own compiler, dev-only. Vite compiles `.scss` out of the box — no plugin.
|
|
14
|
-
`bulma`
|
|
16
|
+
`bulma` has to be a dependency of the app itself: bestax-bulma depends on it, but under pnpm's
|
|
17
|
+
default layout the app's Sass can only load the packages the app lists. The library
|
|
15
18
|
publishes its SCSS sources (`src/scss` ships in the npm package, exposed via the
|
|
16
19
|
`@allxsmith/bestax-bulma/scss/*` export).
|
|
17
20
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// under a ConfigProvider `classPrefix`, which the prefixed flavors read. This
|
|
6
6
|
// is global (even on a scoped Theme); `'system'` removes the attributes so
|
|
7
7
|
// Bulma follows the OS `prefers-color-scheme`. Wrap the app once at the root.
|
|
8
|
-
import
|
|
8
|
+
import { useState } from 'react';
|
|
9
9
|
import {
|
|
10
10
|
Theme,
|
|
11
11
|
Box,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// palette. The <Theme> component writes those CSS variables for you:
|
|
7
7
|
// - isRoot -> inject the variables globally at :root (use once, at the app root)
|
|
8
8
|
// - without isRoot -> wrap children in a <div> and scope the variables to it
|
|
9
|
-
import
|
|
9
|
+
import type { ReactNode } from 'react';
|
|
10
10
|
import {
|
|
11
11
|
Theme,
|
|
12
12
|
Button,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
|
|
18
18
|
// 1) Global brand theme at the app root.
|
|
19
19
|
// Hue is unitless; saturation and lightness are percentages.
|
|
20
|
-
export function ThemedApp({ children }: { children:
|
|
20
|
+
export function ThemedApp({ children }: { children: ReactNode }) {
|
|
21
21
|
return (
|
|
22
22
|
<Theme
|
|
23
23
|
isRoot
|
|
@@ -246,7 +246,9 @@ list it, so set it in your CSS or through a `style` prop.)
|
|
|
246
246
|
The two `range` variables paint a range calendar (`DateRangeInput`): the band between a range's
|
|
247
247
|
ends, and the fainter band shown while the end is still being picked. Both are mixed from
|
|
248
248
|
`--bulma-dateinput-cell-selected-bg`, so `color` and an override of the selected fill re-tint
|
|
249
|
-
them too.
|
|
249
|
+
them too. Inside a band, a nearby month's day reads `--bulma-dateinput-cell-color` rather than
|
|
250
|
+
`--bulma-dateinput-cell-other-month-color`, and today's tint leans a fifth of the way toward
|
|
251
|
+
`--bulma-text-strong`, so both stay readable on the band's color.
|
|
250
252
|
|
|
251
253
|
### DateRangeInput
|
|
252
254
|
|