bestax-mcp 0.0.0

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.
Files changed (144) hide show
  1. package/README.md +90 -0
  2. package/data/catalog.json +1869 -0
  3. package/data/components/Autocomplete.json +604 -0
  4. package/data/components/Avatar.json +220 -0
  5. package/data/components/Avatars.json +294 -0
  6. package/data/components/Badge.json +261 -0
  7. package/data/components/Block.json +105 -0
  8. package/data/components/Box.json +157 -0
  9. package/data/components/Breadcrumb.json +155 -0
  10. package/data/components/Button.json +599 -0
  11. package/data/components/Buttons.json +533 -0
  12. package/data/components/Card.json +506 -0
  13. package/data/components/Carousel.json +512 -0
  14. package/data/components/Cell.json +154 -0
  15. package/data/components/Checkbox.json +176 -0
  16. package/data/components/Checkboxes.json +240 -0
  17. package/data/components/Code.json +128 -0
  18. package/data/components/Collapse.json +218 -0
  19. package/data/components/Column.json +284 -0
  20. package/data/components/Columns.json +542 -0
  21. package/data/components/ConfigProvider.json +16 -0
  22. package/data/components/Container.json +149 -0
  23. package/data/components/Content.json +228 -0
  24. package/data/components/Control.json +484 -0
  25. package/data/components/DateInput.json +872 -0
  26. package/data/components/DateTimeInput.json +952 -0
  27. package/data/components/Delete.json +153 -0
  28. package/data/components/Dialog.json +285 -0
  29. package/data/components/Divider.json +68 -0
  30. package/data/components/Dropdown.json +353 -0
  31. package/data/components/Emphasis.json +99 -0
  32. package/data/components/Field.json +539 -0
  33. package/data/components/Figure.json +143 -0
  34. package/data/components/File.json +403 -0
  35. package/data/components/Footer.json +109 -0
  36. package/data/components/Grid.json +357 -0
  37. package/data/components/Hero.json +340 -0
  38. package/data/components/Icon.json +232 -0
  39. package/data/components/IconText.json +307 -0
  40. package/data/components/Image.json +166 -0
  41. package/data/components/Input.json +583 -0
  42. package/data/components/Level.json +332 -0
  43. package/data/components/Link.json +154 -0
  44. package/data/components/LinkButton.json +247 -0
  45. package/data/components/ListItem.json +101 -0
  46. package/data/components/Loading.json +323 -0
  47. package/data/components/Media.json +345 -0
  48. package/data/components/Menu.json +317 -0
  49. package/data/components/Message.json +303 -0
  50. package/data/components/Modal.json +444 -0
  51. package/data/components/Navbar.json +996 -0
  52. package/data/components/Notification.json +165 -0
  53. package/data/components/Numberinput.json +364 -0
  54. package/data/components/OrderedList.json +189 -0
  55. package/data/components/Pagination.json +619 -0
  56. package/data/components/Panel.json +582 -0
  57. package/data/components/Paragraph.json +107 -0
  58. package/data/components/Pre.json +114 -0
  59. package/data/components/Progress.json +137 -0
  60. package/data/components/Radio.json +164 -0
  61. package/data/components/Radios.json +240 -0
  62. package/data/components/Rate.json +466 -0
  63. package/data/components/Reveal.json +177 -0
  64. package/data/components/Section.json +123 -0
  65. package/data/components/Select.json +526 -0
  66. package/data/components/Sidebar.json +488 -0
  67. package/data/components/Skeleton.json +162 -0
  68. package/data/components/Slider.json +534 -0
  69. package/data/components/Span.json +100 -0
  70. package/data/components/Steps.json +452 -0
  71. package/data/components/Strong.json +105 -0
  72. package/data/components/SubTitle.json +233 -0
  73. package/data/components/Switch.json +291 -0
  74. package/data/components/Table.json +490 -0
  75. package/data/components/Tabs.json +592 -0
  76. package/data/components/Tag.json +197 -0
  77. package/data/components/Taginput.json +587 -0
  78. package/data/components/Tags.json +181 -0
  79. package/data/components/TextArea.json +483 -0
  80. package/data/components/Theme.json +65 -0
  81. package/data/components/TimeInput.json +906 -0
  82. package/data/components/Title.json +240 -0
  83. package/data/components/Toast.json +308 -0
  84. package/data/components/Tooltip.json +212 -0
  85. package/data/components/UnorderedList.json +149 -0
  86. package/data/components/Valid value constants.json +16 -0
  87. package/data/components/classNames.json +65 -0
  88. package/data/components/useBulmaClasses.json +169 -0
  89. package/data/components/usePrefixedClassNames.json +25 -0
  90. package/data/skills/bestax-custom-component/SKILL.md +196 -0
  91. package/data/skills/bestax-custom-component/examples/stat-card.tsx +105 -0
  92. package/data/skills/bestax-custom-component/references/api.md +90 -0
  93. package/data/skills/bestax-custom-component/references/component-catalog.md +149 -0
  94. package/data/skills/bestax-custom-component/references/library-contributor.md +395 -0
  95. package/data/skills/bestax-custom-component/references/patterns.md +136 -0
  96. package/data/skills/bestax-form/SKILL.md +254 -0
  97. package/data/skills/bestax-form/references/api.md +103 -0
  98. package/data/skills/bestax-form/references/patterns.md +210 -0
  99. package/data/skills/bestax-icons/SKILL.md +80 -0
  100. package/data/skills/bestax-icons/examples/icon-usage.tsx +80 -0
  101. package/data/skills/bestax-icons/references/icon-libraries.md +131 -0
  102. package/data/skills/bestax-layout-scaffold/SKILL.md +196 -0
  103. package/data/skills/bestax-layout-scaffold/examples/app-shell.tsx +86 -0
  104. package/data/skills/bestax-layout-scaffold/examples/card-grid.tsx +106 -0
  105. package/data/skills/bestax-layout-scaffold/examples/centered.tsx +56 -0
  106. package/data/skills/bestax-layout-scaffold/examples/content-page.tsx +90 -0
  107. package/data/skills/bestax-layout-scaffold/examples/landing.tsx +122 -0
  108. package/data/skills/bestax-layout-scaffold/references/archetypes.md +246 -0
  109. package/data/skills/bestax-layout-scaffold/references/layout-components.md +269 -0
  110. package/data/skills/bestax-migrate/SKILL.md +78 -0
  111. package/data/skills/bestax-migrate/references/component-map.md +91 -0
  112. package/data/skills/bestax-migrate/references/css-migration.md +100 -0
  113. package/data/skills/bestax-migrate/references/prop-map.md +48 -0
  114. package/data/skills/bestax-migrate/references/unmappables.md +124 -0
  115. package/data/skills/bestax-optimize/SKILL.md +131 -0
  116. package/data/skills/bestax-optimize/references/modular-build.md +173 -0
  117. package/data/skills/bestax-theming/SKILL.md +117 -0
  118. package/data/skills/bestax-theming/examples/dark-mode.tsx +38 -0
  119. package/data/skills/bestax-theming/examples/theme-config.tsx +60 -0
  120. package/data/skills/bestax-theming/references/css-variables.md +466 -0
  121. package/data/skills/bestax-theming/references/themeable-components.md +119 -0
  122. package/data/skills.json +148 -0
  123. package/dist/data.d.ts +131 -0
  124. package/dist/data.d.ts.map +1 -0
  125. package/dist/data.js +111 -0
  126. package/dist/format.d.ts +37 -0
  127. package/dist/format.d.ts.map +1 -0
  128. package/dist/format.js +178 -0
  129. package/dist/helper-props.d.ts +57 -0
  130. package/dist/helper-props.d.ts.map +1 -0
  131. package/dist/helper-props.js +249 -0
  132. package/dist/index.d.ts +3 -0
  133. package/dist/index.d.ts.map +1 -0
  134. package/dist/index.js +18 -0
  135. package/dist/search.d.ts +32 -0
  136. package/dist/search.d.ts.map +1 -0
  137. package/dist/search.js +194 -0
  138. package/dist/server.d.ts +28 -0
  139. package/dist/server.d.ts.map +1 -0
  140. package/dist/server.js +616 -0
  141. package/dist/version.d.ts +29 -0
  142. package/dist/version.d.ts.map +1 -0
  143. package/dist/version.js +147 -0
  144. package/package.json +70 -0
