--- name: bestax-layout-scaffold 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). license: MIT --- # Scaffolding a page layout with @allxsmith/bestax-bulma Turn a high-level request ("admin dashboard", "landing page", "login screen", "product catalog") into a complete responsive page built from bestax-bulma layout components. ## Behavioral rule Select an archetype from the request and build it in one shot. Do **not** ask layout questions ("how many columns?", "where should the nav go?", "what width?") — infer the structure from the request and proceed. The archetype determines the structure; fill it with the requested content. Ask **at most one** clarifying question, and only for a high-level fork the request genuinely does not imply: whether the page is **public-facing** (marketing) or an **internal tool** (authenticated app). When the request already signals this ("dashboard", "admin", "landing", "login", "pricing"), skip the question and default. ## Select an archetype | Request signals | Archetype | | ---------------------------------------------------------------------- | ------------- | | dashboard, admin, console, internal tool, authenticated app, "sidebar" | **App shell** | | landing, marketing, homepage, product/pricing page, public site | **Landing** | | login, sign up, auth, settings, checkout, a single focused form | **Centered** | | catalog, gallery, products, listing, "grid of cards", search results | **Card grid** | Default when ambiguous: internal tool → App shell; public-facing → Landing; one focused task → Centered; a collection of items → Card grid. For mixed requests, pick the dominant intent (e.g. "admin dashboard with a product list" → App shell whose main column holds a Card grid). ## Approach - Compose pages from the shipped layout components — `Container`, `Section`, `Hero`, `Footer`, `Level`, `Columns`/`Column`, `Grid`/`Cell`, `Navbar`, `Menu`, `Card`. There is **no `Tile` component**. For **uniform grids** (card grids, galleries — same-shaped items) prefer `Grid`/`Cell`: CSS Grid gives equal-height cells for free (per row — each row's cells match its tallest, same row-level behavior as the flex recipe). Use `Columns`/`Column` for proportional or per-breakpoint column layouts — and when cards there must be equal height, apply the flex recipe (`Column display="flex" flexDirection="column"` + `Card flexGrow="1"`; `height: 100%` on the card doesn't help — the column's height is auto). - Rely on Bulma's responsive defaults: `Columns` sit side by side on tablet and up and stack on mobile. Add responsive `size*` props only to tune the breakpoints. - Interactive extras don't share a state API — never transfer one by analogy: `Collapse trigger={node} open/defaultOpen onOpenChange` (`onOpenChange(open)` reports every trigger; `onOpen/onClose` fire only when the Collapse holds its own state), an accordion is `Collapses value/defaultValue/onChange` around plain `Collapse` children indexed from 0 by position (`number | null`, or `number[]` with `multiple`; hide an item with `visibility="hidden"`, never `{cond && …}`, or the open state shifts to its neighbour) rather than hand-rolled open-index state, `Tabs value={i}/onChange` (each `Tabs.Tab`/`Tabs.Content.Item` requires `index={i}`, and `Tabs.Content` must be a **child of ``** — the active-tab context lives on it; a sibling panel never switches. The arrow keys, Home/End, Enter/Space, the single tab stop and the `aria-controls`/`aria-labelledby` links come built in, so add no `onKeyDown` or ARIA of your own; `onChange` fires when a tab is activated, never on arrow-key focus), `Dropdown active/onActiveChange`, `ToggleButton pressed/defaultPressed onPressedChange` for a button that stays on or off (not `Button isActive`, which sets no `aria-pressed`; the label stays the same in both states; a set goes in `Buttons hasAddons role="group"` with an `aria-label`, where it's also `Buttons.ToggleButton`, and a row where only one can be on is `SegmentedControl`), `SegmentedControl aria-label="…" value/defaultValue onChange` for a row of buttons where only one can be on, such as a list or grid view (one `SegmentedControl.Segment value="…"` per option; a radio group with the single tab stop and the arrow keys built in, so add no `onKeyDown` of your own; an icon-only segment needs its own `aria-label`; the arrows check as they move, so `onChange(value)` fires on each, and it can't be cleared; it carries no form value, so a choice a form submits is `Radios`), `Popover trigger={} open/defaultOpen onOpenChange` (`trigger` is one element, not a node: Popover clones it to add the click and ARIA, so never wrap it in a clickable of your own; build the panel from `Popover.Header`/`Body`/`Footer`/`Close`, and a panel without a `Popover.Header` needs `ariaLabel`), `HoverCard trigger={…}` for a preview on hover or keyboard focus (`trigger` is one link or button, cloned the same way; the card's content goes straight in as children with no sub-components; a trigger inside a `Paragraph` needs `appendToBody`; hover and focus only unless `openOnTap` is set, which suits only a trigger with no tap action of its own, such as a `Button` with no `onClick`; on touch a link trigger just follows the link, so what the card shows must be on that page too, and a form is a `Popover`), `ContextMenu aria-label="…" trigger={…}` for actions on a right-click or a long press (`trigger` is one element, a row or a card, cloned rather than wrapped; the items are `ContextMenu.Item`/`ContextMenu.Divider`, which are `Dropdown`'s; no `open` prop, `onOpenChange` reports it; always put the same items in a visible `Dropdown` on the row too, since a context menu is only a shortcut), `Steps value={i}/onStepClick items={[{label, icon?}]}` (child form is `Steps.Step`, not `Steps.Item`). `Reveal cascade` staggers only its **direct children** — to stagger a grid, put `` inside each `Cell`, not around the container. - **An empty list, table or search with no results is `EmptyState`**, not a hand-built `Box` of `Icon`, `Title` and `Buttons isCentered`: `` with its one `