Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions docs/docs/guides/library/columns.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,40 @@ Offsets are useful for centering or right-aligning columns, but can cause layout
</Columns>
```

**Equal-Height Cards**

Columns themselves are equal height (flexbox), but a `Card` inside a `Column` ends at its own
content — and `height: 100%` on the card doesn't help here, because `100%` resolves against
the column's _auto_ height (percentage heights only resolve against a definite size). The
robust pattern: make the column a flex container and let the card grow:

```tsx live
<Columns>
<Column display="flex" flexDirection="column">
<Card flexGrow="1" header="Basic">
Short blurb.
</Card>
</Column>
<Column display="flex" flexDirection="column">
<Card flexGrow="1" header="Featured">
A much longer description that would normally make this card taller than
its neighbors — now they all match.
</Card>
</Column>
<Column display="flex" flexDirection="column">
<Card flexGrow="1" header="Pro">
Medium-length blurb here.
</Card>
</Column>
</Columns>
```

:::tip
For **uniform grids** of same-shaped cards, [`Grid`/`Cell`](./grid.md) gives equal-height cells
for free (CSS Grid stretches every cell to its row's height) — no flex recipe needed. Both
approaches equalize per row: cards match their own row's tallest card.
:::

[View full documentation.](../../api/columns/column)

---
Expand Down
5 changes: 4 additions & 1 deletion docs/docs/guides/library/grid.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ This page summarizes the Bulma-styled grid system in Bestax, with a brief descri
Provides Bulma's advanced CSS Grid layout for complex, modern layouts. Supports responsive and fixed grid modes, gap and min column controls, fixed column counts per breakpoint, and full color/background/utility helpers. Use with `Cell` for granular grid placement.

:::info
Use `Grid` for advanced layouts where you need more control than Columns can provide. It supports both auto-fit and fixed column counts.
Use `Grid` for advanced layouts where you need more control than Columns can provide — and for
**uniform card grids**: CSS Grid keeps every cell in a row equal height for free (each row
matches its tallest cell), so cards line up without the flex recipe [`Columns` needs](./columns.md#column). It supports both auto-fit
and fixed column counts.
:::

```tsx live
Expand Down
13 changes: 10 additions & 3 deletions skills/bestax-layout-scaffold/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,13 @@ Centered; a collection of items → Card grid. For mixed requests, pick the domi
## Approach

- Compose pages from the shipped layout components — `Container`, `Section`, `Hero`, `Footer`,
`Level`, `Columns`/`Column`, `Navbar`, `Menu`, `Card`. There is **no `Tile` component** — build
grids with `Columns`/`Column`.
`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.
- For a `fixed="top"` `Navbar`, add the `has-navbar-fixed-top` class to `<html>` so content is not
Expand Down Expand Up @@ -74,7 +79,9 @@ color }}`. Set the app-wide icon library once with `<ConfigProvider iconLibrary=

- [ ] Map the request to one archetype; do not ask layout questions.
- [ ] Wrap page content in `Container` (+ `Section` for vertical rhythm).
- [ ] Use `Columns`/`Column` for side-by-side layout; rely on the mobile stack default.
- [ ] Use `Grid`/`Cell` for uniform grids (equal heights per row, free); `Columns`/`Column`
for proportional or per-breakpoint side-by-side layout — with the flex recipe when its
cards must match height.
- [ ] For a fixed navbar, add `has-navbar-fixed-top` to `<html>`.
- [ ] Do not use `Tile` — it is not shipped.
- [ ] Style with helper props (`mt`/`p`, `textAlign`, `textColor`), not inline `style`.
Expand Down
7 changes: 7 additions & 0 deletions skills/bestax-layout-scaffold/examples/card-grid.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// Card grid / catalog page — a collection of similar items.
// `<Columns isMultiline>` wraps cards onto new rows; the responsive column sizes
// give 1 card per row on mobile, 2 on tablet, 3 on desktop.
// Equal heights: each Column is a flex container and its Card grows to fill
// it (flexGrow="1"), so short blurbs don't leave ragged card bottoms.
// (`height: 100%` on the card would NOT work — it resolves against auto
// height. For uniform grids, Grid/Cell gives equal heights for free.)
import React from 'react';
import {
Section,
Expand Down Expand Up @@ -78,8 +82,11 @@ export default function CatalogPage() {
sizeMobile="full"
sizeTablet="half"
sizeDesktop="one-third"
display="flex"
flexDirection="column"
>
<Card
flexGrow="1"
image={product.image}
imageAlt={product.name}
header={product.name}
Expand Down
11 changes: 11 additions & 0 deletions skills/bestax-layout-scaffold/references/archetypes.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,11 @@ search results, "a grid of cards".
sizeMobile="full"
sizeTablet="half"
sizeDesktop="one-third"
display="flex"
flexDirection="column"
>
<Card
flexGrow="1"
image={item.image}
header={item.name}
footer={<span className="card-footer-item">{item.price}</span>}
Expand All @@ -183,6 +186,14 @@ search results, "a grid of cards".
**Responsive:** `isMultiline` wraps cards onto new rows; the `size*` props set the per-row count —
1 on mobile, 2 on tablet, 3 on desktop here. Change the fractions to change the column count.

**Equal heights:** the `display="flex" flexDirection="column"` on each `Column` plus
`flexGrow="1"` on the `Card` stretches every card to its row's height — without it, cards end
at their content and rows look ragged (`height: 100%` on the card doesn't help — it resolves
against the column's auto height). Alternatively
build the whole grid with `Grid`/`Cell` (`<Grid isFixed fixedColsMobile={1} fixedColsTablet={2}
fixedColsDesktop={3} gap={4}>`) — CSS Grid keeps cells equal-height for free; see the
`Grid / Cell` section in `layout-components.md`.

---

## Combining archetypes
Expand Down
76 changes: 75 additions & 1 deletion skills/bestax-layout-scaffold/references/layout-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
Level,
Columns,
Column,
Grid,
Cell,
Navbar,
Menu,
Card,
Expand All @@ -26,7 +28,9 @@ Every component also accepts the shared Bulma helper props (`m`/`p` spacing, `te
> `textColor="grey"` / `bgColor="light"` not `style={{ color }}`. Spacing scale is `0`–`6` | `auto`
> (`4` = 1rem). Reserve `style`/CSS vars only for values the design system doesn't tokenize.

