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,210 @@
1
+ # Reference: form patterns
2
+
3
+ ## A complete multi-field form (controlled + manual validation)
4
+
5
+ No form library — state is plain React, validation is a function, errors surface through
6
+ `color` + `message` + `messageColor`.
7
+
8
+ ```tsx
9
+ import { useState } from 'react';
10
+ import {
11
+ Input,
12
+ Select,
13
+ TextArea,
14
+ Checkbox,
15
+ Button,
16
+ Field,
17
+ } from '@allxsmith/bestax-bulma';
18
+
19
+ interface Values {
20
+ name: string;
21
+ email: string;
22
+ country: string;
23
+ bio: string;
24
+ agree: boolean;
25
+ }
26
+
27
+ function validate(v: Values) {
28
+ const errors: Partial<Record<keyof Values, string>> = {};
29
+ if (!v.name.trim()) errors.name = 'Name is required.';
30
+ if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(v.email))
31
+ errors.email = 'Enter a valid email.';
32
+ if (!v.country) errors.country = 'Pick a country.';
33
+ if (!v.agree) errors.agree = 'You must accept the terms.';
34
+ return errors;
35
+ }
36
+
37
+ export function ProfileForm() {
38
+ const [values, setValues] = useState<Values>({
39
+ name: '',
40
+ email: '',
41
+ country: '',
42
+ bio: '',
43
+ agree: false,
44
+ });
45
+ const [submitted, setSubmitted] = useState(false);
46
+
47
+ const errors = validate(values);
48
+ const show = (k: keyof Values) => (submitted ? errors[k] : undefined);
49
+ const set = (k: keyof Values, val: Values[keyof Values]) =>
50
+ setValues(prev => ({ ...prev, [k]: val }));
51
+
52
+ return (
53
+ <form
54
+ onSubmit={e => {
55
+ e.preventDefault();
56
+ setSubmitted(true);
57
+ if (Object.keys(errors).length === 0) {
58
+ // submit values…
59
+ }
60
+ }}
61
+ >
62
+ <Input
63
+ label="Name"
64
+ value={values.name}
65
+ onChange={e => set('name', e.target.value)}
66
+ color={show('name') ? 'danger' : undefined}
67
+ message={show('name')}
68
+ messageColor="danger"
69
+ />
70
+
71
+ <Input
72
+ label="Email"
73
+ type="email"
74
+ value={values.email}
75
+ onChange={e => set('email', e.target.value)}
76
+ color={show('email') ? 'danger' : undefined}
77
+ message={show('email')}
78
+ messageColor="danger"
79
+ iconLeftName="envelope"
80
+ />
81
+
82
+ <Select
83
+ label="Country"
84
+ value={values.country}
85
+ onChange={e => set('country', e.target.value)}
86
+ color={show('country') ? 'danger' : undefined}
87
+ message={show('country')}
88
+ messageColor="danger"
89
+ >
90
+ <option value="">Select…</option>
91
+ <option value="us">United States</option>
92
+ <option value="ca">Canada</option>
93
+ </Select>
94
+
95
+ <TextArea
96
+ label="Bio"
97
+ value={values.bio}
98
+ onChange={e => set('bio', e.target.value)}
99
+ rows={3}
100
+ />
101
+
102
+ <Field>
103
+ <Checkbox
104
+ checked={values.agree}
105
+ onChange={e => set('agree', e.target.checked)}
106
+ >
107
+ {' '}
108
+ I accept the terms
109
+ </Checkbox>
110
+ {show('agree') && <p className="help is-danger">{show('agree')}</p>}
111
+ </Field>
112
+
113
+ <Button color="primary" type="submit" mt="4">
114
+ Save
115
+ </Button>
116
+ </form>
117
+ );
118
+ }
119
+ ```
120
+
121
+ Notes:
122
+
123
+ - Validation runs every render as a pure function; `submitted` gates when errors are shown so the
124
+ form isn't red before the user interacts. You could gate per-field on blur instead.
125
+ - For the checkbox the convenience `message` prop isn't used; the help text is rendered manually
126
+ inside the `Field` — a good illustration of dropping to composition when needed.
127
+
128
+ ## Grouped controls and addons
129
+
130
+ ```tsx
131
+ // Search box: input + button attached.
132
+ <Field hasAddons>
133
+ <Control isExpanded>
134
+ <InputBase placeholder="Search" />
135
+ </Control>
136
+ <Control>
137
+ <Button color="primary">Search</Button>
138
+ </Control>
139
+ </Field>
140
+
141
+ // Two controls on one row.
142
+ <Field grouped>
143
+ <Control>
144
+ <InputBase placeholder="First" />
145
+ </Control>
146
+ <Control>
147
+ <InputBase placeholder="Last" />
148
+ </Control>
149
+ </Field>
150
+ ```
151
+
152
+ ## Horizontal field with explicit label/body
153
+
154
+ ```tsx
155
+ <Field horizontal>
156
+ <Field.Label size="normal">Email</Field.Label>
157
+ <Field.Body>
158
+ <Control iconLeftName="envelope" hasIconsLeft>
159
+ <InputBase type="email" placeholder="you@example.com" />
160
+ </Control>
161
+ </Field.Body>
162
+ </Field>
163
+ ```
164
+
165
+ ## Advanced inputs
166
+
167
+ These are controlled the same way — own the value, pass `value`/`onChange`.
168
+
169
+ ```tsx
170
+ // Autocomplete — onInput fires on typing, onSelect when a suggestion is chosen.
171
+ const [city, setCity] = useState('');
172
+ <Autocomplete
173
+ value={city}
174
+ onInput={setCity}
175
+ onSelect={item =>
176
+ setCity(typeof item === 'string' ? item : (item?.value ?? ''))
177
+ }
178
+ data={['Austin', 'Boston', 'Chicago']}
179
+ openOnFocus
180
+ />;
181
+
182
+ // Slider (single and dual thumb)
183
+ const [volume, setVolume] = useState(50);
184
+ <Slider value={volume} onChange={setVolume} min={0} max={100} tooltip="auto" />;
185
+
186
+ const [range, setRange] = useState<[number, number]>([20, 80]);
187
+ <Slider range value={range} onChange={setRange} min={0} max={100} />;
188
+
189
+ // Numberinput
190
+ const [qty, setQty] = useState(1);
191
+ <Numberinput value={qty} onChange={setQty} min={1} max={10} step={1} />;
192
+
193
+ // Rate
194
+ const [stars, setStars] = useState(3);
195
+ <Rate value={stars} onChange={setStars} max={5} />;
196
+
197
+ // Taginput — tags can be strings or { value, label } objects; onChange yields TaginputTag[].
198
+ const [tags, setTags] = useState<string[]>(['react']);
199
+ <Taginput
200
+ value={tags}
201
+ onChange={next =>
202
+ setTags(next.map(t => (typeof t === 'string' ? t : t.value)))
203
+ }
204
+ data={['react', 'bulma', 'ts']}
205
+ />;
206
+ ```
207
+
208
+ Each renders inside Bulma's field/control structure already, so wrap them in a `Field` only when
209
+ you need a label or grouped layout. Reflect validation on them with the same `color` /
210
+ `message` / `messageColor` approach used for text inputs.
@@ -0,0 +1,66 @@
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`, `Navbar`, `Menu`, `Card`. There is **no `Tile` component** — build
40
+ grids with `Columns`/`Column`.
41
+ - Rely on Bulma's responsive defaults: `Columns` sit side by side on tablet and up and stack on
42
+ mobile. Add responsive `size*` props only to tune the breakpoints.
43
+ - For a `fixed="top"` `Navbar`, add the `has-navbar-fixed-top` class to `<html>` so content is not
44
+ hidden behind it — the library does not do this automatically.
45
+
46
+ ## References
47
+
48
+ - `references/layout-components.md` — the layout component inventory: real prop names, types, and
49
+ accepted values, plus subcomponent nesting.
50
+ - `references/archetypes.md` — the four archetypes: selection criteria, JSX skeleton, and responsive
51
+ behavior.
52
+
53
+ ## Examples
54
+
55
+ - `examples/app-shell.tsx` — fixed `Navbar` + sidebar `Menu` + content (dashboard).
56
+ - `examples/landing.tsx` — `Hero` + `Section`s + `Footer`.
57
+ - `examples/centered.tsx` — centered single column (auth/settings).
58
+ - `examples/card-grid.tsx` — multiline `Columns` of `Card`s (catalog).
59
+
60
+ ## Checklist
61
+
62
+ - [ ] Map the request to one archetype; do not ask layout questions.
63
+ - [ ] Wrap page content in `Container` (+ `Section` for vertical rhythm).
64
+ - [ ] Use `Columns`/`Column` for side-by-side layout; rely on the mobile stack default.
65
+ - [ ] For a fixed navbar, add `has-navbar-fixed-top` to `<html>`.
66
+ - [ ] Do not use `Tile` — it is not shipped.
@@ -0,0 +1,80 @@
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. The columns sit side by side on tablet and up, and stack (menu above
7
+ // content) on mobile.
8
+ import React, { useEffect, useState } from 'react';
9
+ import {
10
+ Navbar,
11
+ Menu,
12
+ Container,
13
+ Columns,
14
+ Column,
15
+ Section,
16
+ Title,
17
+ Box,
18
+ } from '@allxsmith/bestax-bulma';
19
+
20
+ export default function AdminShell() {
21
+ const [menuOpen, setMenuOpen] = useState(false);
22
+
23
+ useEffect(() => {
24
+ document.documentElement.classList.add('has-navbar-fixed-top');
25
+ return () => {
26
+ document.documentElement.classList.remove('has-navbar-fixed-top');
27
+ };
28
+ }, []);
29
+
30
+ return (
31
+ <>
32
+ <Navbar fixed="top" color="dark">
33
+ <Navbar.Brand>
34
+ <Navbar.Item href="#">Acme Admin</Navbar.Item>
35
+ <Navbar.Burger
36
+ active={menuOpen}
37
+ onClick={() => setMenuOpen(open => !open)}
38
+ aria-label="menu"
39
+ aria-expanded={menuOpen}
40
+ />
41
+ </Navbar.Brand>
42
+ <Navbar.Menu active={menuOpen}>
43
+ <Navbar.End>
44
+ <Navbar.Item href="#">Docs</Navbar.Item>
45
+ <Navbar.Item href="#">Account</Navbar.Item>
46
+ </Navbar.End>
47
+ </Navbar.Menu>
48
+ </Navbar>
49
+
50
+ <Container fluid>
51
+ <Columns>
52
+ <Column size={3} sizeWidescreen={2}>
53
+ <Menu>
54
+ <Menu.Label>General</Menu.Label>
55
+ <Menu.List>
56
+ <Menu.Item active href="#">
57
+ Dashboard
58
+ </Menu.Item>
59
+ <Menu.Item href="#">Customers</Menu.Item>
60
+ <Menu.Item href="#">Orders</Menu.Item>
61
+ </Menu.List>
62
+ <Menu.Label>Admin</Menu.Label>
63
+ <Menu.List>
64
+ <Menu.Item href="#">Team</Menu.Item>
65
+ <Menu.Item href="#">Settings</Menu.Item>
66
+ </Menu.List>
67
+ </Menu>
68
+ </Column>
69
+
70
+ <Column>
71
+ <Section>
72
+ <Title size="3">Dashboard</Title>
73
+ <Box>Main content area — drop dashboard widgets here.</Box>
74
+ </Section>
75
+ </Column>
76
+ </Columns>
77
+ </Container>
78
+ </>
79
+ );
80
+ }
@@ -0,0 +1,98 @@
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
+ import React from 'react';
5
+ import {
6
+ Section,
7
+ Container,
8
+ Title,
9
+ Columns,
10
+ Column,
11
+ Card,
12
+ } from '@allxsmith/bestax-bulma';
13
+
14
+ interface Product {
15
+ id: number;
16
+ name: string;
17
+ price: string;
18
+ image: string;
19
+ blurb: string;
20
+ }
21
+
22
+ const PRODUCTS: Product[] = [
23
+ {
24
+ id: 1,
25
+ name: 'Aurora Lamp',
26
+ price: '$48',
27
+ image: 'https://picsum.photos/seed/1/600/400',
28
+ blurb: 'Warm ambient light.',
29
+ },
30
+ {
31
+ id: 2,
32
+ name: 'Drift Chair',
33
+ price: '$220',
34
+ image: 'https://picsum.photos/seed/2/600/400',
35
+ blurb: 'Ergonomic and airy.',
36
+ },
37
+ {
38
+ id: 3,
39
+ name: 'Stone Mug',
40
+ price: '$18',
41
+ image: 'https://picsum.photos/seed/3/600/400',
42
+ blurb: 'Hand-thrown ceramic.',
43
+ },
44
+ {
45
+ id: 4,
46
+ name: 'Field Notebook',
47
+ price: '$12',
48
+ image: 'https://picsum.photos/seed/4/600/400',
49
+ blurb: 'Pocket-sized, lined.',
50
+ },
51
+ {
52
+ id: 5,
53
+ name: 'Trail Bottle',
54
+ price: '$26',
55
+ image: 'https://picsum.photos/seed/5/600/400',
56
+ blurb: 'Insulated steel.',
57
+ },
58
+ {
59
+ id: 6,
60
+ name: 'Linen Throw',
61
+ price: '$64',
62
+ image: 'https://picsum.photos/seed/6/600/400',
63
+ blurb: 'Soft, breathable.',
64
+ },
65
+ ];
66
+
67
+ export default function CatalogPage() {
68
+ return (
69
+ <Section>
70
+ <Container>
71
+ <Title size="3" mb="5">
72
+ Catalog
73
+ </Title>
74
+ <Columns isMultiline>
75
+ {PRODUCTS.map(product => (
76
+ <Column
77
+ key={product.id}
78
+ sizeMobile="full"
79
+ sizeTablet="half"
80
+ sizeDesktop="one-third"
81
+ >
82
+ <Card
83
+ image={product.image}
84
+ imageAlt={product.name}
85
+ header={product.name}
86
+ footer={
87
+ <span className="card-footer-item">{product.price}</span>
88
+ }
89
+ >
90
+ <p>{product.blurb}</p>
91
+ </Card>
92
+ </Column>
93
+ ))}
94
+ </Columns>
95
+ </Container>
96
+ </Section>
97
+ );
98
+ }
@@ -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
+ }
@@ -0,0 +1,77 @@
1
+ // Marketing / landing page — Hero + stacked Sections + Footer.
2
+ // Each Section stacks vertically; the feature Columns collapse to one per row on
3
+ // mobile (Bulma columns stack below the tablet breakpoint).
4
+ import React from 'react';
5
+ import {
6
+ Hero,
7
+ Section,
8
+ Container,
9
+ Footer,
10
+ Columns,
11
+ Column,
12
+ Box,
13
+ Title,
14
+ SubTitle,
15
+ Content,
16
+ Button,
17
+ Buttons,
18
+ } from '@allxsmith/bestax-bulma';
19
+
20
+ const FEATURES = [
21
+ { title: 'Fast', body: 'Ship pages in minutes, not days.' },
22
+ { title: 'Responsive', body: 'Looks right on every screen by default.' },
23
+ { title: 'Composable', body: 'Build from small, predictable pieces.' },
24
+ ];
25
+
26
+ export default function LandingPage() {
27
+ return (
28
+ <>
29
+ <Hero color="primary" size="medium">
30
+ <Hero.Body>
31
+ <Container textAlign="centered">
32
+ <Title size="1">Ship faster with Acme</Title>
33
+ <SubTitle size="3">
34
+ The all-in-one platform for modern teams.
35
+ </SubTitle>
36
+ <Buttons isCentered mt="5">
37
+ <Button color="light" size="large">
38
+ Get started
39
+ </Button>
40
+ <Button color="primary" isInverted isOutlined size="large">
41
+ Live demo
42
+ </Button>
43
+ </Buttons>
44
+ </Container>
45
+ </Hero.Body>
46
+ </Hero>
47
+
48
+ <Section size="large">
49
+ <Container>
50
+ <Title size="3" textAlign="centered" mb="6">
51
+ Why Acme
52
+ </Title>
53
+ <Columns>
54
+ {FEATURES.map(feature => (
55
+ <Column key={feature.title}>
56
+ <Box>
57
+ <Title size="5">{feature.title}</Title>
58
+ <Content>{feature.body}</Content>
59
+ </Box>
60
+ </Column>
61
+ ))}
62
+ </Columns>
63
+ </Container>
64
+ </Section>
65
+
66
+ <Footer>
67
+ <Container>
68
+ <Content textAlign="centered">
69
+ <p>
70
+ <strong>Acme</strong> — built with bestax-bulma.
71
+ </p>
72
+ </Content>
73
+ </Container>
74
+ </Footer>
75
+ </>
76
+ );
77
+ }