Skip to content

feat(web)!: layout/grid system v1 — Container/Grid/Row/Column primitives + responsive nav#12

Merged
odenirdev merged 20 commits into
mainfrom
feat/layout-grid-system
Jul 19, 2026
Merged

feat(web)!: layout/grid system v1 — Container/Grid/Row/Column primitives + responsive nav#12
odenirdev merged 20 commits into
mainfrom
feat/layout-grid-system

Conversation

@odenirdev

Copy link
Copy Markdown
Contributor

What this ships

The layout/grid system v1 for @ogs-tech/press-web (plan: docs/superpowers/plans/2026-07-16-layout-grid-system.md, executed task-by-task with per-task spec+quality reviews and a final whole-branch review).

  • Four server-first layout primitives under packages/web/src/layout/Container, Grid (12-col), Row, Column — emitting semantic HTML + data-press-layout="…" + per-instance CSS custom properties; all responsive behavior lives in theme.css var() cascades over three fixed tiers (base 0 / md 768 / lg 1024). A coordination test pins the TS↔CSS breakpoint literals against drift.
  • Tokens: FIXED_TOKENS.container (widths + paddingX) and FIXED_TOKENS.gridGap, emitted via buildThemeStyle's single :root injection point (engine-fixed, not adopter-overridable).
  • All four preset organisms refactored to consume the primitives: Hero (responsive 2-col — text 7 / image 5 on md+, stacked at base), Cta (boxy visual moved to inner data-cta="frame"), Navbar (Container + nested Rows), Footer (Container-wrapped <small>).
  • MobileNav hamburger drawer (the one deliberate client-side exception): aria-expanded/aria-controls, role="dialog" aria-modal, Escape closes, backdrop-only close (target === currentTarget), body scroll lock, focus to first link on open / restored to toggle on close. Internal to Navbar — not exported; adopters overriding preset-organism.navbar bypass it entirely.
  • Shell rewrite: main is full-width; a single selector keeps every preset-atom.*/custom-atom.* inside main at ~72ch prose width; header/footer shells keep only stroke + vertical padding.
  • MAJOR changeset for @ogs-tech/press-web + CLAUDE.md "Layout primitives" architecture section.

Breaking (see changeset for migration)

  1. main no longer caps at 72ch — adopter custom non-atom blocks that relied on the old cap should wrap in <Container maxWidth="prose">.
  2. The engine navbar now mounts a client-side MobileNav (adopters keeping the engine navbar get it automatically).

Wire contract untouched: PressSchema/PageBody/HeaderBlocks/FooterBlocks byte-identical; packages/cms, shared, cli have zero changes; no re-seed, no press-cms bump. preset-layout CMS category stays labelled and empty by design.

Verification

  • Full gate at HEAD: pnpm -r --if-present typecheck clean (+ cms backend tsc); tests cli 21/21, cms 60/60, web 284/284.
  • Every task passed a spec-compliance + code-quality review; Task 13 had one fix round (backdrop-only close + focus-contract assertions) and re-reviewed clean.
  • Final whole-branch review: ready to merge — wire-contract diff empty against the plan's untouched list, CSS var economy closed (every emitted var consumed and vice versa), selector/attr contracts coherent, public surface exact.
  • Live playground smoke: navbar Container(full) + desktop Row + footer Container + prose atoms render correctly; hamburger/nav-links correctly render null with the seeded zero-nav-items Site Settings (tolerant-by-design, verified against the CMS API).

Remaining manual checklist (editor-driven — needs admin-created content)

  • Hero at ≥1024 / 768–1023 / <768 (7/5 split → stacked)
  • Cta frame visual (border on inner frame, not outer edge)
  • Drawer with real nav links: open/Escape/backdrop/scroll-lock at <768px (behaviors are jsdom-tested; drawer CSS not yet seen in a real browser)
  • Paragraph prose width at every viewport

Tracked follow-ups (non-blocking, from reviews)

  • A11y cluster: drawer focus trap (or drop aria-modal), CTA-only-drawer focus target, drawer aria-current, drawer external-link marker styling.
  • Cleanup PR: shared setCssVar helper + gapExpr dedupe + Container passthrough index-signature alignment + minor comment/test hardening.
  • Document managed-attrs-win passthrough semantics on Row/Grid.

🤖 Generated with Claude Code

odenirdev and others added 20 commits July 16, 2026 20:07
Approved brainstorming output. Hybrid path: engine ships four React
primitives (Container, Grid, Row, Column) consumed by organism/template
code; preset-layout CMS palette stays reserved with zero components (the
Strapi 5 no-DZ-inside-component limit rules out polymorphic layout blocks
on the editor side).

Shell change: main becomes full-width, atom blocks preserve the 72ch
prose width via one CSS selector, chrome shells strip layout CSS so
refactored organisms own their containers.

Scope: three-tier mobile-first breakpoints (base/md/lg), 12-column Grid,
refactor of Hero + Cta + Navbar + Footer to consume the primitives.
Wire-compatible (no PressSchema change); visual-only breaking change
for adopter custom blocks that relied on the old 72ch main.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ives allow data-/aria-* passthrough

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@odenirdev
odenirdev merged commit 530c8a8 into main Jul 19, 2026
1 check passed
@odenirdev
odenirdev deleted the feat/layout-grid-system branch July 19, 2026 23:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant