create-bestax 2.2.0 → 3.1.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 (30) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +2 -0
  3. package/dist/constants.d.ts +3 -0
  4. package/dist/constants.d.ts.map +1 -1
  5. package/dist/constants.js +27 -6
  6. package/dist/project-creator.d.ts +2 -0
  7. package/dist/project-creator.d.ts.map +1 -1
  8. package/dist/project-creator.js +27 -3
  9. package/dist/prompts.d.ts +1 -0
  10. package/dist/prompts.d.ts.map +1 -1
  11. package/dist/prompts.js +9 -0
  12. package/package.json +4 -3
  13. package/templates/skills/bestax-custom-component/SKILL.md +389 -0
  14. package/templates/skills/bestax-custom-component/references/api.md +77 -0
  15. package/templates/skills/bestax-custom-component/references/patterns.md +133 -0
  16. package/templates/skills/bestax-form/SKILL.md +209 -0
  17. package/templates/skills/bestax-form/references/api.md +102 -0
  18. package/templates/skills/bestax-form/references/patterns.md +210 -0
  19. package/templates/skills/bestax-layout-scaffold/SKILL.md +66 -0
  20. package/templates/skills/bestax-layout-scaffold/examples/app-shell.tsx +80 -0
  21. package/templates/skills/bestax-layout-scaffold/examples/card-grid.tsx +98 -0
  22. package/templates/skills/bestax-layout-scaffold/examples/centered.tsx +56 -0
  23. package/templates/skills/bestax-layout-scaffold/examples/landing.tsx +77 -0
  24. package/templates/skills/bestax-layout-scaffold/references/archetypes.md +183 -0
  25. package/templates/skills/bestax-layout-scaffold/references/layout-components.md +181 -0
  26. package/templates/skills/bestax-theming/SKILL.md +73 -0
  27. package/templates/skills/bestax-theming/examples/dark-mode.tsx +38 -0
  28. package/templates/skills/bestax-theming/examples/theme-config.tsx +58 -0
  29. package/templates/skills/bestax-theming/references/css-variables.md +130 -0
  30. package/templates/skills/bestax-theming/references/themeable-components.md +74 -0
@@ -0,0 +1,183 @@
1
+ # Layout archetypes
2
+
3
+ Four named, composable page patterns. For each: **when to pick it**, the **JSX skeleton**, and its
4
+ **responsive behavior**. Map the request to one archetype and build it — do not ask the user layout
5
+ questions. Full runnable versions live in `examples/`.
6
+
7
+ ---
8
+
9
+ ## 1. App shell with sidebar
10
+
11
+ **Pick when:** the request is an internal/authenticated tool — dashboard, admin, console, back
12
+ office, or anything that mentions a persistent sidebar/navigation. The default for "build me an
13
+ app".
14
+
15
+ **Skeleton:**
16
+
17
+ ```tsx
18
+ <>
19
+ <Navbar fixed="top" color="dark">
20
+ <Navbar.Brand>
21
+ <Navbar.Item href="#">Brand</Navbar.Item>
22
+ <Navbar.Burger
23
+ active={open}
24
+ onClick={() => setOpen(o => !o)}
25
+ aria-label="menu"
26
+ />
27
+ </Navbar.Brand>
28
+ <Navbar.Menu active={open}>
29
+ <Navbar.End>
30
+ <Navbar.Item href="#">Account</Navbar.Item>
31
+ </Navbar.End>
32
+ </Navbar.Menu>
33
+ </Navbar>
34
+
35
+ <Container fluid>
36
+ <Columns>
37
+ <Column size={3} sizeWidescreen={2}>
38
+ <Menu>
39
+ <Menu.Label>General</Menu.Label>
40
+ <Menu.List>
41
+ <Menu.Item active href="#">
42
+ Dashboard
43
+ </Menu.Item>
44
+ <Menu.Item href="#">Customers</Menu.Item>
45
+ </Menu.List>
46
+ </Menu>
47
+ </Column>
48
+ <Column>
49
+ <Section>{/* main content */}</Section>
50
+ </Column>
51
+ </Columns>
52
+ </Container>
53
+ </>
54
+ ```
55
+
56
+ **Required:** add `has-navbar-fixed-top` to `<html>` (see `examples/app-shell.tsx`) so content is
57
+ not hidden behind the fixed navbar.
58
+
59
+ **Responsive:** the navbar collapses to a burger on mobile (`Navbar.Burger` + `Navbar.Menu active`).
60
+ The sidebar and content columns sit side by side on tablet and up, and stack (menu above content)
61
+ on mobile.
62
+
63
+ ---
64
+
65
+ ## 2. Marketing / landing
66
+
67
+ **Pick when:** the request is a public-facing page — landing, homepage, marketing, product or
68
+ pricing page. The default for "build me a site/page".
69
+
70
+ **Skeleton:**
71
+
72
+ ```tsx
73
+ <>
74
+ <Hero color="primary" size="medium">
75
+ <Hero.Body>
76
+ <Container textAlign="centered">
77
+ <Title size="1">Headline</Title>
78
+ <SubTitle size="3">Supporting line.</SubTitle>
79
+ <Buttons isCentered>
80
+ <Button color="light" size="large">
81
+ Primary CTA
82
+ </Button>
83
+ </Buttons>
84
+ </Container>
85
+ </Hero.Body>
86
+ </Hero>
87
+
88
+ <Section size="large">
89
+ <Container>
90
+ <Columns>
91
+ <Column>
92
+ <Box>{/* feature */}</Box>
93
+ </Column>
94
+ <Column>
95
+ <Box>{/* feature */}</Box>
96
+ </Column>
97
+ <Column>
98
+ <Box>{/* feature */}</Box>
99
+ </Column>
100
+ </Columns>
101
+ </Container>
102
+ </Section>
103
+
104
+ <Footer>
105
+ <Container>
106
+ <Content textAlign="centered">{/* footer */}</Content>
107
+ </Container>
108
+ </Footer>
109
+ </>
110
+ ```
111
+
112
+ **Responsive:** `Section`s already stack vertically. The feature `Columns` collapse to one feature
113
+ per row on mobile. Use `Hero size="large"` / `"fullheight"` for a taller hero.
114
+
115
+ ---
116
+
117
+ ## 3. Centered single-column
118
+
119
+ **Pick when:** the request is one focused task — login, sign up, auth, settings, checkout, or a
120
+ single standalone form/panel.
121
+
122
+ **Skeleton:**
123
+
124
+ ```tsx
125
+ <Section>
126
+ <Container>
127
+ <Columns isCentered>
128
+ <Column size="half" sizeWidescreen="one-third">
129
+ <Box>{/* form / panel */}</Box>
130
+ </Column>
131
+ </Columns>
132
+ </Container>
133
+ </Section>
134
+ ```
135
+
136
+ **Responsive:** the centered column is narrow on desktop and becomes full width on mobile. Tighten
137
+ or widen via the `size*` breakpoint props (`one-third` desktop, `half` tablet, full mobile).
138
+
139
+ ---
140
+
141
+ ## 4. Card grid / catalog
142
+
143
+ **Pick when:** the request is a collection of similar items — catalog, gallery, products, listing,
144
+ search results, "a grid of cards".
145
+
146
+ **Skeleton:**
147
+
148
+ ```tsx
149
+ <Section>
150
+ <Container>
151
+ <Columns isMultiline>
152
+ {items.map(item => (
153
+ <Column
154
+ key={item.id}
155
+ sizeMobile="full"
156
+ sizeTablet="half"
157
+ sizeDesktop="one-third"
158
+ >
159
+ <Card
160
+ image={item.image}
161
+ header={item.name}
162
+ footer={<span className="card-footer-item">{item.price}</span>}
163
+ >
164
+ {item.blurb}
165
+ </Card>
166
+ </Column>
167
+ ))}
168
+ </Columns>
169
+ </Container>
170
+ </Section>
171
+ ```
172
+
173
+ **Responsive:** `isMultiline` wraps cards onto new rows; the `size*` props set the per-row count —
174
+ 1 on mobile, 2 on tablet, 3 on desktop here. Change the fractions to change the column count.
175
+
176
+ ---
177
+
178
+ ## Combining archetypes
179
+
180
+ Archetypes nest. An "admin dashboard with a product list" is **App shell** whose main `Column`
181
+ holds a **Card grid**. A "settings page inside the app" is **App shell** whose main column holds a
182
+ **Centered** panel. Pick the outer archetype from the dominant intent, then place another inside
183
+ its content area.
@@ -0,0 +1,181 @@
1
+ # Layout component inventory
2
+
3
+ Self-contained reference for the `@allxsmith/bestax-bulma` layout components. All values are
4
+ source-verified. Import everything from the package root:
5
+
6
+ ```tsx
7
+ import {
8
+ Container,
9
+ Section,
10
+ Hero,
11
+ Footer,
12
+ Level,
13
+ Columns,
14
+ Column,
15
+ Navbar,
16
+ Menu,
17
+ Card,
18
+ } from '@allxsmith/bestax-bulma';
19
+ ```
20
+
21
+ Every component also accepts the shared Bulma helper props (`m`/`p` spacing, `textAlign`,
22
+ `textColor`, `bgColor`, etc.).
23
+
24
+ > **There is no `Tile` component.** Build grids and nested layouts with `Columns` / `Column`.
25
+
26
+ ## Container
27
+
28
+ `<Container>` centers and constrains page content.
29
+
30
+ | Prop | Type | Notes |
31
+ | --------------------------------- | --------------------------------------- | ----------------------------------------- |
32
+ | `fluid` | `boolean` | Full width with a small gutter. |
33
+ | `widescreen` / `fullhd` | `boolean` | Only constrain at that breakpoint and up. |
34
+ | `breakpoint` | `'tablet' \| 'desktop' \| 'widescreen'` | Max-width breakpoint. |
35
+ | `isMax` | `boolean` | Use the `is-max-*` width. |
36
+ | `color` / `textColor` / `bgColor` | Bulma color | — |
37
+
38
+ ## Section
39
+
40
+ `<Section>` adds vertical page rhythm (padding).
41
+
42
+ | Prop | Type |
43
+ | --------------------------------- | ---------------------------------------- |
44
+ | `size` | `'medium' \| 'large'` (omit for default) |
45
+ | `color` / `textColor` / `bgColor` | Bulma color |
46
+
47
+ ## Hero
48
+
49
+ `<Hero>` is a full-width banner. Subcomponents: `Hero.Head`, `Hero.Body`, `Hero.Foot`.
50
+
51
+ | Prop | Type |
52
+ | ---------------------- | ---------------------------------------------------------------------------- |
53
+ | `color` | Bulma color |
54
+ | `size` | `'small' \| 'medium' \| 'large' \| 'fullheight' \| 'fullheight-with-navbar'` |
55
+ | `fullheightWithNavbar` | `boolean` |
56
+
57
+ ```tsx
58
+ <Hero color="primary" size="medium">
59
+ <Hero.Body>…</Hero.Body>
60
+ </Hero>
61
+ ```
62
+
63
+ ## Footer
64
+
65
+ `<Footer>` is the page footer.
66
+
67
+ | Prop | Type |
68
+ | --------------------------------- | ------------------- |
69
+ | `as` | `'footer' \| 'div'` |
70
+ | `color` / `textColor` / `bgColor` | Bulma color |
71
+
72
+ ## Level
73
+
74
+ `<Level>` is a horizontal toolbar (left/right groups). Subcomponents: `Level.Left`, `Level.Right`,
75
+ `Level.Item`.
76
+
77
+ | Prop | Type |
78
+ | ---------------------------- | ------------------------------------- |
79
+ | `Level.isMobile` | `boolean` (keep horizontal on mobile) |
80
+ | `Level.Item.as` | `'div' \| 'p' \| 'a'` |
81
+ | `Level.Item.hasTextCentered` | `boolean` |
82
+
83
+ ## Columns / Column
84
+
85
+ The responsive grid. `Columns` is the row; `Column` is a cell.
86
+
87
+ **Columns**
88
+
89
+ | Prop | Type |
90
+ | -------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
91
+ | `isMultiline` | `boolean` (wrap cells onto new rows) |
92
+ | `isCentered` | `boolean` (center the row) |
93
+ | `isVCentered` | `boolean` (vertical centering — capital V) |
94
+ | `isGapless` | `boolean` |
95
+ | `isMobile` | `boolean` (stay side-by-side on mobile) |
96
+ | `isDesktop` | `boolean` |
97
+ | `gapSize` / `gapSizeMobile` / `gapSizeTablet` / `gapSizeDesktop` / `gapSizeWidescreen` / `gapSizeFullhd` | `0`–`8` (number or string) |
98
+
99
+ **Column**
100
+
101
+ | Prop | Type |
102
+ | -------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
103
+ | `size` (+ `sizeMobile` / `sizeTablet` / `sizeDesktop` / `sizeWidescreen` / `sizeFullhd`) | `BulmaColumnSize` |
104
+ | `offset` (+ per-breakpoint) | `BulmaColumnSize` |
105
+ | `isNarrow` (+ per-breakpoint: `isNarrowMobile` / `isNarrowTablet` / `isNarrowTouch` / `isNarrowDesktop` / `isNarrowWidescreen` / `isNarrowFullhd`) | `boolean` |
106
+
107
+ ```ts
108
+ type BulmaColumnSize =
109
+ | number // 1–12
110
+ | 'full'
111
+ | 'half'
112
+ | 'one-third'
113
+ | 'two-thirds'
114
+ | 'one-quarter'
115
+ | 'three-quarters'
116
+ | 'one-fifth'
117
+ | 'two-fifths'
118
+ | 'three-fifths'
119
+ | 'four-fifths';
120
+ ```
121
+
122
+ > Columns **stack on mobile** by default and go side-by-side at the tablet breakpoint and up.
123
+ > Use the per-breakpoint `size*` props to control how many cells share a row at each width.
124
+
125
+ ## Navbar
126
+
127
+ `<Navbar>` is the top bar. Subcomponents: `Navbar.Brand`, `Navbar.Item`, `Navbar.Link`,
128
+ `Navbar.Burger`, `Navbar.Menu`, `Navbar.Start`, `Navbar.End`, `Navbar.Dropdown`,
129
+ `Navbar.DropdownMenu`, `Navbar.Divider`.
130
+
131
+ | Prop | Type |
132
+ | --------------- | ---------------------------------------------------------------------------------------------------------------- |
133
+ | `fixed` | `'top' \| 'bottom'` |
134
+ | `transparent` | `boolean` |
135
+ | `color` | `'primary' \| 'link' \| 'info' \| 'success' \| 'warning' \| 'danger' \| 'black' \| 'dark' \| 'light' \| 'white'` |
136
+ | `Navbar.Item` | `as?`, `active?`, `href` |
137
+ | `Navbar.Burger` | `active?`, `onClick` |
138
+ | `Navbar.Menu` | `active?` (toggled open on mobile) |
139
+
140
+ The burger/menu is controlled state — toggle `Navbar.Burger active`/`onClick` and pass the same
141
+ flag to `Navbar.Menu active`. **A `fixed="top"` navbar requires `has-navbar-fixed-top` on `<html>`**
142
+ (Bulma offsets the page from it); the library adds no helper, so set it yourself:
143
+
144
+ ```ts
145
+ document.documentElement.classList.add('has-navbar-fixed-top');
146
+ ```
147
+
148
+ ## Menu
149
+
150
+ `<Menu>` is a vertical sidebar menu. Subcomponents: `Menu.Label`, `Menu.List`, `Menu.Item`.
151
+
152
+ | Prop | Type |
153
+ | ----------- | ------------------------------------------------------------------------------------------------- |
154
+ | `Menu.Item` | `active?`, `href?`, `as?` (custom link component); nest a `Menu.List` inside an item for submenus |
155
+
156
+ ```tsx
157
+ <Menu>
158
+ <Menu.Label>General</Menu.Label>
159
+ <Menu.List>
160
+ <Menu.Item active href="#">
161
+ Dashboard
162
+ </Menu.Item>
163
+ <Menu.Item href="#">Customers</Menu.Item>
164
+ </Menu.List>
165
+ </Menu>
166
+ ```
167
+
168
+ ## Card
169
+
170
+ `<Card>` for catalog/grid items. Use the props form (`header`, `image`, `footer`) or the compound
171
+ subcomponents (`Card.Header` + `.Title`/`.Icon`, `Card.Image`, `Card.Content`, `Card.Footer`,
172
+ `Card.FooterItem`).
173
+
174
+ | Prop | Type |
175
+ | ------------------------------- | ----------------------------- |
176
+ | `header` | `ReactNode` |
177
+ | `image` | `string` (URL) or `ReactNode` |
178
+ | `imageAlt` | `string` |
179
+ | `footer` | `ReactNode \| ReactNode[]` |
180
+ | `hasShadow` | `boolean` (default `true`) |
181
+ | `headerCentered` / `headerIcon` | `boolean` / `ReactNode` |
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: bestax-theming
3
+ description: Customize colors, branding, dark mode, and visual tokens of an app built with @allxsmith/bestax-bulma. Use when changing the primary/brand color, recoloring components, overriding Bulma --bulma-* CSS variables, setting fonts/radius/spacing tokens, or adding light/dark mode.
4
+ license: MIT
5
+ ---
6
+
7
+ # Theming @allxsmith/bestax-bulma
8
+
9
+ `@allxsmith/bestax-bulma` wraps Bulma 1.x, which is themed through `--bulma-*` CSS custom
10
+ properties. Theme an app by overriding the right variables — no component re-styling required.
11
+
12
+ ## Use when
13
+
14
+ - Setting a brand/primary color or recoloring `link`/`info`/`success`/`warning`/`danger`.
15
+ - Adjusting global tokens — radius, fonts, sizes, weights.
16
+ - Adding light/dark mode.
17
+
18
+ ## Approach
19
+
20
+ Recolor a brand color by overriding its **hue/saturation/lightness trio** — Bulma derives every
21
+ shade, light/dark, and invert variant from `--bulma-<color>-h` / `-s` / `-l`. Override the trio and
22
+ the whole palette follows.
23
+
24
+ Choose an override path:
25
+
26
+ - **`Theme` component (runtime, preferred).** Exported from the package. Pass named HSL props
27
+ (`primaryH`, `primaryS`, `primaryL`, …) and/or `bulmaVars={{ '--bulma-*': '…' }}` for everything
28
+ else. Add `isRoot` to inject the variables globally at `:root` (once, at the app root); omit it to
29
+ scope the variables to the wrapped subtree.
30
+ - **Plain CSS.** Set `:root { --bulma-primary-h: …; }` (or any selector) directly.
31
+ - **Build-time Sass.** `@use 'bulma/sass' with ($primary: #1e6b99)` when compiling Bulma's Sass.
32
+
33
+ For **dark mode**, pass `colorMode` to `Theme` (`'light' | 'dark' | 'system'`). It writes Bulma's
34
+ `data-theme` attribute on `<html>`, flipping the light/dark scheme — global, even on a scoped
35
+ `Theme`; `'system'` follows the OS `prefers-color-scheme`. Drive it from state on the app-root
36
+ `Theme`: `<Theme isRoot colorMode={mode}>`.
37
+
38
+ Reach for the helper props (`color` / `textColor` / `bgColor` / `colorShade`, `textSize`,
39
+ `textWeight`, `fontFamily`) to apply themed colors and type to individual components.
40
+
41
+ ## Quick start
42
+
43
+ ```tsx
44
+ import { Theme, Button } from '@allxsmith/bestax-bulma';
45
+
46
+ // Global brand theme at the app root.
47
+ <Theme isRoot primaryH="265" primaryS="65%" primaryL="55%">
48
+ <App />
49
+ </Theme>;
50
+
51
+ // Themed components recolor automatically.
52
+ <Button color="primary">Save</Button>;
53
+ ```
54
+
55
+ ## References
56
+
57
+ - `references/css-variables.md` — the `--bulma-*` variable map (colors, scheme/text/border, radius,
58
+ fonts, sizes, weights, dark mode) and all three override mechanisms.
59
+ - `references/themeable-components.md` — which components take `color`/`size` props, the real
60
+ accepted values, and the shared helper props.
61
+
62
+ ## Examples
63
+
64
+ - `examples/theme-config.tsx` — a custom brand theme at the app root, plus a scoped override.
65
+ - `examples/dark-mode.tsx` — a light/dark toggle using Bulma's `data-theme`.
66
+
67
+ ## Checklist
68
+
69
+ - [ ] Recolor brand colors via the HSL trio (`*-h` / `*-s` / `*-l`), not by hard-coding hex on components.
70
+ - [ ] Apply a global theme once with `<Theme isRoot>` (or `:root`); use scoped `<Theme>` for one-off sections.
71
+ - [ ] Set non-color tokens (radius, fonts, sizes) through `bulmaVars` or `:root`.
72
+ - [ ] Implement dark mode with `data-theme` on `<html>`; do not expect a shipped dark-mode component.
73
+ - [ ] Pass `color`/`textColor`/`bgColor` (not custom CSS) to color individual components.
@@ -0,0 +1,38 @@
1
+ // Dark mode for an app built on @allxsmith/bestax-bulma.
2
+ //
3
+ // The Theme component drives the light/dark scheme: pass `colorMode` and it
4
+ // writes Bulma's `data-theme` attribute on <html>. This is global (even on a
5
+ // scoped Theme); `'system'` removes the attribute so Bulma follows the OS
6
+ // `prefers-color-scheme`. Wrap the app once at the root.
7
+ import React, { useState } from 'react';
8
+ import {
9
+ Theme,
10
+ Box,
11
+ Button,
12
+ Title,
13
+ Notification,
14
+ } from '@allxsmith/bestax-bulma';
15
+
16
+ type Mode = 'light' | 'dark' | 'system';
17
+
18
+ export function DarkModeToggle() {
19
+ const [mode, setMode] = useState<Mode>('system');
20
+
21
+ return (
22
+ <Theme isRoot colorMode={mode}>
23
+ <Box>
24
+ <Title size="5">Color mode: {mode}</Title>
25
+ <Notification color="info">
26
+ Components below follow the current Bulma color scheme.
27
+ </Notification>
28
+ <Button color="primary" onClick={() => setMode('light')}>
29
+ Light
30
+ </Button>
31
+ <Button color="primary" onClick={() => setMode('dark')}>
32
+ Dark
33
+ </Button>
34
+ <Button onClick={() => setMode('system')}>System</Button>
35
+ </Box>
36
+ </Theme>
37
+ );
38
+ }
@@ -0,0 +1,58 @@
1
+ // Custom brand theme for an app built on @allxsmith/bestax-bulma.
2
+ // Copy this to your app and adjust the HSL values to your brand.
3
+ //
4
+ // Bulma 1.x derives every shade of a color from its hue/saturation/lightness
5
+ // trio (--bulma-<color>-h / -s / -l), so overriding the trio recolors the whole
6
+ // palette. The <Theme> component writes those CSS variables for you:
7
+ // - isRoot -> inject the variables globally at :root (use once, at the app root)
8
+ // - without isRoot -> wrap children in a <div> and scope the variables to it
9
+ import React from 'react';
10
+ import {
11
+ Theme,
12
+ Button,
13
+ Notification,
14
+ Box,
15
+ Title,
16
+ } from '@allxsmith/bestax-bulma';
17
+
18
+ // 1) Global brand theme at the app root.
19
+ // Hue is unitless; saturation and lightness are percentages.
20
+ export function ThemedApp({ children }: { children: React.ReactNode }) {
21
+ return (
22
+ <Theme
23
+ isRoot
24
+ // Brand primary (HSL trio) — recolors every `is-primary` / `has-text-primary`.
25
+ primaryH="265"
26
+ primaryS="65%"
27
+ primaryL="55%"
28
+ // A matching link color.
29
+ linkH="200"
30
+ linkS="80%"
31
+ linkL="45%"
32
+ // Anything without a named prop goes through `bulmaVars`, keyed by the real
33
+ // --bulma-* variable names (string values).
34
+ bulmaVars={{
35
+ '--bulma-radius': '0.75rem',
36
+ '--bulma-radius-large': '1.25rem',
37
+ '--bulma-family-primary': "'Inter', system-ui, sans-serif",
38
+ }}
39
+ >
40
+ {children}
41
+ </Theme>
42
+ );
43
+ }
44
+
45
+ // 2) Scoped override — theme just one section; the rest of the app is untouched.
46
+ export function PromoPanel() {
47
+ return (
48
+ <Theme primaryH="16" primaryS="85%" primaryL="55%">
49
+ <Box>
50
+ <Title size="4">Limited offer</Title>
51
+ <Notification color="primary">
52
+ This panel uses a warm primary; the rest of the app is unaffected.
53
+ </Notification>
54
+ <Button color="primary">Claim it</Button>
55
+ </Box>
56
+ </Theme>
57
+ );
58
+ }
@@ -0,0 +1,130 @@
1
+ # Bulma CSS variables & override mechanisms
2
+
3
+ `@allxsmith/bestax-bulma` wraps **Bulma 1.x**, which is themed entirely through `--bulma-*` CSS
4
+ custom properties. Every color, font, size, and radius resolves from one of these variables, so
5
+ theming means overriding the right `--bulma-*` values.
6
+
7
+ ## How to override (three paths)
8
+
9
+ ### 1. The `Theme` component (runtime, recommended)
10
+
11
+ `Theme` is exported from the package and writes `--bulma-*` variables for you.
12
+
13
+ - `isRoot` → injects the variables globally at `:root` (use once, at the app root).
14
+ - without `isRoot` → wraps children in a `<div>` and scopes the variables to that subtree.
15
+ - Named props set the color/scheme HSL channels and common values (see "Theme props" below).
16
+ - `bulmaVars` sets any other variable, keyed by its real `--bulma-*` name:
17
+
18
+ ```tsx
19
+ <Theme
20
+ isRoot
21
+ primaryH="265"
22
+ primaryS="65%"
23
+ primaryL="55%"
24
+ bulmaVars={{
25
+ '--bulma-radius': '0.75rem',
26
+ '--bulma-family-primary': "'Inter', sans-serif",
27
+ }}
28
+ >
29
+ <App />
30
+ </Theme>
31
+ ```
32
+
33
+ > Note: the type of the `bulmaVars` keys is not exported — pass it as an object literal (TypeScript
34
+ > still checks the keys against the allowed `--bulma-*` names).
35
+
36
+ ### 2. Plain CSS
37
+
38
+ Set the variables yourself on any selector. `:root` themes the whole document; a class scopes it.
39
+
40
+ ```css
41
+ :root {
42
+ --bulma-primary-h: 265;
43
+ --bulma-primary-s: 65%;
44
+ --bulma-primary-l: 55%;
45
+ --bulma-radius: 0.75rem;
46
+ }
47
+ ```
48
+
49
+ ### 3. Build-time Sass
50
+
51
+ If compiling Bulma's Sass yourself, set the SCSS variables before the CSS variables are generated:
52
+
53
+ ```scss
54
+ @use 'bulma/sass' with (
55
+ $primary: #1e6b99,
56
+ $link: #485fc7
57
+ );
58
+ ```
59
+
60
+ (The library itself ships `$primary: #1e6b99` — HSL `202 / 67% / 36%` — this way.)
61
+
62
+ ## Colors — override the H/S/L trio to recolor
63
+
64
+ Bulma derives a color's entire palette (shades, light/dark/invert variants) from three channels.
65
+ Override the trio; the rest follows automatically. For each color `<c>` ∈ `primary`, `link`,
66
+ `info`, `success`, `warning`, `danger`:
67
+
68
+ | Variable | Meaning | `Theme` prop |
69
+ | --------------- | -------------------------- | ------------------------ |
70
+ | `--bulma-<c>-h` | hue (unitless, e.g. `265`) | `<c>H` (e.g. `primaryH`) |
71
+ | `--bulma-<c>-s` | saturation (`%`) | `<c>S` |
72
+ | `--bulma-<c>-l` | lightness (`%`) | `<c>L` |
73
+
74
+ Read-only derived values (set automatically; reference if you need them): `--bulma-<c>` (the
75
+ resolved color), `--bulma-<c>-invert`, `--bulma-<c>-light`, `--bulma-<c>-dark`, `--bulma-<c>-rgb`,
76
+ and numeric shades `--bulma-<c>-00` … `--bulma-<c>-95`.
77
+
78
+ ## Scheme, text, background, border (light/dark surfaces)
79
+
80
+ | Variable | Role |
81
+ | --------------------------------------------------------------------------- | ----------------------------------------------------- |
82
+ | `--bulma-scheme-h`, `--bulma-scheme-s` | scheme hue/saturation (`Theme`: `schemeH`, `schemeS`) |
83
+ | `--bulma-scheme-main`, `--bulma-scheme-main-bis`, `--bulma-scheme-main-ter` | page/surface backgrounds (main + subtle steps) |
84
+ | `--bulma-background` | secondary background |
85
+ | `--bulma-text`, `--bulma-text-strong`, `--bulma-text-weak` | body / emphasized / muted text |
86
+ | `--bulma-border`, `--bulma-border-weak` | borders |
87
+
88
+ ## Radius, typography
89
+
90
+ | Variable | Default | `Theme` prop |
91
+ | ----------------------------------------------------------------------------- | --------------------------------- | --------------- |
92
+ | `--bulma-radius-small` / `--bulma-radius` / `--bulma-radius-large` | 0.25 / 0.375 / 0.75rem | via `bulmaVars` |
93
+ | `--bulma-radius-rounded` | 9999px | via `bulmaVars` |
94
+ | `--bulma-family-primary` / `--bulma-family-secondary` / `--bulma-family-code` | sans / sans / mono | via `bulmaVars` |
95
+ | `--bulma-size-1` … `--bulma-size-7` | 3rem … 0.75rem | via `bulmaVars` |
96
+ | `--bulma-size-small` / `-normal` / `-medium` / `-large` | 0.75 / 1 / 1.25 / 1.5rem | via `bulmaVars` |
97
+ | `--bulma-weight-light/normal/medium/semibold/bold/extrabold` | 300 / 400 / 500 / 600 / 700 / 800 | via `bulmaVars` |
98
+
99
+ ## Dark mode (`Theme colorMode`)
100
+
101
+ Drive the light/dark scheme with the `Theme` component's **`colorMode`** prop —
102
+ `'light' | 'dark' | 'system'`:
103
+
104
+ ```tsx
105
+ <Theme isRoot colorMode={mode}>
106
+ <App />
107
+ </Theme>
108
+ ```
109
+
110
+ `colorMode` writes Bulma's **`data-theme`** attribute on `<html>`, so it is always **global** (even
111
+ on a scoped `Theme`). `'system'` removes the attribute, so Bulma falls back to the OS
112
+ `@media (prefers-color-scheme: dark)`. Omitting `colorMode` leaves the current setting untouched.
113
+
114
+ Under the hood this is Bulma 1.x's own mechanism — `[data-theme="dark"]` / `.theme-dark` selectors
115
+ (plus the `prefers-color-scheme` media query). Setting the attribute by hand still works
116
+ (`document.documentElement.setAttribute('data-theme', 'dark')`); `colorMode` just does it for you.
117
+
118
+ Under dark mode Bulma flips the scheme/text/border/background lightness variables (e.g.
119
+ `--bulma-scheme-main-l` 100% → 9%, `--bulma-text-l` 29% → 71%). Your brand color overrides from
120
+ `Theme isRoot` or `:root` still apply on top, because they set the hue/saturation/lightness
121
+ channels directly.
122
+
123
+ ## `Theme` props (named)
124
+
125
+ Color trios: `primaryH/primaryS/primaryL`, `linkH/linkS/linkL`, `infoH/S/L`, `successH/S/L`,
126
+ `warningH/S/L`, `dangerH/S/L`. Scheme: `schemeH`, `schemeS`, `lightL`, `darkL`, `lightInvertL`,
127
+ `darkInvertL`, `softL`, `boldL`, `softInvertL`, `boldInvertL`. Interaction deltas:
128
+ `hoverBackgroundLDelta`, `activeBackgroundLDelta`, `hoverBorderLDelta`, `activeBorderLDelta`,
129
+ `hoverColorLDelta`, `activeColorLDelta`, `hoverShadowADelta`, `activeShadowADelta`. Everything else:
130
+ `bulmaVars={{ '--bulma-…': '…' }}`. All values are strings.