@@ -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).
@@ -0,0 +1,196 @@
1
+ ---
2
+ name: bestax-layout-scaffold
3
+ description: Scaffold a complete, responsive page layout with @allxsmith/bestax-bulma — app shells/dashboards, marketing/landing pages, centered auth/settings pages, and card-grid catalogs. Use when building a full page or overall app layout (not a single component).
4
+ license: MIT
5
+ ---
6
+
7
+ # Scaffolding a page layout with @allxsmith/bestax-bulma
8
+
9
+ Turn a high-level request ("admin dashboard", "landing page", "login screen", "product catalog")
10
+ into a complete responsive page built from bestax-bulma layout components.
11
+
12
+ ## Behavioral rule
13
+
14
+ Select an archetype from the request and build it in one shot. Do **not** ask layout questions
15
+ ("how many columns?", "where should the nav go?", "what width?") — infer the structure from the
16
+ request and proceed. The archetype determines the structure; fill it with the requested content.
17
+
18
+ Ask **at most one** clarifying question, and only for a high-level fork the request genuinely does
19
+ not imply: whether the page is **public-facing** (marketing) or an **internal tool** (authenticated
20
+ app). When the request already signals this ("dashboard", "admin", "landing", "login", "pricing"),
21
+ skip the question and default.
22
+
23
+ ## Select an archetype
24
+
25
+ | Request signals | Archetype |
26
+ | ---------------------------------------------------------------------- | ------------- |
27
+ | dashboard, admin, console, internal tool, authenticated app, "sidebar" | **App shell** |
28
+ | landing, marketing, homepage, product/pricing page, public site | **Landing** |
29
+ | login, sign up, auth, settings, checkout, a single focused form | **Centered** |
30
+ | catalog, gallery, products, listing, "grid of cards", search results | **Card grid** |
31
+
32
+ Default when ambiguous: internal tool → App shell; public-facing → Landing; one focused task →
33
+ Centered; a collection of items → Card grid. For mixed requests, pick the dominant intent (e.g.
34
+ "admin dashboard with a product list" → App shell whose main column holds a Card grid).
35
+
36
+ ## Approach
37
+
38
+ - Compose pages from the shipped layout components — `Container`, `Section`, `Hero`, `Footer`,
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).
46
+ - Rely on Bulma's responsive defaults: `Columns` sit side by side on tablet and up and stack on
47
+ mobile. Add responsive `size*` props only to tune the breakpoints.
48
+ - Interactive extras don't share a state API — never transfer one by analogy:
49
+ `Collapse trigger={node} open/defaultOpen onOpen/onClose`, `Tabs value={i}/onChange`
50
+ (each `Tabs.Tab`/`Tabs.Content.Item` requires `index={i}`, and `Tabs.Content` must be a
51
+ **child of `<Tabs>`** — the active-tab context lives on it; a sibling panel never
52
+ switches), `Dropdown active/onActiveChange`,
53
+ `Steps value={i}/onStepClick items={[{label, icon?}]}` (child form is `Steps.Step`, not
54
+ `Steps.Item`). `Reveal cascade` staggers only its **direct children** — to stagger a grid,
55
+ put `<Reveal delay={i * 80}>` inside each `Cell`, not around the container.
56
+ - Link lists (footer nav, sidebars): a bare `UnorderedList` of `ListItem`s is already
57
+ marker-less and flush — Bulma's reset unstyles `ul` — so no prop or CSS is needed;
58
+ bullets appear only inside `Content`.
59
+ - `Navbar.Burger`/`Navbar.Menu` are **controlled** — wire the same `active` state to both:
60
+ `active` on `Navbar.Menu` shows/hides the mobile menu, while `active` + `onClick` on
61
+ `Navbar.Burger` make the burger toggle it and animate. Left unwired, clicking the burger
62
+ does nothing (no error, silent failure). For a `fixed="top"` `Navbar`, add the
63
+ `has-navbar-fixed-top` class to `<html>` so content is not hidden behind it — the library
64
+ does not do this automatically, and an inline padding offset is not a substitute.
65
+ - **Style with helper props — no inline `style`, no raw Bulma `className`s.** Before writing
66
+ `style={{ … }}` anywhere, translate each declaration with the mapping table below — the helper
67
+ props cover the common cases. Bare markup has wrapper elements that take all
68
+ helper props: `<Span textSize="7" textColor="grey">`, `Paragraph`, `Strong` — never a raw
69
+ `<span className="is-size-7 has-text-grey">`. Table cells: `Th`/`Td` take `textAlign="right"`,
70
+ `textWeight`, `textSize` directly (their `color` prop colors the cell; for muted cell text
71
+ wrap content in `Span textColor="grey"`). Set the app-wide icon library once with
72
+ `<ConfigProvider iconLibrary="…">` at the root rather than `library` on every `<Icon>`.
73
+ - **Decorative CSS is budgeted: three compact rules, ≤13 lines per app — comments count:
74
+ at most one short inline note, never a file-header comment block — every value derived
75
+ from `--bulma-*`.** A marketing page gets at most one hero wash, one alternating section
76
+ band, and one featured-card ring, applied via `className` — no resets (Bulma ships one;
77
+ body/list margins are already zero) and no grid textures, masks, or multi-layer backdrops;
78
+ the components carry the design:
79
+
80
+ ```css
81
+ .hero-wash {
82
+ background-image: radial-gradient(
83
+ 60rem 30rem at 20% -10%,
84
+ hsl(var(--bulma-primary-h) var(--bulma-primary-s) 50% / 0.2),
85
+ transparent 60%
86
+ );
87
+ }
88
+ .section-alt {
89
+ background: var(--bulma-scheme-main-bis); /* next band: -ter */
90
+ }
91
+ .featured-ring {
92
+ --bulma-shadow: 0 0 0 2px var(--bulma-primary);
93
+ }
94
+ ```
95
+
96
+ The ring works by overriding the **upstream token**, not the component's own var: `.card`
97
+ and `.box` re-declare `--bulma-card-shadow`/`--bulma-box-shadow` from `--bulma-shadow` on
98
+ their own selector, so setting _those_ from an ancestor never wins (same for
99
+ `--bulma-box-radius`; `--bulma-card-radius` is a literal with no ancestor route at all).
100
+ It has to be a CSS rule rather than `<Theme bulmaVars={{ '--bulma-shadow': … }}>`, because
101
+ `bulmaVars` is a closed typed record and `--bulma-shadow` is not one of its keys — that
102
+ exact call **does not compile**, and it was the single most repeated invention across this
103
+ library's cold-start evals. Either way the subtree stays theme- and dark-mode-aware.
104
+
105
+ - **CTAs on a colored hero must stay legible in both schemes.** On a fixed-color surface
106
+ (`Hero color="primary"`, a dark banner), use **filled** buttons — `color="light"` or
107
+ `color="primary" isInverted` — never a thin `isOutlined` secondary: a light outline + light
108
+ label on a dark surface is low-contrast and gets worse under OS dark mode. And when the page's
109
+ design is single-mode (a fixed light or dark look), pin it at the root —
110
+ `<Theme isRoot colorMode="light">` — so a visitor's OS dark mode can't flip Bulma's text
111
+ colors out from under the fixed palette (details: the `bestax-theming` skill's contrast rules).
112
+
113
+ ## Three components core Bulma will talk you out of
114
+
115
+ Most of this library's additions get found on their own, because nothing in Bulma does the
116
+ job. These three do not: each has a Bulma near-miss close enough to stop the search. Across
117
+ 44 cold-start builds, `Dialog` was used **zero** times and `LinkButton` in two thirds — and
118
+ every miss shipped the "not this" column instead.
119
+
120
+ | You need | Use | Not this |
121
+ | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
122
+ | A brief confirmation after an action, self-dismissing | `Toast` — mount `<ToastContainer position="top-right" />` once at the app root, then `toast.success('Saved')` (also `.danger`/`.warning`/`.info`) from anywhere | `Notification`/`Message` — static page elements you have to place, position and dismiss yourself |
123
+ | A confirm or alert the user must answer before anything | `Dialog` — mount `<DialogContainer />` at the root, then `if (await dialog.confirm({ title, message })) …` | `Modal` — an empty shell; the title, message, button row and confirm/cancel wiring are all yours to rebuild |
124
+ | A control that reads as text or a link but _does_ something | `LinkButton` (`variant="text" \| "ghost" \| "underline"`, optional `color`) | `<a href="#">`/`<div onClick>` (no keyboard or screen-reader support) or `Button color="text"` (still button-shaped) |
125
+
126
+ Mounting a container without ever calling `toast.*`/`dialog.*` is not usage — the container is
127
+ the mount point, the imperative call is the thing that shows something. Both also work as
128
+ ordinary controlled components when you would rather hold the state yourself —
129
+ `<Toast message … duration onClose>`, `<Dialog isOpen title message type onConfirm onCancel>` —
130
+ but in an app with more than one call site the root container plus the imperative helper is
131
+ less wiring, not more.
132
+
133
+ ## Inline style → helper prop mapping
134
+
135
+ Look up the declaration you were about to inline. The spacing, typography, and flex helpers
136
+ below are on every component; `textColor`/`bgColor` are on the content components you'll
137
+ target (`Box`, `Block`, `Title`, `Content`, `Hero`, `Card`, …) — the ones with a semantic
138
+ `color` variant (`Tag`, `Tabs`, `Panel`) take `color` instead; wrap content in a `Block` if
139
+ you need a text color there. `Notification` is the mixed case: it takes `textColor`, but its
140
+ background comes from the semantic `color` prop, not `bgColor`.
141
+
142
+ | Inline style you're about to write | Helper props instead |
143
+ | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
144
+ | `marginTop: '1rem'` (any margin/padding) | `mt="4"` — `m`/`mt`/`mx`/`p`/`py`/… scale: `1`=0.25rem, `2`=0.5rem, `3`=0.75rem, `4`=1rem, `5`=1.5rem, `6`=3rem (nearest step) |
145
+ | `textAlign: 'center'` | `textAlign="centered"` (also `left`, `right`, `justified`) |
146
+ | `color: '#…'` | `textColor` with the nearest Bulma color: `primary`, `link`, `info`, `success`, `warning`, `danger`, `white`, `black`, `grey` (+ `grey-light`, `grey-dark`, …) |
147
+ | `backgroundColor: '#…'` | `bgColor` (same palette) |
148
+ | `fontSize: …` | `textSize="1"`…`"7"` (`1` largest) — for headings use `Title`/`SubTitle` `size` |
149
+ | `fontWeight: …` | `textWeight`: `light`, `normal`, `medium`, `semibold`, `bold` |
150
+ | `textTransform`, italics | `textTransform`: `uppercase`, `lowercase`, `capitalized`, `italic` |
151
+ | `display: 'flex'` + flex properties | same-named props: `display="flex"`, `flexDirection`, `justifyContent`, `alignItems`, `flexWrap` |
152
+ | `height: '100%'` on a flex child | `flexGrow="1"` |
153
+ | `display: 'none'` | `visibility="hidden"`, or responsive `display*` props (`displayMobile`, `displayTablet`, …) |
154
+ | `gap: …` in a flex layout | no `gap` helper exists — space children with `m*` margins; `Grid` and `Columns` take a `gap` prop, so prefer those there |
155
+
156
+ No helper matches (e.g. `maxWidth`, a one-off gradient)? Add a named class to the project
157
+ stylesheet (`src/App.css` in a scaffolded app) and pass it via `className` — still never
158
+ inline `style`.
159
+
160
+ ## References
161
+
162
+ - `references/layout-components.md` — the layout component inventory: real prop names, types, and
163
+ accepted values, plus subcomponent nesting.
164
+ - `references/archetypes.md` — the four archetypes: selection criteria, JSX skeleton, and responsive
165
+ behavior.
166
+
167
+ ## Examples
168
+
169
+ - `examples/app-shell.tsx` — fixed `Navbar` + sidebar `Menu` + content (dashboard).
170
+ - `examples/landing.tsx` — fixed `Navbar` (controlled burger) + `Hero` + `Section`s + `Footer`.
171
+ - `examples/centered.tsx` — centered single column (auth/settings).
172
+ - `examples/card-grid.tsx` — multiline `Columns` of `Card`s (catalog).
173
+ - `examples/content-page.tsx` — hero + feature cards + CTA styled with helper props (no inline
174
+ `style`), wrapped in `ConfigProvider`.
175
+
176
+ ## Checklist
177
+
178
+ - [ ] Map the request to one archetype; do not ask layout questions.
179
+ - [ ] Wrap page content in `Container` (+ `Section` for vertical rhythm).
180
+ - [ ] Use `Grid`/`Cell` for uniform grids (equal heights per row, free); `Columns`/`Column`
181
+ for proportional or per-breakpoint side-by-side layout — with the flex recipe when its
182
+ cards must match height.
183
+ - [ ] Wire `active` state to **both** `Navbar.Burger` and `Navbar.Menu` (they are controlled).
184
+ - [ ] For a fixed navbar, add `has-navbar-fixed-top` to `<html>`.
185
+ - [ ] Do not use `Tile` — it is not shipped.
186
+ - [ ] Action feedback goes through `Toast`, a confirmation through `Dialog`, a text-styled
187
+ action through `LinkButton` — not `Notification`, `Modal` or a bare `<a>`.
188
+ - [ ] Style with helper props, not inline `style` — translate via the mapping table; values
189
+ with no helper get a named class in the stylesheet, never `style={{}}`. No raw Bulma
190
+ `className`s either (`Span`/`Paragraph` wrap bare text; `Th`/`Td` take `textAlign`/`textWeight`).
191
+ - [ ] Decorative CSS ≤13 lines total incl. comments — no file-header comment (hero wash +
192
+ section band + featured-card ring), `--bulma-*`-derived; no resets — Bulma ships one.
193
+ The ring sets `--bulma-shadow` in a CSS rule; `Theme bulmaVars` has no such key.
194
+ - [ ] Set the icon library once via `<ConfigProvider iconLibrary="…">` at the root.
195
+ - [ ] Site built? ~800 KB raw / ~82 KB gzip CSS is the expected default-flavor size — to shrink
196
+ it, run the `bestax-optimize` skill (measure first).
@@ -0,0 +1,86 @@
1
+ // App shell with sidebar — fixed top Navbar + a narrow Menu column beside the
2
+ // main content. The admin/dashboard default.
3
+ //
4
+ // A fixed-top navbar needs the `has-navbar-fixed-top` class on <html> so the page
5
+ // is padded below it — Bulma requires this and the library does NOT add it for
6
+ // you. In a real app set it statically in index.html; the useEffect below is the
7
+ // fallback for a conditionally-mounted navbar (and keeps this file self-contained).
8
+ // The columns sit side by side on tablet and up, and stack (menu above
9
+ // content) on mobile.
10
+ //
11
+ // `ConfigProvider` wraps the shell once at the root to set the app-wide icon
12
+ // library (so <Icon> needs no `library` prop) and, optionally, a class prefix.
13
+ import React, { useEffect, useState } from 'react';
14
+ import {
15
+ ConfigProvider,
16
+ Navbar,
17
+ Menu,
18
+ Container,
19
+ Columns,
20
+ Column,
21
+ Section,
22
+ Title,
23
+ Box,
24
+ } from '@allxsmith/bestax-bulma';
25
+
26
+ export default function AdminShell() {
27
+ const [menuOpen, setMenuOpen] = useState(false);
28
+
29
+ useEffect(() => {
30
+ document.documentElement.classList.add('has-navbar-fixed-top');
31
+ return () => {
32
+ document.documentElement.classList.remove('has-navbar-fixed-top');
33
+ };
34
+ }, []);
35
+
36
+ return (
37
+ <ConfigProvider iconLibrary="fa">
38
+ <Navbar fixed="top" color="dark">
39
+ <Navbar.Brand>
40
+ <Navbar.Item href="#">Acme Admin</Navbar.Item>
41
+ <Navbar.Burger
42
+ active={menuOpen}
43
+ onClick={() => setMenuOpen(open => !open)}
44
+ aria-label="menu"
45
+ aria-expanded={menuOpen}
46
+ />
47
+ </Navbar.Brand>
48
+ <Navbar.Menu active={menuOpen}>
49
+ <Navbar.End>
50
+ <Navbar.Item href="#">Docs</Navbar.Item>
51
+ <Navbar.Item href="#">Account</Navbar.Item>
52
+ </Navbar.End>
53
+ </Navbar.Menu>
54
+ </Navbar>
55
+
56
+ <Container fluid>
57
+ <Columns>
58
+ <Column size={3} sizeWidescreen={2}>
59
+ <Menu>
60
+ <Menu.Label>General</Menu.Label>
61
+ <Menu.List>
62
+ <Menu.Item active href="#">
63
+ Dashboard
64
+ </Menu.Item>
65
+ <Menu.Item href="#">Customers</Menu.Item>
66
+ <Menu.Item href="#">Orders</Menu.Item>
67
+ </Menu.List>
68
+ <Menu.Label>Admin</Menu.Label>
69
+ <Menu.List>
70
+ <Menu.Item href="#">Team</Menu.Item>
71
+ <Menu.Item href="#">Settings</Menu.Item>
72
+ </Menu.List>
73
+ </Menu>
74
+ </Column>
75
+
76
+ <Column>
77
+ <Section>
78
+ <Title size="3">Dashboard</Title>
79
+ <Box>Main content area — drop dashboard widgets here.</Box>
80
+ </Section>
81
+ </Column>
82
+ </Columns>
83
+ </Container>
84
+ </ConfigProvider>
85
+ );
86
+ }
@@ -0,0 +1,106 @@
1
+ // Card grid / catalog page — a collection of similar items.
2
+ // `<Columns isMultiline>` wraps cards onto new rows; the responsive column sizes
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.)
8
+ import React from 'react';
9
+ import {
10
+ Section,
11
+ Container,
12
+ Title,
13
+ Columns,
14
+ Column,
15
+ Card,
16
+ } from '@allxsmith/bestax-bulma';
17
+
18
+ interface Product {
19
+ id: number;
20
+ name: string;
21
+ price: string;
22
+ image: string;
23
+ blurb: string;
24
+ }
25
+
26
+ const PRODUCTS: Product[] = [
27
+ {
28
+ id: 1,
29
+ name: 'Aurora Lamp',
30
+ price: '$48',
31
+ image: 'https://picsum.photos/seed/1/600/400',
32
+ blurb: 'Warm ambient light.',
33
+ },
34
+ {
35
+ id: 2,
36
+ name: 'Drift Chair',
37
+ price: '$220',
38
+ image: 'https://picsum.photos/seed/2/600/400',
39
+ blurb: 'Ergonomic and airy.',
40
+ },
41
+ {
42
+ id: 3,
43
+ name: 'Stone Mug',
44
+ price: '$18',
45
+ image: 'https://picsum.photos/seed/3/600/400',
46
+ blurb: 'Hand-thrown ceramic.',
47
+ },
48
+ {
49
+ id: 4,
50
+ name: 'Field Notebook',
51
+ price: '$12',
52
+ image: 'https://picsum.photos/seed/4/600/400',
53
+ blurb: 'Pocket-sized, lined.',
54
+ },
55
+ {
56
+ id: 5,
57
+ name: 'Trail Bottle',
58
+ price: '$26',
59
+ image: 'https://picsum.photos/seed/5/600/400',
60
+ blurb: 'Insulated steel.',
61
+ },
62
+ {
63
+ id: 6,
64
+ name: 'Linen Throw',
65
+ price: '$64',
66
+ image: 'https://picsum.photos/seed/6/600/400',
67
+ blurb: 'Soft, breathable.',
68
+ },
69
+ ];
70
+
71
+ export default function CatalogPage() {
72
+ return (
73
+ <Section>
74
+ <Container>
75
+ <Title size="3" mb="5">
76
+ Catalog
77
+ </Title>
78
+ <Columns isMultiline>
79
+ {PRODUCTS.map(product => (
80
+ <Column
81
+ key={product.id}
82
+ sizeMobile="full"
83
+ sizeTablet="half"
84
+ sizeDesktop="one-third"
85
+ display="flex"
86
+ flexDirection="column"
87
+ >
88
+ <Card
89
+ flexGrow="1"
90
+ image={product.image}
91
+ imageAlt={product.name}
92
+ header={product.name}
93
+ // Card wraps each footer item in .card-footer-item itself —
94
+ // no raw span/className needed (and a literal class would
95
+ // break under ConfigProvider classPrefix).
96
+ footer={product.price}
97
+ >
98
+ <p>{product.blurb}</p>
99
+ </Card>
100
+ </Column>
101
+ ))}
102
+ </Columns>
103
+ </Container>
104
+ </Section>
105
+ );
106
+ }
@@ -0,0 +1,56 @@
1
+ // Centered single-column page — auth, settings, focused forms.
2
+ // A narrow column is centered with `<Columns isCentered>`; on mobile the column
3
+ // becomes full width automatically.
4
+ import React from 'react';
5
+ import {
6
+ Section,
7
+ Container,
8
+ Columns,
9
+ Column,
10
+ Box,
11
+ Title,
12
+ SubTitle,
13
+ Input,
14
+ Button,
15
+ } from '@allxsmith/bestax-bulma';
16
+
17
+ export default function LoginPage() {
18
+ return (
19
+ <Section>
20
+ <Container>
21
+ <Columns isCentered>
22
+ <Column
23
+ size="half"
24
+ sizeTablet="two-thirds"
25
+ sizeDesktop="half"
26
+ sizeWidescreen="one-third"
27
+ >
28
+ <Box>
29
+ <Title size="4" textAlign="centered">
30
+ Sign in
31
+ </Title>
32
+ <SubTitle size="6" textAlign="centered" textColor="grey">
33
+ Welcome back
34
+ </SubTitle>
35
+ <Input
36
+ label="Email"
37
+ type="email"
38
+ iconLeftName="envelope"
39
+ placeholder="you@example.com"
40
+ />
41
+ <Input
42
+ label="Password"
43
+ type="password"
44
+ iconLeftName="lock"
45
+ placeholder="••••••••"
46
+ />
47
+ <Button color="primary" isFullWidth mt="4">
48
+ Sign in
49
+ </Button>
50
+ </Box>
51
+ </Column>
52
+ </Columns>
53
+ </Container>
54
+ </Section>
55
+ );
56
+ }