feat(grid): add Grid layout primitive#308
Draft
itsprade wants to merge 1 commit into
Draft
Conversation
Add `Grid` — a generic, presentational CSS-Grid layout primitive for arranging arbitrary children into equal or custom-width columns, with responsive reflow, gap control, auto-fit (`minChildWidth`), and optional `Grid.Item` spanning. Complements `Layout` (page scaffold) by handling content-level grids. Dynamic templates use the CSS-variable + arbitrary-value utility technique already shipped by `Layout` (`--layout-cols` → `grid-cols-[var(...)]`), so no new styling infrastructure is introduced. - packages/core: Grid + Grid.Item, style resolvers in styles.ts, 20 tests - docs: docs/components/grid.md - examples/nextjs-app: interactive Grid demo wired into the custom module - changeset: minor Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
Grid— a generic, presentational CSS-Grid layout primitive for arranging arbitrary children (cards, KPIs, fields, dashboards) into equal or custom-width columns, with responsive reflow, gap control, auto-fit sizing, and optionalGrid.Itemspanning.Planning ticket: tailor-inc/platform-planning#779
Gridfills a real gap:Layoutis a page scaffold (header + fixed-width left/main/right), but there was no generic content grid — developers and AI agents fell back to rawastw:grid astw:grid-cols-*, which is inconsistent and leaks styling internals.Grid vs.
LayoutThey're complementary, not overlapping:
Layout(exists)Grid(this PR)left320px /main1fr /right280px)Layout.Header,Layout.ColumnonlyGrid.Item)Design decision
After surveying design systems, grids split into two families: A (span-per-item, 12/24-col — Ant, MUI v2, Mantine
Grid) and B (declarative container — Radix Themes, Chakra/MantineSimpleGrid).This implements Family B, modeled on Radix Themes
Grid, plus Chakra'sminChildWidthauto-fit and an optionalGrid.Itemfor spanning. Rationale — it's the most legible model for both AI agents and developers: explicit, strongly-typed props (columns={4}) instead of className soup, no hidden "must sum to 12" invariant, with escape hatches (className, raw template strings).API
Gridpropscolumnsnumber | string | Responsive<number | string>grid-template-columns; responsive objectrowsnumber | string | Responsive<number | string>gap/gapX/gapYnumber | Responsive<number>4→1rem)minChildWidthnumber | stringminmax(w, 1fr); overridescolumnsflow"row" | "column" | "dense" | "row-dense" | "column-dense"grid-auto-flowalign"start" | "center" | "end" | "stretch" | "baseline"align-itemsjustify"start" | "center" | "end" | "between" | "around" | "evenly"justify-contentclassName,style,...divPropsGrid.Itemprops (optional cell — only to span or place)colSpannumber | "full" | Responsive<…>grid-column: span n(or1 / -1)rowSpannumber | "full" | Responsive<…>grid-row: span ncolStart/colEndnumber | Responsive<number>className,style,...divPropsPlain children occupy a single cell;
Grid.Itemis only needed for spanning/placement. Responsive breakpoints align with Tailwind:initial,sm,md,lg,xl,2xl.Implementation notes
Layout(--layout-cols→astw:grid-cols-[var(--layout-cols)]). Class strings are written as literals so Tailwind compiles them into the shipped stylesheet — verified present indist/app-shell.cssfor all breakpoint variants.grid/):Grid.tsx(the two components),styles.ts(CSS-var/class resolvers + maps),types.ts,index.ts,Grid.test.tsx— matchingdescription-card/.Grid(withGrid.Itemattached) +GridProps/GridItemPropsonly.astw:prefix throughout,data-slot="grid"/data-slot="grid-item",cn(), noglobals.csschanges, no"use client", fully domain-agnostic.Docs & demo
docs/components/grid.md— full page matching the app-shell doc pattern (Import, Usage, Props tables, responsive/sizing/spanning/alignment, examples, a Grid vs. Layout callout, and notes on thejustify/flowgotchas)./custom-page/grid-demo(nextjs-app) — showcase sections (responsiveMetricCardKPIs, auto-fit gallery, custom widths,Grid.Itemspanning), a static "Understanding flow" side-by-side illustration, and an interactive playground with sliders for the numeric props and live generated-JSX output.Tests
minChildWidthprecedence, responsive breakpoints, andGrid.Itemspanning).pnpm type-check,pnpm lint,pnpm test,pnpm fmt:checkall pass.How to test
Changeset
minor— addsGrid.🤖 Generated with Claude Code