create-bestax 3.3.1 → 3.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +10 -5
- package/dist/project-creator.d.ts.map +1 -1
- package/dist/project-creator.js +6 -1
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +6 -0
- package/package.json +1 -1
- package/templates/skills/bestax-icons/SKILL.md +78 -0
- package/templates/skills/bestax-icons/examples/icon-usage.tsx +80 -0
- package/templates/skills/bestax-icons/references/icon-libraries.md +131 -0
- package/templates/skills/bestax-layout-scaffold/SKILL.md +10 -3
- package/templates/skills/bestax-layout-scaffold/examples/card-grid.tsx +7 -0
- package/templates/skills/bestax-layout-scaffold/references/archetypes.md +11 -0
- package/templates/skills/bestax-layout-scaffold/references/layout-components.md +81 -1
- package/templates/skills/bestax-theming/references/css-variables.md +237 -2
- package/templates/skills/bestax-theming/references/themeable-components.md +37 -12
package/dist/constants.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export declare const MESSAGES: {
|
|
|
12
12
|
readonly PROJECT_NAME_REQUIRED: "Project name is required";
|
|
13
13
|
readonly PROJECT_NAME_TOO_LONG: "Project name too long";
|
|
14
14
|
readonly PROJECT_NAME_INVALID_CHARS: "Project name can only contain letters, numbers, dots, dashes and underscores";
|
|
15
|
+
readonly PROJECT_NAME_DOT: "Project name cannot start with a dot (names like \".\" or \"..\" would scaffold outside a new directory) — pass a directory name";
|
|
15
16
|
readonly OPERATION_CANCELLED: "✖ Operation cancelled";
|
|
16
17
|
readonly NO_TTY: string;
|
|
17
18
|
readonly DIRECTORY_NOT_EMPTY: (dir: string) => string;
|
|
@@ -41,6 +42,7 @@ export interface IconLibrary {
|
|
|
41
42
|
display: string;
|
|
42
43
|
color: typeof chalk.yellow;
|
|
43
44
|
packageName?: string;
|
|
45
|
+
packageVersion?: string;
|
|
44
46
|
importStatement?: string;
|
|
45
47
|
setupInstructions?: string;
|
|
46
48
|
}
|
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
|
|
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;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,MA+DF,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
|
@@ -10,6 +10,7 @@ export const MESSAGES = {
|
|
|
10
10
|
PROJECT_NAME_REQUIRED: 'Project name is required',
|
|
11
11
|
PROJECT_NAME_TOO_LONG: 'Project name too long',
|
|
12
12
|
PROJECT_NAME_INVALID_CHARS: 'Project name can only contain letters, numbers, dots, dashes and underscores',
|
|
13
|
+
PROJECT_NAME_DOT: 'Project name cannot start with a dot (names like "." or ".." would scaffold outside a new directory) — pass a directory name',
|
|
13
14
|
OPERATION_CANCELLED: '✖ Operation cancelled',
|
|
14
15
|
NO_TTY: 'No interactive terminal detected — cannot prompt for input.\n' +
|
|
15
16
|
'Re-run non-interactively with a project name and flags, e.g.:\n' +
|
|
@@ -113,6 +114,7 @@ export const ICON_LIBRARIES = [
|
|
|
113
114
|
display: 'Font Awesome',
|
|
114
115
|
color: chalk.blue,
|
|
115
116
|
packageName: '@fortawesome/fontawesome-free',
|
|
117
|
+
packageVersion: '^7.2.0',
|
|
116
118
|
importStatement: "import '@fortawesome/fontawesome-free/css/all.min.css';",
|
|
117
119
|
},
|
|
118
120
|
{
|
|
@@ -120,6 +122,7 @@ export const ICON_LIBRARIES = [
|
|
|
120
122
|
display: 'Material Design Icons',
|
|
121
123
|
color: chalk.cyan,
|
|
122
124
|
packageName: '@mdi/font',
|
|
125
|
+
packageVersion: '^7.4.47',
|
|
123
126
|
importStatement: "import '@mdi/font/css/materialdesignicons.min.css';",
|
|
124
127
|
},
|
|
125
128
|
{
|
|
@@ -134,6 +137,7 @@ export const ICON_LIBRARIES = [
|
|
|
134
137
|
display: 'Google Material Icons',
|
|
135
138
|
color: chalk.yellow,
|
|
136
139
|
packageName: 'material-icons',
|
|
140
|
+
packageVersion: '^1.13.14',
|
|
137
141
|
importStatement: "import 'material-icons';",
|
|
138
142
|
},
|
|
139
143
|
{
|
|
@@ -141,6 +145,7 @@ export const ICON_LIBRARIES = [
|
|
|
141
145
|
display: 'Material Symbols',
|
|
142
146
|
color: chalk.magenta,
|
|
143
147
|
packageName: 'material-symbols',
|
|
148
|
+
packageVersion: '^0.45.2',
|
|
144
149
|
importStatement: "import 'material-symbols';",
|
|
145
150
|
},
|
|
146
151
|
];
|
|
@@ -148,14 +153,14 @@ export const BULMA_FLAVORS = [
|
|
|
148
153
|
{
|
|
149
154
|
name: 'complete',
|
|
150
155
|
display: 'Complete (Recommended)',
|
|
151
|
-
description: 'Full Bulma CSS with all components and helpers',
|
|
156
|
+
description: 'Full Bulma CSS with all components and helpers (~82 KB gzip)',
|
|
152
157
|
color: chalk.green,
|
|
153
158
|
importStatement: "import '@allxsmith/bestax-bulma/bestax.css';",
|
|
154
159
|
},
|
|
155
160
|
{
|
|
156
161
|
name: 'prefixed',
|
|
157
162
|
display: 'Prefixed',
|
|
158
|
-
description: 'All classes prefixed with "bestax-" to avoid conflicts',
|
|
163
|
+
description: 'All classes prefixed with "bestax-" to avoid conflicts (~84 KB gzip)',
|
|
159
164
|
color: chalk.blue,
|
|
160
165
|
importStatement: "import '@allxsmith/bestax-bulma/versions/bestax-prefixed.css';",
|
|
161
166
|
needsPrefix: true,
|
|
@@ -163,14 +168,14 @@ export const BULMA_FLAVORS = [
|
|
|
163
168
|
{
|
|
164
169
|
name: 'no-helpers',
|
|
165
170
|
display: 'No Helpers',
|
|
166
|
-
description: 'Core components only, no utility classes',
|
|
171
|
+
description: 'Core components only, no utility classes — helper props need them (~67 KB gzip)',
|
|
167
172
|
color: chalk.yellow,
|
|
168
173
|
importStatement: "import '@allxsmith/bestax-bulma/versions/bestax-no-helpers.css';",
|
|
169
174
|
},
|
|
170
175
|
{
|
|
171
176
|
name: 'no-helpers-prefixed',
|
|
172
177
|
display: 'No Helpers, Prefixed',
|
|
173
|
-
description: 'Core components only with "bestax-" prefix',
|
|
178
|
+
description: 'Core components only with "bestax-" prefix (~69 KB gzip)',
|
|
174
179
|
color: chalk.magenta,
|
|
175
180
|
importStatement: "import '@allxsmith/bestax-bulma/versions/bestax-no-helpers-prefixed.css';",
|
|
176
181
|
needsPrefix: true,
|
|
@@ -178,7 +183,7 @@ export const BULMA_FLAVORS = [
|
|
|
178
183
|
{
|
|
179
184
|
name: 'no-dark-mode',
|
|
180
185
|
display: 'No Dark Mode',
|
|
181
|
-
description: 'Light mode only, smaller bundle size',
|
|
186
|
+
description: 'Light mode only, smaller bundle size (~70 KB gzip)',
|
|
182
187
|
color: chalk.cyan,
|
|
183
188
|
importStatement: "import '@allxsmith/bestax-bulma/versions/bestax-no-dark-mode.css';",
|
|
184
189
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-creator.d.ts","sourceRoot":"","sources":["../src/project-creator.ts"],"names":[],"mappings":"AA2BA,OAAO,EAML,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAIxB,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAAS;gBAEjB,YAAY,CAAC,EAAE,MAAM;IAI3B,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAa3D,sBAAsB,CAC1B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC;IAkBnB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAInC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjE,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC;IAiBV,gBAAgB,CACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAmDhB,OAAO,CAAC,WAAW;IA2BnB,OAAO,CAAC,YAAY;IAYd,gBAAgB,CACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"project-creator.d.ts","sourceRoot":"","sources":["../src/project-creator.ts"],"names":[],"mappings":"AA2BA,OAAO,EAML,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAIxB,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAAS;gBAEjB,YAAY,CAAC,EAAE,MAAM;IAI3B,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAa3D,sBAAsB,CAC1B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC;IAkBnB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAInC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjE,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC;IAiBV,gBAAgB,CACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAmDhB,OAAO,CAAC,WAAW;IA2BnB,OAAO,CAAC,YAAY;IAYd,gBAAgB,CACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAgJV,mBAAmB,CACvB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAmEV,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAwIvE"}
|
package/dist/project-creator.js
CHANGED
|
@@ -135,6 +135,10 @@ export class ProjectCreator {
|
|
|
135
135
|
const headEndMatch = htmlContent.match(/<\/head>/);
|
|
136
136
|
if (headEndMatch) {
|
|
137
137
|
const insertPosition = headEndMatch.index;
|
|
138
|
+
// The ionicons version is pinned to an immutable unpkg URL. SRI
|
|
139
|
+
// integrity attributes are deliberately not added: the ionicons ESM
|
|
140
|
+
// loader dynamically imports per-icon chunks that cannot carry
|
|
141
|
+
// integrity hashes, so entry-file SRI would give false assurance.
|
|
138
142
|
const ioniconScripts = ` <!-- Ionicons -->
|
|
139
143
|
<script type="module" src="https://unpkg.com/ionicons@8.0.13/dist/ionicons/ionicons.esm.js"></script>
|
|
140
144
|
<script nomodule src="https://unpkg.com/ionicons@8.0.13/dist/ionicons/ionicons.js"></script>
|
|
@@ -159,7 +163,8 @@ export class ProjectCreator {
|
|
|
159
163
|
packageJson.dependencies = {};
|
|
160
164
|
}
|
|
161
165
|
if (library.packageName) {
|
|
162
|
-
packageJson.dependencies[library.packageName] =
|
|
166
|
+
packageJson.dependencies[library.packageName] =
|
|
167
|
+
library.packageVersion ?? 'latest';
|
|
163
168
|
}
|
|
164
169
|
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
165
170
|
// Add import statement to main file
|
package/dist/validators.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"AAMA,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"AAMA,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAqBnE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD"}
|
package/dist/validators.js
CHANGED
|
@@ -6,6 +6,12 @@ export function validateProjectName(value) {
|
|
|
6
6
|
if (value.length > MAX_PROJECT_NAME_LENGTH) {
|
|
7
7
|
return MESSAGES.PROJECT_NAME_TOO_LONG;
|
|
8
8
|
}
|
|
9
|
+
// The regex below allows dots, so "." and ".." would pass and resolve to
|
|
10
|
+
// the current/parent directory — which --yes would then empty. Rejecting
|
|
11
|
+
// every leading-dot name closes that hole ("/" and "\" are already blocked).
|
|
12
|
+
if (value.startsWith('.')) {
|
|
13
|
+
return MESSAGES.PROJECT_NAME_DOT;
|
|
14
|
+
}
|
|
9
15
|
if (!PROJECT_NAME_REGEX.test(value)) {
|
|
10
16
|
return MESSAGES.PROJECT_NAME_INVALID_CHARS;
|
|
11
17
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bestax-icons
|
|
3
|
+
description: Use icons in an app built with @allxsmith/bestax-bulma — the Icon/IconText components and the five supported libraries (Font Awesome, Material Design Icons, Ionicons, Google Material Icons, Material Symbols). Use when adding an icon, choosing or configuring the app-wide icon library, fixing an icon that renders blank, pairing icons with text, or making icons accessible (decorative vs labeled).
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Icons with @allxsmith/bestax-bulma
|
|
8
|
+
|
|
9
|
+
`Icon` renders a Bulma icon container (`span.icon`) around a glyph from any of five icon
|
|
10
|
+
libraries behind one normalized API. `IconText` pairs icons with text. The library ships **no
|
|
11
|
+
icon fonts** — the chosen library's package (or CDN script) must be installed in the app.
|
|
12
|
+
|
|
13
|
+
## Quick start
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { ConfigProvider, Icon, IconText } from '@allxsmith/bestax-bulma';
|
|
17
|
+
|
|
18
|
+
// Set the library ONCE at the app root; <Icon> then never needs `library`.
|
|
19
|
+
<ConfigProvider iconLibrary="fa">
|
|
20
|
+
<App />
|
|
21
|
+
</ConfigProvider>;
|
|
22
|
+
|
|
23
|
+
// Inside the app:
|
|
24
|
+
<Icon name="rocket" ariaLabel="Launch" />;
|
|
25
|
+
<IconText iconProps={{ name: 'star', 'aria-hidden': 'true' }}>
|
|
26
|
+
Starred
|
|
27
|
+
</IconText>;
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## The five libraries
|
|
31
|
+
|
|
32
|
+
| Library | `iconLibrary` / `library` value | Name format | Example `name` |
|
|
33
|
+
| ---------------------- | ------------------------------- | ---------------------------- | --------------- |
|
|
34
|
+
| Font Awesome (default) | `'fa'` | kebab-case, no `fa-` prefix | `rocket` |
|
|
35
|
+
| Material Design Icons | `'mdi'` | kebab-case, no `mdi-` prefix | `rocket-launch` |
|
|
36
|
+
| Ionicons | `'ion'` | kebab-case | `rocket` |
|
|
37
|
+
| Google Material Icons | `'material-icons'` | snake_case (a text ligature) | `rocket_launch` |
|
|
38
|
+
| Material Symbols | `'material-symbols'` | snake_case (a text ligature) | `rocket_launch` |
|
|
39
|
+
|
|
40
|
+
⚠️ **The Ionicons value is `'ion'`, not `'ionicons'`.** The `npm create bestax` scaffold's
|
|
41
|
+
`--icon ionicons` flag maps to `iconLibrary="ion"` — passing `'ionicons'` to `ConfigProvider`
|
|
42
|
+
or `library` silently renders nothing.
|
|
43
|
+
|
|
44
|
+
**The same glyph has a different name per library** (`rocket` vs `rocket-launch` vs
|
|
45
|
+
`rocket_launch`). When an icon renders blank, the name format for the active library is the
|
|
46
|
+
first thing to check. A redundant `fa-`/`mdi-` prefix in `name` is tolerated (stripped), but
|
|
47
|
+
don't rely on it.
|
|
48
|
+
|
|
49
|
+
## Styling
|
|
50
|
+
|
|
51
|
+
- `size` — `'small' | 'medium' | 'large'` sizes the Bulma **container** (`is-small` ≈ 1rem,
|
|
52
|
+
`is-medium` ≈ 2rem, `is-large` ≈ 3rem box). To scale the **glyph**, use `features`
|
|
53
|
+
(Font Awesome `'fa-lg'`/`'fa-2x'`) or a Bulma text-size class (`'is-size-3'`).
|
|
54
|
+
- `variant` — per-library style: Font Awesome `solid` (default) / `regular` / `brands` /
|
|
55
|
+
`light` / `duotone` / `thin`; Material Icons `filled` (default) / `outlined` / `round` /
|
|
56
|
+
`sharp`; Material Symbols `outlined` (default) / `rounded` / `sharp`; Ionicons `outline` /
|
|
57
|
+
`sharp`. MDI has no variants. Note Material **Icons** uses `round`, Material **Symbols**
|
|
58
|
+
uses `rounded`.
|
|
59
|
+
- `features` — extra library classes, string or array: `'fa-spin'`, `['fa-lg', 'fa-border']`.
|
|
60
|
+
- Color via the helper props: `textColor="primary"`, `textColor="danger"`, etc.
|
|
61
|
+
|
|
62
|
+
## Accessibility
|
|
63
|
+
|
|
64
|
+
Every `Icon` renders `aria-label` (default `"icon"`).
|
|
65
|
+
|
|
66
|
+
- **Meaningful icon** (stands alone, conveys information): pass a descriptive
|
|
67
|
+
`ariaLabel="Delete item"`.
|
|
68
|
+
- **Decorative icon** (next to visible text that says the same thing, e.g. inside `IconText`
|
|
69
|
+
or a labeled `Button`): hide it from screen readers with `aria-hidden`:
|
|
70
|
+
`<Icon name="check" aria-hidden="true" />` — otherwise "icon" (or a duplicate label) is
|
|
71
|
+
announced alongside the text.
|
|
72
|
+
|
|
73
|
+
## References
|
|
74
|
+
|
|
75
|
+
- `references/icon-libraries.md` — per-library setup (install/import/CDN), the full
|
|
76
|
+
name-format and variant tables, `features` values, and the blank-icon troubleshooting list.
|
|
77
|
+
- `examples/icon-usage.tsx` — runnable example: ConfigProvider setup, sizes, variants,
|
|
78
|
+
colors, IconText, and decorative-vs-labeled patterns.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Icons with @allxsmith/bestax-bulma — the canonical patterns.
|
|
2
|
+
//
|
|
3
|
+
// The app must load the icon library itself (bestax ships no icon fonts):
|
|
4
|
+
// here Font Awesome, via `npm install @fortawesome/fontawesome-free` and
|
|
5
|
+
// `import '@fortawesome/fontawesome-free/css/all.min.css';` in main.tsx.
|
|
6
|
+
// Set the library ONCE on ConfigProvider ('fa' | 'mdi' | 'ion' |
|
|
7
|
+
// 'material-icons' | 'material-symbols' — Ionicons is 'ion', NOT 'ionicons');
|
|
8
|
+
// every <Icon> below then omits `library`.
|
|
9
|
+
import React from 'react';
|
|
10
|
+
import {
|
|
11
|
+
ConfigProvider,
|
|
12
|
+
Icon,
|
|
13
|
+
IconText,
|
|
14
|
+
Button,
|
|
15
|
+
Box,
|
|
16
|
+
Title,
|
|
17
|
+
} from '@allxsmith/bestax-bulma';
|
|
18
|
+
|
|
19
|
+
export function IconShowcase() {
|
|
20
|
+
return (
|
|
21
|
+
<ConfigProvider iconLibrary="fa">
|
|
22
|
+
<Box>
|
|
23
|
+
<Title size="5">Meaningful icons carry their own label</Title>
|
|
24
|
+
{/* Standalone icons convey information — give them a descriptive
|
|
25
|
+
ariaLabel (the default is just "icon"). */}
|
|
26
|
+
<Icon
|
|
27
|
+
name="triangle-exclamation"
|
|
28
|
+
textColor="warning"
|
|
29
|
+
ariaLabel="Warning"
|
|
30
|
+
/>
|
|
31
|
+
<Icon name="circle-check" textColor="success" ariaLabel="Success" />
|
|
32
|
+
|
|
33
|
+
<Title size="5" mt="4">
|
|
34
|
+
Decorative icons hide from screen readers
|
|
35
|
+
</Title>
|
|
36
|
+
{/* Next to visible text the icon repeats the message — aria-hidden
|
|
37
|
+
stops "icon" (or a duplicate) being announced. */}
|
|
38
|
+
<IconText iconProps={{ name: 'star', 'aria-hidden': 'true' }}>
|
|
39
|
+
Starred
|
|
40
|
+
</IconText>
|
|
41
|
+
<Button color="primary">
|
|
42
|
+
<Icon name="floppy-disk" aria-hidden="true" />
|
|
43
|
+
<span>Save</span>
|
|
44
|
+
</Button>
|
|
45
|
+
|
|
46
|
+
<Title size="5" mt="4">
|
|
47
|
+
Sizes, variants, features, color
|
|
48
|
+
</Title>
|
|
49
|
+
{/* `size` sizes the Bulma container; `features` scales the glyph. */}
|
|
50
|
+
<Icon name="rocket" size="large" features="fa-2x" ariaLabel="Launch" />
|
|
51
|
+
{/* Font Awesome styles come from `variant`; brands require it. */}
|
|
52
|
+
<Icon name="bell" variant="regular" ariaLabel="Notifications" />
|
|
53
|
+
<Icon name="github" variant="brands" ariaLabel="GitHub" />
|
|
54
|
+
{/* Spin + color via features and the textColor helper. */}
|
|
55
|
+
<Icon
|
|
56
|
+
name="spinner"
|
|
57
|
+
features="fa-spin"
|
|
58
|
+
textColor="info"
|
|
59
|
+
ariaLabel="Loading"
|
|
60
|
+
/>
|
|
61
|
+
|
|
62
|
+
<Title size="5" mt="4">
|
|
63
|
+
Multi-segment icon text
|
|
64
|
+
</Title>
|
|
65
|
+
<IconText
|
|
66
|
+
items={[
|
|
67
|
+
{
|
|
68
|
+
iconProps: { name: 'train', 'aria-hidden': 'true' },
|
|
69
|
+
text: 'Metro',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
iconProps: { name: 'arrow-right', 'aria-hidden': 'true' },
|
|
73
|
+
text: 'Airport',
|
|
74
|
+
},
|
|
75
|
+
]}
|
|
76
|
+
/>
|
|
77
|
+
</Box>
|
|
78
|
+
</ConfigProvider>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Icon libraries — setup, names, variants, troubleshooting
|
|
2
|
+
|
|
3
|
+
Facts an agent can act on for each of the five libraries `Icon` supports. The library ships no
|
|
4
|
+
icon fonts: the app must install the chosen library (the `npm create bestax` scaffold's
|
|
5
|
+
`--icon` flag does this; in an existing app, follow Setup below).
|
|
6
|
+
|
|
7
|
+
## How `Icon` renders
|
|
8
|
+
|
|
9
|
+
- `fa` / `mdi` — an `<i>` with CSS classes (`fas fa-rocket`, `mdi mdi-rocket-launch`).
|
|
10
|
+
- `material-icons` / `material-symbols` — an `<i>` whose **text content** is the name
|
|
11
|
+
(a font ligature): `<i class="material-icons">rocket_launch</i>`. That's why these names are
|
|
12
|
+
snake_case — they are literal text, not class names.
|
|
13
|
+
- `ion` — the `<ion-icon>` web component: `<ion-icon name="rocket-outline" />`.
|
|
14
|
+
|
|
15
|
+
The resolution order for the library is `library` prop → `ConfigProvider iconLibrary` → `'fa'`.
|
|
16
|
+
Set it once on `ConfigProvider` and omit `library` everywhere else.
|
|
17
|
+
|
|
18
|
+
## Font Awesome — `'fa'` (the default)
|
|
19
|
+
|
|
20
|
+
- **Setup:** `npm install @fortawesome/fontawesome-free` and
|
|
21
|
+
`import '@fortawesome/fontawesome-free/css/all.min.css';` once (e.g. `main.tsx`).
|
|
22
|
+
- **Scaffold flag:** `--icon fontawesome`.
|
|
23
|
+
- **Names:** kebab-case without the `fa-` prefix: `rocket`, `circle-check`, `magnifying-glass`.
|
|
24
|
+
A leading `fa-` in `name` is stripped automatically (so `fa-rocket` also works), but write
|
|
25
|
+
the bare name.
|
|
26
|
+
- **Variants** (`variant` → class): `solid` → `fas` (default), `regular` → `far`, `brands` →
|
|
27
|
+
`fab`, `light` → `fal`, `duotone` → `fad`, `thin` → `fat`. The free package includes only
|
|
28
|
+
solid, regular (partial), and brands — light/duotone/thin need a Font Awesome Pro kit.
|
|
29
|
+
- **Features:** Font Awesome utility classes — `'fa-lg'`, `'fa-2x'`…`'fa-10x'`, `'fa-spin'`,
|
|
30
|
+
`'fa-pulse'`, `'fa-border'`, `'fa-fw'`, `'fa-flip-horizontal'`, `'fa-rotate-90'`.
|
|
31
|
+
- Brand icons **require** `variant="brands"`: `<Icon name="github" variant="brands" />`.
|
|
32
|
+
|
|
33
|
+
## Material Design Icons — `'mdi'`
|
|
34
|
+
|
|
35
|
+
- **Setup:** `npm install @mdi/font` and
|
|
36
|
+
`import '@mdi/font/css/materialdesignicons.min.css';`.
|
|
37
|
+
- **Scaffold flag:** `--icon mdi`.
|
|
38
|
+
- **Names:** kebab-case without the `mdi-` prefix: `account`, `rocket-launch`,
|
|
39
|
+
`home-outline`. A leading `mdi-` is stripped automatically. Outline/off styles are part of
|
|
40
|
+
the **name** (`home-outline`, `bell-off`), not a variant.
|
|
41
|
+
- **Variants:** none — `variant` is ignored for MDI.
|
|
42
|
+
- **Features:** MDI helpers (`'mdi-24px'`, `'mdi-48px'`, `'mdi-spin'`, `'mdi-rotate-90'`) or
|
|
43
|
+
Bulma text-size classes (`'is-size-3'`).
|
|
44
|
+
|
|
45
|
+
## Ionicons — `'ion'` ⚠️ value is `ion`, not `ionicons`
|
|
46
|
+
|
|
47
|
+
- **Setup:** a CDN script pair in `index.html` (no npm package — it registers the
|
|
48
|
+
`<ion-icon>` web component):
|
|
49
|
+
|
|
50
|
+
```html
|
|
51
|
+
<script
|
|
52
|
+
type="module"
|
|
53
|
+
src="https://unpkg.com/ionicons@8.0.13/dist/ionicons/ionicons.esm.js"
|
|
54
|
+
></script>
|
|
55
|
+
<script
|
|
56
|
+
nomodule
|
|
57
|
+
src="https://unpkg.com/ionicons@8.0.13/dist/ionicons/ionicons.js"
|
|
58
|
+
></script>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
- **Scaffold flag:** `--icon ionicons` — which maps to `iconLibrary="ion"`. Passing
|
|
62
|
+
`'ionicons'` as the `library`/`iconLibrary` value renders nothing.
|
|
63
|
+
- **Names:** kebab-case: `rocket`, `heart`, `settings`.
|
|
64
|
+
- **Variants:** `outline` and `sharp` — appended to the name (`variant="outline"` +
|
|
65
|
+
`name="heart"` renders `<ion-icon name="heart-outline">`). Omit for the filled default.
|
|
66
|
+
- **Features:** not applicable (web component, not classes); size the container with `size`
|
|
67
|
+
or style via CSS.
|
|
68
|
+
|
|
69
|
+
## Google Material Icons — `'material-icons'`
|
|
70
|
+
|
|
71
|
+
- **Setup:** `npm install material-icons` and `import 'material-icons';`.
|
|
72
|
+
- **Scaffold flag:** `--icon material-icons`.
|
|
73
|
+
- **Names:** snake_case ligature text: `home`, `rocket_launch`, `shopping_cart`. A kebab-case
|
|
74
|
+
name will not match a ligature and renders as raw text.
|
|
75
|
+
- **Variants:** `filled` (default) / `outlined` / `round` / `sharp` — note **`round`**, not
|
|
76
|
+
`rounded`.
|
|
77
|
+
- **Features:** Bulma classes like `'is-size-1'` (the font scales with text size).
|
|
78
|
+
|
|
79
|
+
## Material Symbols — `'material-symbols'`
|
|
80
|
+
|
|
81
|
+
- **Setup:** `npm install material-symbols` and `import 'material-symbols';`.
|
|
82
|
+
- **Scaffold flag:** `--icon material-symbols`.
|
|
83
|
+
- **Names:** snake_case ligature text, same as Material Icons: `rocket_launch`.
|
|
84
|
+
- **Variants:** `outlined` (default) / `rounded` / `sharp` — note **`rounded`** here vs
|
|
85
|
+
Material Icons' `round`.
|
|
86
|
+
- **Features:** Bulma classes like `'is-size-1'`.
|
|
87
|
+
|
|
88
|
+
## One glyph, five names
|
|
89
|
+
|
|
90
|
+
| Glyph | fa | mdi | ion | material-icons / material-symbols |
|
|
91
|
+
| -------- | ------------------ | --------------- | ---------- | --------------------------------- |
|
|
92
|
+
| Rocket | `rocket` | `rocket-launch` | `rocket` | `rocket_launch` |
|
|
93
|
+
| Home | `house` / `home` | `home` | `home` | `home` |
|
|
94
|
+
| Settings | `gear` | `cog` | `settings` | `settings` |
|
|
95
|
+
| Search | `magnifying-glass` | `magnify` | `search` | `search` |
|
|
96
|
+
|
|
97
|
+
## Blank icon? Check in this order
|
|
98
|
+
|
|
99
|
+
1. **Library value** — `'ion'` not `'ionicons'`; the five valid values are `fa`, `mdi`,
|
|
100
|
+
`ion`, `material-icons`, `material-symbols`.
|
|
101
|
+
2. **Name format for that library** — kebab vs snake_case (see the table above); for
|
|
102
|
+
material-* a wrong name renders as literal text instead of a glyph.
|
|
103
|
+
3. **The library's CSS/script is actually loaded** — the import in `main.tsx` (or the
|
|
104
|
+
Ionicons scripts in `index.html`) must exist; bestax ships none of them.
|
|
105
|
+
4. **Variant availability** — Font Awesome free has no `light`/`duotone`/`thin`; brand
|
|
106
|
+
glyphs need `variant="brands"`.
|
|
107
|
+
|
|
108
|
+
## IconText
|
|
109
|
+
|
|
110
|
+
Pairs icon(s) with text inside a Bulma `icon-text` container. Single icon:
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
<IconText iconProps={{ name: 'check', 'aria-hidden': 'true' }}>Saved</IconText>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Multiple segments via `items`:
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
<IconText
|
|
120
|
+
items={[
|
|
121
|
+
{ iconProps: { name: 'train', 'aria-hidden': 'true' }, text: 'Metro' },
|
|
122
|
+
{
|
|
123
|
+
iconProps: { name: 'arrow-right', 'aria-hidden': 'true' },
|
|
124
|
+
text: 'Airport',
|
|
125
|
+
},
|
|
126
|
+
]}
|
|
127
|
+
/>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Icons inside `IconText` sit next to their visible text — mark them decorative with
|
|
131
|
+
`aria-hidden` (see SKILL.md's accessibility rules).
|
|
@@ -36,8 +36,13 @@ Centered; a collection of items → Card grid. For mixed requests, pick the domi
|
|
|
36
36
|
## Approach
|
|
37
37
|
|
|
38
38
|
- Compose pages from the shipped layout components — `Container`, `Section`, `Hero`, `Footer`,
|
|
39
|
-
`Level`, `Columns`/`Column`, `Navbar`, `Menu`, `Card`. There is **no `Tile`
|
|
40
|
-
grids
|
|
39
|
+
`Level`, `Columns`/`Column`, `Grid`/`Cell`, `Navbar`, `Menu`, `Card`. There is **no `Tile`
|
|
40
|
+
component**. For **uniform grids** (card grids, galleries — same-shaped items) prefer
|
|
41
|
+
`Grid`/`Cell`: CSS Grid gives equal-height cells for free (per row — each row's cells match
|
|
42
|
+
its tallest, same row-level behavior as the flex recipe). Use `Columns`/`Column` for
|
|
43
|
+
proportional or per-breakpoint column layouts — and when cards there must be equal height,
|
|
44
|
+
apply the flex recipe (`Column display="flex" flexDirection="column"` + `Card flexGrow="1"`;
|
|
45
|
+
`height: 100%` on the card doesn't help — the column's height is auto).
|
|
41
46
|
- Rely on Bulma's responsive defaults: `Columns` sit side by side on tablet and up and stack on
|
|
42
47
|
mobile. Add responsive `size*` props only to tune the breakpoints.
|
|
43
48
|
- For a `fixed="top"` `Navbar`, add the `has-navbar-fixed-top` class to `<html>` so content is not
|
|
@@ -74,7 +79,9 @@ color }}`. Set the app-wide icon library once with `<ConfigProvider iconLibrary=
|
|
|
74
79
|
|
|
75
80
|
- [ ] Map the request to one archetype; do not ask layout questions.
|
|
76
81
|
- [ ] Wrap page content in `Container` (+ `Section` for vertical rhythm).
|
|
77
|
-
- [ ] Use `
|
|
82
|
+
- [ ] Use `Grid`/`Cell` for uniform grids (equal heights per row, free); `Columns`/`Column`
|
|
83
|
+
for proportional or per-breakpoint side-by-side layout — with the flex recipe when its
|
|
84
|
+
cards must match height.
|
|
78
85
|
- [ ] For a fixed navbar, add `has-navbar-fixed-top` to `<html>`.
|
|
79
86
|
- [ ] Do not use `Tile` — it is not shipped.
|
|
80
87
|
- [ ] Style with helper props (`mt`/`p`, `textAlign`, `textColor`), not inline `style`.
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
// Card grid / catalog page — a collection of similar items.
|
|
2
2
|
// `<Columns isMultiline>` wraps cards onto new rows; the responsive column sizes
|
|
3
3
|
// give 1 card per row on mobile, 2 on tablet, 3 on desktop.
|
|
4
|
+
// Equal heights: each Column is a flex container and its Card grows to fill
|
|
5
|
+
// it (flexGrow="1"), so short blurbs don't leave ragged card bottoms.
|
|
6
|
+
// (`height: 100%` on the card would NOT work — it resolves against auto
|
|
7
|
+
// height. For uniform grids, Grid/Cell gives equal heights for free.)
|
|
4
8
|
import React from 'react';
|
|
5
9
|
import {
|
|
6
10
|
Section,
|
|
@@ -78,8 +82,11 @@ export default function CatalogPage() {
|
|
|
78
82
|
sizeMobile="full"
|
|
79
83
|
sizeTablet="half"
|
|
80
84
|
sizeDesktop="one-third"
|
|
85
|
+
display="flex"
|
|
86
|
+
flexDirection="column"
|
|
81
87
|
>
|
|
82
88
|
<Card
|
|
89
|
+
flexGrow="1"
|
|
83
90
|
image={product.image}
|
|
84
91
|
imageAlt={product.name}
|
|
85
92
|
header={product.name}
|
|
@@ -165,8 +165,11 @@ search results, "a grid of cards".
|
|
|
165
165
|
sizeMobile="full"
|
|
166
166
|
sizeTablet="half"
|
|
167
167
|
sizeDesktop="one-third"
|
|
168
|
+
display="flex"
|
|
169
|
+
flexDirection="column"
|
|
168
170
|
>
|
|
169
171
|
<Card
|
|
172
|
+
flexGrow="1"
|
|
170
173
|
image={item.image}
|
|
171
174
|
header={item.name}
|
|
172
175
|
footer={<span className="card-footer-item">{item.price}</span>}
|
|
@@ -183,6 +186,14 @@ search results, "a grid of cards".
|
|
|
183
186
|
**Responsive:** `isMultiline` wraps cards onto new rows; the `size*` props set the per-row count —
|
|
184
187
|
1 on mobile, 2 on tablet, 3 on desktop here. Change the fractions to change the column count.
|
|
185
188
|
|
|
189
|
+
**Equal heights:** the `display="flex" flexDirection="column"` on each `Column` plus
|
|
190
|
+
`flexGrow="1"` on the `Card` stretches every card to its row's height — without it, cards end
|
|
191
|
+
at their content and rows look ragged (`height: 100%` on the card doesn't help — it resolves
|
|
192
|
+
against the column's auto height). Alternatively
|
|
193
|
+
build the whole grid with `Grid`/`Cell` (`<Grid isFixed fixedColsMobile={1} fixedColsTablet={2}
|
|
194
|
+
fixedColsDesktop={3} gap={4}>`) — CSS Grid keeps cells equal-height for free; see the
|
|
195
|
+
`Grid / Cell` section in `layout-components.md`.
|
|
196
|
+
|
|
186
197
|
---
|
|
187
198
|
|
|
188
199
|
## Combining archetypes
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
Level,
|
|
13
13
|
Columns,
|
|
14
14
|
Column,
|
|
15
|
+
Grid,
|
|
16
|
+
Cell,
|
|
15
17
|
Navbar,
|
|
16
18
|
Menu,
|
|
17
19
|
Card,
|
|
@@ -26,7 +28,9 @@ Every component also accepts the shared Bulma helper props (`m`/`p` spacing, `te
|
|
|
26
28
|
> `textColor="grey"` / `bgColor="light"` not `style={{ color }}`. Spacing scale is `0`–`6` | `auto`
|
|
27
29
|
> (`4` = 1rem). Reserve `style`/CSS vars only for values the design system doesn't tokenize.
|
|
28
30
|
|
|
29
|
-
> **There is no `Tile` component.**
|
|
31
|
+
> **There is no `Tile` component.** For uniform grids (cards, galleries) use `Grid` / `Cell` —
|
|
32
|
+
> equal-height cells for free; for proportional or per-breakpoint layouts use
|
|
33
|
+
> `Columns` / `Column`.
|
|
30
34
|
|
|
31
35
|
## Container
|
|
32
36
|
|
|
@@ -127,6 +131,76 @@ type BulmaColumnSize =
|
|
|
127
131
|
> Columns **stack on mobile** by default and go side-by-side at the tablet breakpoint and up.
|
|
128
132
|
> Use the per-breakpoint `size*` props to control how many cells share a row at each width.
|
|
129
133
|
|
|
134
|
+
**Equal-height cards inside Columns** — columns are equal height, but a card inside one does
|
|
135
|
+
**not** stretch to fill it (and `height: 100%` on the card doesn't help — it resolves against
|
|
136
|
+
the column's auto height). Make the `Column` a flex container and let the card grow:
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
<Columns isMultiline>
|
|
140
|
+
{items.map(item => (
|
|
141
|
+
<Column
|
|
142
|
+
key={item.id}
|
|
143
|
+
sizeTablet="half"
|
|
144
|
+
sizeDesktop="one-third"
|
|
145
|
+
display="flex"
|
|
146
|
+
flexDirection="column"
|
|
147
|
+
>
|
|
148
|
+
<Card flexGrow="1">{item.blurb}</Card>
|
|
149
|
+
</Column>
|
|
150
|
+
))}
|
|
151
|
+
</Columns>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`display`, `flexDirection`, and `flexGrow` are helper props every component accepts;
|
|
155
|
+
`flexGrow` takes a string (`"1"`).
|
|
156
|
+
|
|
157
|
+
## Grid / Cell
|
|
158
|
+
|
|
159
|
+
Bulma's CSS Grid. **Preferred for uniform grids** — same-shaped items in a repeating pattern
|
|
160
|
+
(card grids, galleries, dashboards): CSS Grid gives **equal-height cells for free** (per row —
|
|
161
|
+
each row's cells match its tallest), with no flex recipe needed. Reach for `Columns`/`Column` instead when you need proportional or
|
|
162
|
+
per-breakpoint column _sizes_ (a 2/3 + 1/3 split, different counts per breakpoint).
|
|
163
|
+
|
|
164
|
+
**Grid**
|
|
165
|
+
|
|
166
|
+
| Prop | Type |
|
|
167
|
+
| ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
|
|
168
|
+
| `gap` / `columnGap` / `rowGap` | `0`–`8` (number or string, same scale as Columns' `gap`) |
|
|
169
|
+
| `minCol` | `1`–`32` (smart grid: min column width step, `is-col-min-X`) |
|
|
170
|
+
| `isFixed` | `boolean` (fixed column count instead of auto-fill) |
|
|
171
|
+
| `fixedCols` (+ `fixedColsMobile` / `fixedColsTablet` / `fixedColsDesktop` / `fixedColsWidescreen` / `fixedColsFullhd`) | `0`–`12` or `'auto'` (fixed grid only) |
|
|
172
|
+
|
|
173
|
+
**Cell**
|
|
174
|
+
|
|
175
|
+
| Prop | Type |
|
|
176
|
+
| ------------------------------------- | --------------------------------------- |
|
|
177
|
+
| `colStart` / `colFromEnd` / `colSpan` | `number` (manual column placement/span) |
|
|
178
|
+
| `rowStart` / `rowFromEnd` / `rowSpan` | `number` (manual row placement/span) |
|
|
179
|
+
|
|
180
|
+
By default the smart grid **auto-fills**: cells flow into as many columns as fit (tune the
|
|
181
|
+
minimum width with `minCol`). `isFixed` + `fixedCols*` pins an exact column count per
|
|
182
|
+
breakpoint instead.
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
// Uniform card grid — equal heights for free, responsive column count for free.
|
|
186
|
+
<Grid
|
|
187
|
+
isFixed
|
|
188
|
+
fixedColsMobile={1}
|
|
189
|
+
fixedColsTablet={2}
|
|
190
|
+
fixedColsDesktop={3}
|
|
191
|
+
gap={4}
|
|
192
|
+
>
|
|
193
|
+
{items.map(item => (
|
|
194
|
+
<Cell key={item.id}>
|
|
195
|
+
<Card header={item.name}>{item.blurb}</Card>
|
|
196
|
+
</Cell>
|
|
197
|
+
))}
|
|
198
|
+
</Grid>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
> To stretch each card to its cell's full (equal) height, the same `display="flex"
|
|
202
|
+
flexDirection="column"` + `flexGrow="1"` pattern applies to `Cell` + `Card`.
|
|
203
|
+
|
|
130
204
|
## Navbar
|
|
131
205
|
|
|
132
206
|
`<Navbar>` is the top bar. Subcomponents: `Navbar.Brand`, `Navbar.Item`, `Navbar.Link`,
|
|
@@ -150,6 +224,12 @@ flag to `Navbar.Menu active`. **A `fixed="top"` navbar requires `has-navbar-fixe
|
|
|
150
224
|
document.documentElement.classList.add('has-navbar-fixed-top');
|
|
151
225
|
```
|
|
152
226
|
|
|
227
|
+
**Routing:** in a routed app, don't use `href="#"` — render items as the router's link
|
|
228
|
+
component. `Menu.Item as={Link} to="/x"` and `Navbar.Item as={Link} to="/x"` both compile
|
|
229
|
+
without casts (their props allow extra keys). Drive `active` from `useLocation().pathname`.
|
|
230
|
+
Full patterns (including Buttons that navigate and Next.js `href`): the docs guide at
|
|
231
|
+
https://bestax.io/docs/guides/features/routing.
|
|
232
|
+
|
|
153
233
|
## Menu
|
|
154
234
|
|
|
155
235
|
`<Menu>` is a vertical sidebar menu. Subcomponents: `Menu.Label`, `Menu.List`, `Menu.Item`.
|
|
@@ -96,9 +96,10 @@ and numeric shades `--bulma-<c>-00` … `--bulma-<c>-95`.
|
|
|
96
96
|
| `--bulma-size-small` / `-normal` / `-medium` / `-large` | 0.75 / 1 / 1.25 / 1.5rem | via `bulmaVars` |
|
|
97
97
|
| `--bulma-weight-light/normal/medium/semibold/bold/extrabold` | 300 / 400 / 500 / 600 / 700 / 800 | via `bulmaVars` |
|
|
98
98
|
|
|
99
|
-
## Extras component variables
|
|
99
|
+
## Extras component variables
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
Every "Beyond Bulma" extra registers its own `--bulma-<component>-*` variables. They are
|
|
102
|
+
registered on the component's **own selector** (`.avatar`, `.dialog`, `.tooltip`, … —
|
|
102
103
|
`.bestax-avatar` etc. with the prefixed CSS flavor), not on `:root`. A value set on a wrapping
|
|
103
104
|
ancestor — including `Theme`'s `bulmaVars` on a wrapping `Theme` — is only _inherited_ and
|
|
104
105
|
always loses to the component-level declaration, so it will NOT take effect. Working overrides
|
|
@@ -108,6 +109,8 @@ target the component's own element instead: redeclare on the component's own cla
|
|
|
108
109
|
(`.avatar.big-avatar { --bulma-avatar-size: 3.5rem; }`), or set it via the component's `style`
|
|
109
110
|
prop. Several default to core theme vars above, so they already flow through a custom theme.
|
|
110
111
|
|
|
112
|
+
### Avatar / Avatars / Badge
|
|
113
|
+
|
|
111
114
|
| Variable | Default |
|
|
112
115
|
| ----------------------------------------------------------------- | -------------------------------- |
|
|
113
116
|
| `--bulma-avatar-size` | `48px` |
|
|
@@ -123,6 +126,238 @@ prop. Several default to core theme vars above, so they already flow through a c
|
|
|
123
126
|
| `--bulma-badge-dot-size` | `0.65em` |
|
|
124
127
|
| `--bulma-badge-inset-circle` / `--bulma-badge-animation-duration` | `12%` / `1.4s` |
|
|
125
128
|
|
|
129
|
+
The remaining extras register the variables below — names only; each default lives in the
|
|
130
|
+
component's SCSS partial under `bulma-ui/src/scss/` as a `$<name> !default` variable. The same
|
|
131
|
+
own-selector override rule applies.
|
|
132
|
+
|
|
133
|
+
### Autocomplete
|
|
134
|
+
|
|
135
|
+
`--bulma-autocomplete-border-color`, `--bulma-autocomplete-border-hover-color`,
|
|
136
|
+
`--bulma-autocomplete-dropdown-background`, `--bulma-autocomplete-dropdown-offset`,
|
|
137
|
+
`--bulma-autocomplete-dropdown-padding-y`, `--bulma-autocomplete-dropdown-radius`,
|
|
138
|
+
`--bulma-autocomplete-dropdown-shadow`, `--bulma-autocomplete-dropdown-z-index`,
|
|
139
|
+
`--bulma-autocomplete-empty-color`, `--bulma-autocomplete-header-footer-color`,
|
|
140
|
+
`--bulma-autocomplete-header-footer-padding`, `--bulma-autocomplete-header-footer-size`,
|
|
141
|
+
`--bulma-autocomplete-icon-hover-color`, `--bulma-autocomplete-item-color`,
|
|
142
|
+
`--bulma-autocomplete-item-disabled-color`, `--bulma-autocomplete-item-disabled-opacity`,
|
|
143
|
+
`--bulma-autocomplete-item-hover-background`, `--bulma-autocomplete-item-hover-color`,
|
|
144
|
+
`--bulma-autocomplete-item-large-padding`, `--bulma-autocomplete-item-medium-padding`,
|
|
145
|
+
`--bulma-autocomplete-item-padding`, `--bulma-autocomplete-item-small-padding`,
|
|
146
|
+
`--bulma-autocomplete-loader-active-color`, `--bulma-autocomplete-loader-border-color`,
|
|
147
|
+
`--bulma-autocomplete-loader-duration`, `--bulma-autocomplete-scrollbar-thumb`,
|
|
148
|
+
`--bulma-autocomplete-scrollbar-thumb-hover`, `--bulma-autocomplete-scrollbar-track`,
|
|
149
|
+
`--bulma-autocomplete-scrollbar-width`
|
|
150
|
+
|
|
151
|
+
### Carousel
|
|
152
|
+
|
|
153
|
+
`--bulma-carousel-arrow-background`, `--bulma-carousel-arrow-background-hover`,
|
|
154
|
+
`--bulma-carousel-arrow-color`, `--bulma-carousel-arrow-disabled-opacity`,
|
|
155
|
+
`--bulma-carousel-arrow-icon-size`, `--bulma-carousel-arrow-icon-size-mobile`,
|
|
156
|
+
`--bulma-carousel-arrow-offset`, `--bulma-carousel-arrow-offset-mobile`,
|
|
157
|
+
`--bulma-carousel-arrow-radius`, `--bulma-carousel-arrow-size`,
|
|
158
|
+
`--bulma-carousel-arrow-size-mobile`, `--bulma-carousel-fade-duration`,
|
|
159
|
+
`--bulma-carousel-indicator-background`, `--bulma-carousel-indicator-background-active`,
|
|
160
|
+
`--bulma-carousel-indicator-background-hover`, `--bulma-carousel-indicator-bar-height`,
|
|
161
|
+
`--bulma-carousel-indicator-bar-height-mobile`, `--bulma-carousel-indicator-bar-width`,
|
|
162
|
+
`--bulma-carousel-indicator-bar-width-mobile`, `--bulma-carousel-indicator-circle-size`,
|
|
163
|
+
`--bulma-carousel-indicator-gap`, `--bulma-carousel-indicator-gap-mobile`,
|
|
164
|
+
`--bulma-carousel-indicator-line-height`, `--bulma-carousel-indicator-line-height-mobile`,
|
|
165
|
+
`--bulma-carousel-indicator-line-radius`, `--bulma-carousel-indicator-line-width`,
|
|
166
|
+
`--bulma-carousel-indicator-line-width-mobile`, `--bulma-carousel-indicator-size`,
|
|
167
|
+
`--bulma-carousel-indicator-size-mobile`, `--bulma-carousel-overlay-arrow-background`,
|
|
168
|
+
`--bulma-carousel-overlay-arrow-background-hover`, `--bulma-carousel-overlay-arrow-color`,
|
|
169
|
+
`--bulma-carousel-overlay-indicator-background`,
|
|
170
|
+
`--bulma-carousel-overlay-indicator-background-active`,
|
|
171
|
+
`--bulma-carousel-overlay-indicator-background-hover`, `--bulma-carousel-transition-duration`
|
|
172
|
+
|
|
173
|
+
### Checkbox
|
|
174
|
+
|
|
175
|
+
`--bulma-checkbox-active-color`, `--bulma-checkbox-background`, `--bulma-checkbox-border-color`,
|
|
176
|
+
`--bulma-checkbox-border-width`, `--bulma-checkbox-check-color`,
|
|
177
|
+
`--bulma-checkbox-focus-shadow-size`, `--bulma-checkbox-indeterminate-color`,
|
|
178
|
+
`--bulma-checkbox-label-gap`, `--bulma-checkbox-radius`, `--bulma-checkbox-size`,
|
|
179
|
+
`--bulma-checkbox-transition-duration`
|
|
180
|
+
|
|
181
|
+
### Collapse
|
|
182
|
+
|
|
183
|
+
`--bulma-collapse-border-color`, `--bulma-collapse-group-gap`, `--bulma-collapse-header-weight`,
|
|
184
|
+
`--bulma-collapse-margin-bottom`, `--bulma-collapse-radius`,
|
|
185
|
+
`--bulma-collapse-trigger-icon-margin`, `--bulma-collapse-trigger-icon-size`
|
|
186
|
+
|
|
187
|
+
### DateInput
|
|
188
|
+
|
|
189
|
+
`--bulma-dateinput-cell-color`, `--bulma-dateinput-cell-disabled-color`,
|
|
190
|
+
`--bulma-dateinput-cell-hover-bg`, `--bulma-dateinput-cell-other-month-color`,
|
|
191
|
+
`--bulma-dateinput-cell-radius`, `--bulma-dateinput-cell-selected-bg`,
|
|
192
|
+
`--bulma-dateinput-cell-selected-color`, `--bulma-dateinput-cell-size`,
|
|
193
|
+
`--bulma-dateinput-cell-today-color`, `--bulma-dateinput-day-name-color`,
|
|
194
|
+
`--bulma-dateinput-day-name-size`, `--bulma-dateinput-header-padding`,
|
|
195
|
+
`--bulma-dateinput-min-width`, `--bulma-dateinput-nav-button-size`
|
|
196
|
+
|
|
197
|
+
### DateTimeInput
|
|
198
|
+
|
|
199
|
+
`--bulma-datetimeinput-gap`, `--bulma-datetimeinput-time-card-background`,
|
|
200
|
+
`--bulma-datetimeinput-time-card-border-color`, `--bulma-datetimeinput-time-card-padding`,
|
|
201
|
+
`--bulma-datetimeinput-time-card-radius`, `--bulma-datetimeinput-time-card-shadow`,
|
|
202
|
+
`--bulma-datetimeinput-time-overlay-background`, `--bulma-datetimeinput-time-overlay-blur`
|
|
203
|
+
|
|
204
|
+
### Dialog
|
|
205
|
+
|
|
206
|
+
`--bulma-dialog-animation-duration`, `--bulma-dialog-background`, `--bulma-dialog-body-color`,
|
|
207
|
+
`--bulma-dialog-body-line-height`, `--bulma-dialog-body-padding`, `--bulma-dialog-border-color`,
|
|
208
|
+
`--bulma-dialog-footer-gap`, `--bulma-dialog-footer-padding`, `--bulma-dialog-header-padding`,
|
|
209
|
+
`--bulma-dialog-icon-margin`, `--bulma-dialog-icon-size`, `--bulma-dialog-max-width`,
|
|
210
|
+
`--bulma-dialog-radius`, `--bulma-dialog-shadow`, `--bulma-dialog-title-color`,
|
|
211
|
+
`--bulma-dialog-title-size`, `--bulma-dialog-title-weight`, `--bulma-dialog-width`
|
|
212
|
+
|
|
213
|
+
### LinkButton
|
|
214
|
+
|
|
215
|
+
`--bulma-link-button-ghost-color`, `--bulma-link-button-ghost-hover-color`,
|
|
216
|
+
`--bulma-link-button-transition-duration`, `--bulma-link-button-underline-offset`
|
|
217
|
+
|
|
218
|
+
### Loading
|
|
219
|
+
|
|
220
|
+
`--bulma-loading-animation-duration`, `--bulma-loading-cancel-background`,
|
|
221
|
+
`--bulma-loading-cancel-border-color`, `--bulma-loading-cancel-color`,
|
|
222
|
+
`--bulma-loading-cancel-hover-border-color`, `--bulma-loading-cancel-hover-color`,
|
|
223
|
+
`--bulma-loading-cancel-radius`, `--bulma-loading-cancel-size`, `--bulma-loading-content-gap`,
|
|
224
|
+
`--bulma-loading-icon-border-width`, `--bulma-loading-icon-border-width-large`,
|
|
225
|
+
`--bulma-loading-icon-border-width-medium`, `--bulma-loading-icon-border-width-small`,
|
|
226
|
+
`--bulma-loading-icon-size`, `--bulma-loading-icon-size-large`,
|
|
227
|
+
`--bulma-loading-icon-size-medium`, `--bulma-loading-icon-size-small`,
|
|
228
|
+
`--bulma-loading-icon-spin-color`, `--bulma-loading-overlay-background`,
|
|
229
|
+
`--bulma-loading-overlay-fullpage-opacity`, `--bulma-loading-overlay-opacity`,
|
|
230
|
+
`--bulma-loading-overlay-opacity-dark`, `--bulma-loading-overlay-opacity-light`,
|
|
231
|
+
`--bulma-loading-overlay-opacity-opaque`, `--bulma-loading-text-color`,
|
|
232
|
+
`--bulma-loading-text-size`
|
|
233
|
+
|
|
234
|
+
### Numberinput
|
|
235
|
+
|
|
236
|
+
`--bulma-numberinput-disabled-opacity`, `--bulma-numberinput-rounded-button-size`,
|
|
237
|
+
`--bulma-numberinput-stepper-border-color`, `--bulma-numberinput-stepper-button-color`,
|
|
238
|
+
`--bulma-numberinput-stepper-button-hover-bg`, `--bulma-numberinput-stepper-button-hover-color`,
|
|
239
|
+
`--bulma-numberinput-stepper-width`
|
|
240
|
+
|
|
241
|
+
### Picker popover (DateInput / TimeInput / DateTimeInput)
|
|
242
|
+
|
|
243
|
+
`--bulma-picker-popover-animation-duration`, `--bulma-picker-popover-background`,
|
|
244
|
+
`--bulma-picker-popover-border-color`, `--bulma-picker-popover-offset`,
|
|
245
|
+
`--bulma-picker-popover-padding`, `--bulma-picker-popover-radius`,
|
|
246
|
+
`--bulma-picker-popover-shadow`, `--bulma-picker-popover-z-index`,
|
|
247
|
+
`--bulma-picker-trigger-color`, `--bulma-picker-trigger-hover-color`,
|
|
248
|
+
`--bulma-picker-trigger-width`
|
|
249
|
+
|
|
250
|
+
### Radio
|
|
251
|
+
|
|
252
|
+
`--bulma-radio-active-color`, `--bulma-radio-background`, `--bulma-radio-border-color`,
|
|
253
|
+
`--bulma-radio-border-width`, `--bulma-radio-dot-color`, `--bulma-radio-focus-shadow-size`,
|
|
254
|
+
`--bulma-radio-label-gap`, `--bulma-radio-size`, `--bulma-radio-transition-duration`
|
|
255
|
+
|
|
256
|
+
### Rate
|
|
257
|
+
|
|
258
|
+
`--bulma-rate-color-active`, `--bulma-rate-color-hover`, `--bulma-rate-color-inactive`,
|
|
259
|
+
`--bulma-rate-disabled-opacity`, `--bulma-rate-font-icon-size`,
|
|
260
|
+
`--bulma-rate-font-icon-size-large`, `--bulma-rate-font-icon-size-medium`,
|
|
261
|
+
`--bulma-rate-font-icon-size-small`, `--bulma-rate-gap`, `--bulma-rate-icon-size`,
|
|
262
|
+
`--bulma-rate-icon-size-large`, `--bulma-rate-icon-size-medium`, `--bulma-rate-icon-size-small`,
|
|
263
|
+
`--bulma-rate-pop-scale`, `--bulma-rate-score-color`, `--bulma-rate-score-weight`,
|
|
264
|
+
`--bulma-rate-spaced-gap`, `--bulma-rate-text-color`, `--bulma-rate-text-size`,
|
|
265
|
+
`--bulma-rate-transition-duration`
|
|
266
|
+
|
|
267
|
+
### Reveal
|
|
268
|
+
|
|
269
|
+
`--bulma-reveal-duration`, `--bulma-reveal-easing`, `--bulma-reveal-flip-angle`,
|
|
270
|
+
`--bulma-reveal-offset`, `--bulma-reveal-offset-large`, `--bulma-reveal-scale`
|
|
271
|
+
|
|
272
|
+
### Sidebar
|
|
273
|
+
|
|
274
|
+
`--bulma-sidebar-background`, `--bulma-sidebar-close-color`,
|
|
275
|
+
`--bulma-sidebar-close-hover-background`, `--bulma-sidebar-close-line-width`,
|
|
276
|
+
`--bulma-sidebar-close-radius`, `--bulma-sidebar-close-size`, `--bulma-sidebar-content-padding`,
|
|
277
|
+
`--bulma-sidebar-footer-border-color`, `--bulma-sidebar-footer-margin-top`,
|
|
278
|
+
`--bulma-sidebar-footer-padding`, `--bulma-sidebar-header-border-color`,
|
|
279
|
+
`--bulma-sidebar-header-margin-bottom`, `--bulma-sidebar-header-padding`,
|
|
280
|
+
`--bulma-sidebar-menu-item-active-background`, `--bulma-sidebar-menu-item-active-color`,
|
|
281
|
+
`--bulma-sidebar-menu-item-hover-background`, `--bulma-sidebar-menu-item-padding`,
|
|
282
|
+
`--bulma-sidebar-menu-item-radius`, `--bulma-sidebar-overlay-background`,
|
|
283
|
+
`--bulma-sidebar-scrollbar-color`, `--bulma-sidebar-scrollbar-color-hover`,
|
|
284
|
+
`--bulma-sidebar-scrollbar-width`, `--bulma-sidebar-shadow`,
|
|
285
|
+
`--bulma-sidebar-static-border-color`, `--bulma-sidebar-title-color`,
|
|
286
|
+
`--bulma-sidebar-title-size`, `--bulma-sidebar-title-weight`,
|
|
287
|
+
`--bulma-sidebar-transition-duration`, `--bulma-sidebar-width`
|
|
288
|
+
|
|
289
|
+
### Slider
|
|
290
|
+
|
|
291
|
+
`--bulma-slider-disabled-opacity`, `--bulma-slider-fill-color`,
|
|
292
|
+
`--bulma-slider-output-background`, `--bulma-slider-output-color`,
|
|
293
|
+
`--bulma-slider-output-font-size`, `--bulma-slider-output-font-weight`, `--bulma-slider-radius`,
|
|
294
|
+
`--bulma-slider-thumb-border`, `--bulma-slider-thumb-color`, `--bulma-slider-thumb-shadow`,
|
|
295
|
+
`--bulma-slider-thumb-size`, `--bulma-slider-thumb-size-large`,
|
|
296
|
+
`--bulma-slider-thumb-size-medium`, `--bulma-slider-thumb-size-small`,
|
|
297
|
+
`--bulma-slider-tick-color`, `--bulma-slider-tick-height`, `--bulma-slider-tick-label-color`,
|
|
298
|
+
`--bulma-slider-tick-label-font-size`, `--bulma-slider-tick-opacity`,
|
|
299
|
+
`--bulma-slider-tick-width`, `--bulma-slider-track-color`, `--bulma-slider-track-height`,
|
|
300
|
+
`--bulma-slider-track-height-large`, `--bulma-slider-track-height-medium`,
|
|
301
|
+
`--bulma-slider-track-height-small`, `--bulma-slider-transition-duration`,
|
|
302
|
+
`--bulma-slider-vertical-height`
|
|
303
|
+
|
|
304
|
+
### Steps
|
|
305
|
+
|
|
306
|
+
`--bulma-steps-animation-duration`, `--bulma-steps-content-margin-top`,
|
|
307
|
+
`--bulma-steps-default-color`, `--bulma-steps-divider-height`, `--bulma-steps-marker-background`,
|
|
308
|
+
`--bulma-steps-marker-font-size`, `--bulma-steps-marker-font-weight`,
|
|
309
|
+
`--bulma-steps-marker-size`, `--bulma-steps-marker-size-large`,
|
|
310
|
+
`--bulma-steps-marker-size-medium`, `--bulma-steps-marker-size-small`,
|
|
311
|
+
`--bulma-steps-navigation-margin-top`, `--bulma-steps-title-active-color`,
|
|
312
|
+
`--bulma-steps-title-active-weight`, `--bulma-steps-title-color`, `--bulma-steps-title-size`,
|
|
313
|
+
`--bulma-steps-title-weight`, `--bulma-steps-vertical-content-margin-left`,
|
|
314
|
+
`--bulma-steps-vertical-padding`
|
|
315
|
+
|
|
316
|
+
### Switch
|
|
317
|
+
|
|
318
|
+
`--bulma-switch-active-color`, `--bulma-switch-background`, `--bulma-switch-border-width`,
|
|
319
|
+
`--bulma-switch-circle-color`, `--bulma-switch-circle-shadow`, `--bulma-switch-focus-shadow`,
|
|
320
|
+
`--bulma-switch-height`, `--bulma-switch-label-gap`, `--bulma-switch-padding`,
|
|
321
|
+
`--bulma-switch-radius`, `--bulma-switch-thin-circle-size`, `--bulma-switch-thin-height`,
|
|
322
|
+
`--bulma-switch-transition-duration`, `--bulma-switch-width`
|
|
323
|
+
|
|
324
|
+
### Tabs
|
|
325
|
+
|
|
326
|
+
`--bulma-tabs-content-padding`, `--bulma-tabs-vertical-border-color`,
|
|
327
|
+
`--bulma-tabs-vertical-border-width`, `--bulma-tabs-vertical-min-width`
|
|
328
|
+
|
|
329
|
+
### Taginput
|
|
330
|
+
|
|
331
|
+
`--bulma-taginput-background`, `--bulma-taginput-border-color`, `--bulma-taginput-border-radius`,
|
|
332
|
+
`--bulma-taginput-dropdown-max-height`, `--bulma-taginput-height`, `--bulma-taginput-min-height`,
|
|
333
|
+
`--bulma-taginput-padding`, `--bulma-taginput-tag-gap`, `--bulma-taginput-transition-duration`
|
|
334
|
+
|
|
335
|
+
### TimeInput
|
|
336
|
+
|
|
337
|
+
`--bulma-timeinput-footer-padding`, `--bulma-timeinput-separator-color`,
|
|
338
|
+
`--bulma-timeinput-separator-size`, `--bulma-timeinput-wheel-bg`,
|
|
339
|
+
`--bulma-timeinput-wheel-color`, `--bulma-timeinput-wheel-dim-color`,
|
|
340
|
+
`--bulma-timeinput-wheel-gap`, `--bulma-timeinput-wheel-hover-bg`,
|
|
341
|
+
`--bulma-timeinput-wheel-item-height`, `--bulma-timeinput-wheel-mask`,
|
|
342
|
+
`--bulma-timeinput-wheel-radius`, `--bulma-timeinput-wheel-selected-bg`,
|
|
343
|
+
`--bulma-timeinput-wheel-selected-color`, `--bulma-timeinput-wheel-width`
|
|
344
|
+
|
|
345
|
+
### Toast
|
|
346
|
+
|
|
347
|
+
`--bulma-toast-action-hover-opacity`, `--bulma-toast-action-radius`,
|
|
348
|
+
`--bulma-toast-action-weight`, `--bulma-toast-animation-duration`, `--bulma-toast-background`,
|
|
349
|
+
`--bulma-toast-color`, `--bulma-toast-gap`, `--bulma-toast-max-width`,
|
|
350
|
+
`--bulma-toast-message-size`, `--bulma-toast-min-width`, `--bulma-toast-padding`,
|
|
351
|
+
`--bulma-toast-radius`, `--bulma-toast-shadow`
|
|
352
|
+
|
|
353
|
+
### Tooltip
|
|
354
|
+
|
|
355
|
+
`--bulma-tooltip-arrow-margin`, `--bulma-tooltip-arrow-size`, `--bulma-tooltip-background`,
|
|
356
|
+
`--bulma-tooltip-color`, `--bulma-tooltip-dashed-color`, `--bulma-tooltip-font-size`,
|
|
357
|
+
`--bulma-tooltip-font-weight`, `--bulma-tooltip-line-height`, `--bulma-tooltip-max-width`,
|
|
358
|
+
`--bulma-tooltip-multiline-width`, `--bulma-tooltip-padding`, `--bulma-tooltip-radius`,
|
|
359
|
+
`--bulma-tooltip-z-index`
|
|
360
|
+
|
|
126
361
|
## Dark mode (`Theme colorMode`)
|
|
127
362
|
|
|
128
363
|
Drive the light/dark scheme with the `Theme` component's **`colorMode`** prop —
|
|
@@ -28,18 +28,43 @@ Shades (`colorShade` / `backgroundColorShade`): `00, 05, 10, … 95, invert, lig
|
|
|
28
28
|
|
|
29
29
|
## Component `color` / `size` props (verbatim unions)
|
|
30
30
|
|
|
31
|
-
| Component
|
|
32
|
-
|
|
|
33
|
-
| `Button`
|
|
34
|
-
| `Notification`
|
|
35
|
-
| `Tag`
|
|
36
|
-
| `Box`
|
|
37
|
-
| `Message`
|
|
38
|
-
| `Input`
|
|
39
|
-
| `Avatar`
|
|
40
|
-
| `Badge`
|
|
41
|
-
| `Title`
|
|
42
|
-
| `SubTitle`
|
|
31
|
+
| Component | `color` accepts | `size` accepts | Notes |
|
|
32
|
+
| ------------------ | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
|
|
33
|
+
| `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` |
|
|
34
|
+
| `Notification` | the 17 `validColors` | — | also `isLight` |
|
|
35
|
+
| `Tag` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `normal \| medium \| large` | also `isRounded`, `isDelete`, `isHoverable` |
|
|
36
|
+
| `Box` | `primary \| link \| info \| success \| warning \| danger` | — | the 6 only; also `hasShadow` |
|
|
37
|
+
| `Message` | `primary \| link \| info \| success \| warning \| danger` | — | the 6 only |
|
|
38
|
+
| `Input` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isRounded`, `isStatic` |
|
|
39
|
+
| `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` |
|
|
40
|
+
| `Badge` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | pill background; default `danger` |
|
|
41
|
+
| `Title` | — (no `color`; use `textColor`) | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | also `isSpaced` |
|
|
42
|
+
| `SubTitle` | — (no `color`; use `textColor`) | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | — |
|
|
43
|
+
| `Autocomplete` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | the 6 only |
|
|
44
|
+
| `Checkbox` | `primary \| link \| info \| success \| warning \| danger` | `small \| normal \| medium \| large` | the 6 only |
|
|
45
|
+
| `DateInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded` |
|
|
46
|
+
| `DateTimeInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded` |
|
|
47
|
+
| `File` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isBoxed`, `isFullwidth` |
|
|
48
|
+
| `Hero` | the 17 `validColors` | `small \| medium \| large \| fullheight \| fullheight-with-navbar` | section background |
|
|
49
|
+
| `LinkButton` | `primary \| link \| info \| success \| warning \| danger \| white \| light \| dark \| black` | — | button-styled link; emits `link-button-<color>` |
|
|
50
|
+
| `Loading` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | spinner color; default light grey |
|
|
51
|
+
| `Navbar` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | — |
|
|
52
|
+
| `Numberinput` | `primary \| link \| info \| success \| warning \| danger \| light \| dark` | `small \| medium \| large` | also `inputColor` (the 6) for the inner input |
|
|
53
|
+
| `Pagination` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | — |
|
|
54
|
+
| `Panel` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | — |
|
|
55
|
+
| `Progress` | the 17 `validColors` | `small \| medium \| large` | — |
|
|
56
|
+
| `Radio` | `primary \| link \| info \| success \| warning \| danger` | `small \| normal \| medium \| large` | the 6 only |
|
|
57
|
+
| `Rate` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | the 6 only |
|
|
58
|
+
| `Select` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isRounded` |
|
|
59
|
+
| `Slider` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded`, `isCircle` |
|
|
60
|
+
| `Steps` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | the 6 only |
|
|
61
|
+
| `Switch` | `primary \| link \| info \| success \| warning \| danger` | `small \| normal \| medium \| large` | also `isRounded`, `isThin`, `isOutlined` |
|
|
62
|
+
| `Tabs` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | — |
|
|
63
|
+
| `Taginput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `tagColor` (the 6 + `dark \| light`) for the tags |
|
|
64
|
+
| `TextArea` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isRounded`, `isStatic` |
|
|
65
|
+
| `TimeInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | — |
|
|
66
|
+
| `Tooltip` | `primary \| link \| info \| success \| warning \| danger \| dark \| light` | `small \| medium \| large` | — |
|
|
67
|
+
| `Tr` / `Td` / `Th` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | table row/cell background |
|
|
43
68
|
|
|
44
69
|
The 6 brand colors (`primary, link, info, success, warning, danger`) are the ones a custom theme
|
|
45
70
|
recolors via the HSL trios (see `css-variables.md`). The greyscale and `white`/`light`/`dark`
|