> **There is no `Tile` component.** Build grids and nested layouts with `Columns` / `Column`.
> **There is no `Tile` component.** For uniform grids (cards, galleries) use `Grid` / `Cell` —
> equal-height cells for free; for proportional or per-breakpoint layouts use
> `Columns` / `Column`.

## Container

Expand Down Expand Up @@ -127,6 +131,76 @@ type BulmaColumnSize =
> Columns **stack on mobile** by default and go side-by-side at the tablet breakpoint and up.
> Use the per-breakpoint `size*` props to control how many cells share a row at each width.

**Equal-height cards inside Columns** — columns are equal height, but a card inside one does
**not** stretch to fill it (and `height: 100%` on the card doesn't help — it resolves against
the column's auto height). Make the `Column` a flex container and let the card grow:

```tsx
<Columns isMultiline>
{items.map(item => (
<Column
key={item.id}
sizeTablet="half"
sizeDesktop="one-third"
display="flex"
flexDirection="column"
>
<Card flexGrow="1">{item.blurb}</Card>
</Column>
))}
</Columns>
```

`display`, `flexDirection`, and `flexGrow` are helper props every component accepts;
`flexGrow` takes a string (`"1"`).

## Grid / Cell

Bulma's CSS Grid. **Preferred for uniform grids** — same-shaped items in a repeating pattern
(card grids, galleries, dashboards): CSS Grid gives **equal-height cells for free** (per row —
each row's cells match its tallest), with no flex recipe needed. Reach for `Columns`/`Column` instead when you need proportional or
per-breakpoint column _sizes_ (a 2/3 + 1/3 split, different counts per breakpoint).

**Grid**

| Prop | Type |
| ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| `gap` / `columnGap` / `rowGap` | `0`–`8` (number or string, same scale as Columns' `gap`) |
| `minCol` | `1`–`32` (smart grid: min column width step, `is-col-min-X`) |
| `isFixed` | `boolean` (fixed column count instead of auto-fill) |
| `fixedCols` (+ `fixedColsMobile` / `fixedColsTablet` / `fixedColsDesktop` / `fixedColsWidescreen` / `fixedColsFullhd`) | `0`–`12` or `'auto'` (fixed grid only) |

**Cell**

| Prop | Type |
| ------------------------------------- | --------------------------------------- |
| `colStart` / `colFromEnd` / `colSpan` | `number` (manual column placement/span) |
| `rowStart` / `rowFromEnd` / `rowSpan` | `number` (manual row placement/span) |

By default the smart grid **auto-fills**: cells flow into as many columns as fit (tune the
minimum width with `minCol`). `isFixed` + `fixedCols*` pins an exact column count per
breakpoint instead.

```tsx
// Uniform card grid — equal heights for free, responsive column count for free.
<Grid
isFixed
fixedColsMobile={1}
fixedColsTablet={2}
fixedColsDesktop={3}
gap={4}
>
{items.map(item => (
<Cell key={item.id}>
<Card header={item.name}>{item.blurb}</Card>
</Cell>
))}
</Grid>
```

> To stretch each card to its cell's full (equal) height, the same `display="flex"
flexDirection="column"` + `flexGrow="1"` pattern applies to `Cell` + `Card`.

## Navbar

`<Navbar>` is the top bar. Subcomponents: `Navbar.Brand`, `Navbar.Item`, `Navbar.Link`,
Expand Down
Loading