jixoai-ui
the terminal design language
loading the style sheet…
Skip to content
docs · print medium: screen

registry:ui · Layout · alpha

prototype-grid — the standardized grid

The layout family, alpha track: the design studio's property panel edits these exact props. Three laws carry over from prototype-flex — single root + rest spread, zero translation, inline style only — plus the track coercion: cols/rows number → repeat(N, minmax(0, 1fr)) (the no-max-content-blowout form), strings stay verbatim, and grid-template-areas passes through as one template string.

install — prototype-grid

$npx jixoai-ui add prototype-grid

https://ui.jixoai.com/r/prototype-grid.json

alpha track inline style only single root + rest spread track coercion: number → repeat zero dependencies

overview

Overview

The flex contract carries over, plus one real coercion: track forms. Everything else — stamps, forwarder axes, host-agnosticism — is the alpha lane verbatim.

The three alpha laws hold unchanged from prototype-flex: SINGLE ROOT + REST SPREAD (one div; consumer attributes first, family stamps after — replace, never merge), ZERO TRANSLATION (the props are CSS: cols/rows/gap/areas pass through as grid-template-columns / -rows / gap / grid-template-areas verbatim), and INLINE STYLE ONLY (no utilities, no theme tokens, no css file — the item renders in any host).

The one real coercion is the TRACK FORM: a number N becomes repeat(N, minmax(0, 1fr)) — the no-max-content-blowout form (min(0, 1fr) floors each track at zero so a wide chip can never stretch the column past its fr share); a string stays verbatim for named and hybrid tracks. Measured in the rig below, against the container's RESOLVED track geometry (px per track from computed grid-template-columns), not the style string: three equal tracks at cols={3}, the auto-fit form reflowing its track count with the viewport, and a verbatim 1fr 2fr 1fr ratio resolving to a 1:2:1 px split.

The eight axes are forwarders exactly as on prototype-flex — all no-own, carriers in the consumer style attr, density stamping its rung for descendants, theme riding the .dark bridge, size echoing on the root. The grid-specific accessibility truth: auto-placement follows the DOM in BOTH dimensions, so plain grids keep source order — but the AREAS form lets you place items anywhere, and a template that visually reorders meaningful content breaks the source-order contract the same way row-reverse does on flex.

prototype-grid · the rig

The property panel, live: cols form, rows and gap are real props — measured end-to-end in task 36 against the container's RESOLVED grid-template-columns (px per track), not the style string.

α 1β 2γ 3δ 4ε 5ζ 6
  • cols form
  • rows
  • gap (px)
  • the cols select demonstrates BOTH coercion forms and the verbatim ratio: watch the resolved tracks in the readout below the container — auto-fit re-counts its tracks as the viewport changes. rows=2 floors the container at two explicit minmax(0, 1fr) rows.

prototype-grid-usage.svelte svelte
<PrototypeGrid cols={3} gap={12}>
  <span>one</span><span>two</span><span>three</span>
</PrototypeGrid>

<!-- number → repeat(N, minmax(0, 1fr)); string stays verbatim -->
<PrototypeGrid cols="repeat(auto-fit, minmax(140px, 1fr))" gap="0.75rem">
  <span>cards</span><span>reflow</span><span>by</span><span>width</span>
</PrototypeGrid>

resolved tracks, measured live against this served container (probe, task 36; px receipts name their seat — re-measures match to the rounding only at the named widths): cols=3 → three equal tracks (240px each at 1400px viewport, style declaration repeat(3, minmax(0px, 1fr))); the auto-fit form shrinks its tracks to the 140px floor (measured 145px at a 760px viewport) and re-counts past it; "1fr 2fr 1fr" resolves a 1:2:1 px ratio (180/361/180 at 1400px); rows=2 pins two equal row tracks; gap 30 → 30px column-gap (the tracks absorb it, 240 → 228px at 1400px).

law

The alpha contract + the track coercion

The three flex laws carry over verbatim; the one grid addition is the track form — number → repeat(N, minmax(0, 1fr)), string verbatim, areas as one template string.

1 · SINGLE ROOT + REST SPREAD — one div, consumer attributes first, family stamps after. 2 · ZERO TRANSLATION — cols/rows/gap/areas are the CSS grid properties; the sole vocabulary event is the NUMBER form of cols/rows, a coercion to repeat(N, minmax(0, 1fr)) chosen for the no-max-content-blowout guarantee (a track can never grow past its fr share because a chip is wide — the css-architecture grid law's vocabulary). 3 · INLINE STYLE ONLY — zero tokens: a grid track you pass is a track that renders, in any host. The areas form is deliberately a single verbatim string in v0 (an array-join convenience is a recorded future enhancement, not guessed).

The layout trio, cross-referenced: prototype-flex — the row prototype-grid — the tracks prototype-waterfall — the columns — one contract, three engines.

types

Types — the track forms, rendered

The coercion inventory: the number form (repeat(N, minmax(0, 1fr))), the verbatim string form (named/hybrid tracks), and the areas form with placed children — one element, three ways to say where things go.

prototype-grid · track forms

number: cols={4} → repeat(4, minmax(0, 1fr))
1234
verbatim string: "1fr 2fr 1fr"
1fr2fr1fr
areas: "head head" "side main"
head side main
prototype-grid-usage.svelte svelte
<PrototypeGrid cols={3} gap={12}>
  <span>one</span><span>two</span><span>three</span>
</PrototypeGrid>

<!-- number → repeat(N, minmax(0, 1fr)); string stays verbatim -->
<PrototypeGrid cols="repeat(auto-fit, minmax(140px, 1fr))" gap="0.75rem">
  <span>cards</span><span>reflow</span><span>by</span><span>width</span>
</PrototypeGrid>

usage

Usage

Pass a number for the even-lanes form, a string for named/hybrid tracks — or omit and let the implicit grid serve.

PrototypeGrid usage
<PrototypeGrid cols={3} gap={12}>
  <span>one</span><span>two</span><span>three</span>
</PrototypeGrid>

<!-- number → repeat(N, minmax(0, 1fr)); string stays verbatim -->
<PrototypeGrid cols="repeat(auto-fit, minmax(140px, 1fr))" gap="0.75rem">
  <span>cards</span><span>reflow</span><span>by</span><span>width</span>
</PrototypeGrid>

api

API

The one vocabulary coercion: number → repeat(N, minmax(0, 1fr)) — strings stay verbatim. Everything else rides through as native div attributes.

Properties

PropertyTypeDefaultDescription
cols number | string—grid-template-columns: number → repeat(N, minmax(0, 1fr)) (the no-max-content-blowout form); string verbatim (named/hybrid tracks).
rows number | string—grid-template-rows, same two forms as cols. Omitted → implicit content-sized rows.
gap number | string—gap: number → px, string verbatim.
areas string—grid-template-areas, verbatim — a single template string. A template that visually reorders meaningful content breaks source-order reading (the a11y note).
class string—Passed through verbatim — the component owns no class of its own.
...rest HTMLAttributes<HTMLDivElement>spreadEvery other attribute lands on the single root (stamped data-jx-prototype-grid after the spread — replace, never merge).

Universal props

PropertyTypeDefaultDescription
size'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopethe base scale — root font-size; parts size in em
shape'round' | 'scoop' | 'bevel' | 'notch' | 'square' | 'squircle' | 'auto''auto' · ambient scopecorner geometry (CSS corner-shape; §14 degrade table)
radius'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopecorner size; auto = the concentric broadcast (§3)
density'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopespacing/leading scale over the kernel channels (§4)
color'primary' | 'secondary' | 'error' | 'warn' | 'success' | 'info' | 'auto' | number | string'auto' · ambient scopethe hue axis of the fixed oklch primary system (§5)
theme'light' | 'dark' | 'system' | 'auto''auto' · ambient scopelight/dark profile; system = the JS-mutable global (§6)
elevation'level-1' | 'level0' | 'level1' | 'level2' | 'level3' | 'level4' | 'level5' | 'auto' | number'auto' · ambient scopeofficial M3 levels over the surface ladder (§7)
motion'reduced' | 'subtle' | 'normal' | 'expressive' | 'auto' | number'auto' · ambient scopeintensity across the motion kernels (§8)

axes

The eight axes on prototype-grid

The zero-translation posture extends to paint: the first-time contract is ALL NO-OWN, and the family paints nothing for any axis — carriers join the consumer style attr, density stamps its rung for descendants, theme rides the .dark bridge, size echoes on the root (fr and em tracks reflow with it). Every row below is a forwarder, measured by stamp receipts rather than paint (there is no family paint to measure).

PropertyTypeDefaultDescription
density '2xs' | 'xs' | 'sm' | 'default' | 'lg' | 'auto' | number (+ the five legacy spellings)'auto'FORWARDER — the resolved rung stamps data-density on the grid root (measured data-density=lg with an explicit lane; null ambient), opening the kernel channels for DESCENDANTS; the track geometry consumes none. Number unit: coefficient.
size 'small' | 'medium' | 'large' | 'auto' | number'auto'FORWARDER, ECHO MEASURED — the §11 stamp lands inline as font-size: var(--jx-size-effective, 1rem) (the carrier chain, measured in the style attr; computed 18px at size={18}), so fr/em-inheriting tracks and children reflow. Number unit: px.
shape 'round' | 'scoop' | 'bevel' | 'notch' | 'square' | 'squircle' | 'auto''auto'FORWARDER — carrier stamp only; zero family readers (an inline-style-only family: no css file, no tokens). Number unit: none.
radius 'small' | 'medium' | 'large' | 'auto' | number'auto'FORWARDER — carrier stamp only; zero family readers. Number unit: px.
color 'primary' | 'secondary' | 'error' | 'warn' | 'success' | 'info' | 'auto' | number | string'auto'FORWARDER — carrier stamp only; children re-tint through the ambient chain if they read it. Zero family readers. Number unit: hue degrees.
theme 'light' | 'dark' | 'system' | 'auto''auto'FORWARDER — dark rides the .dark class bridge on the grid root (measured with theme="dark"), re-scoping token chains for the subtree; the track geometry is theme-blind. No number lane.
elevation 'level-1' | 'level0' | 'level1' | 'level2' | 'level3' | 'level4' | 'level5' | 'auto' | number'auto'FORWARDER — carrier stamp only; zero family readers. Number unit: dp.
motion 'reduced' | 'subtle' | 'normal' | 'expressive' | 'auto' | number'auto'FORWARDER — carrier stamp only; the layout has no transitions of its own (grep receipt: zero transition declarations in the family). Number unit: coefficient.

Receipts: the rig's three controls measured end-to-end against the container's RESOLVED track geometry (computed grid-template-columns in px per track: three equal 240px tracks at cols=3; the auto-fit form shrinking to its 140px floor (145px measured) before re-counting; the verbatim 1fr 2fr 1fr ratio resolving 180/361/180; rows=2 pinning two equal row tracks; gap 30 → 30px column-gap with the tracks absorbing it) — task 36; the density rung stamp (data-density=lg explicit, null ambient), the size carrier (font-size: var(--jx-size-effective, 1rem), computed 18px at size={18}) and the dark class bridge were measured on this page's served DOM; the zero-reader rows carry grep receipts over ui/prototype-grid/ (an inline-style-only family). The query() seat below rides the md viewport key (48rem) on the size LANE — the lanes-vs- passthroughs boundary (task 35) applies: cols/rows/gap/areas reject query().

one real query() case
<script lang="ts">
  import PrototypeGrid from '@ui/prototype-grid.svelte';
  import { query } from '@lib/universal-props-query.svelte';
</script>

<!-- below 48rem the base (13px root) applies; at 48rem+ the md case
     (18px) wins — the §11 stamp scales the root, fr tracks reflow -->
<PrototypeGrid cols={3} size={query({ md: 18 }, 13)} gap={12}>…</PrototypeGrid>

prototype-grid · query()

13px → 18pxat48rem

Media keys are min-width: below 48rem the base (13px root) applies; at 48rem and wider the md case wins (18px) — the §11 stamp scales the root and the fr tracks reflow around it. The number lane goes bare. Resize across 48rem.

prototype-grid-query-demo.svelte svelte
<script lang="ts">
  import PrototypeGrid from '@ui/prototype-grid.svelte';
  import { query } from '@lib/universal-props-query.svelte';
</script>

<!-- below 48rem the base (13px root) applies; at 48rem+ the md case
     (18px) wins — the §11 stamp scales the root, fr tracks reflow -->
<PrototypeGrid cols={3} size={query({ md: 18 }, 13)} gap={12}>…</PrototypeGrid>

PrototypeGrid · universal props

onetwothree
namedsteps
darklg rung
autofitreflows
prototype-grid-universal.svelte svelte
<PrototypeGrid cols={3} size={18} density="small">…</PrototypeGrid>

a11y

Accessibility

A layout primitive: no role, no keys, no announcements of its own — its a11y story is PLACEMENT: auto-placement keeps source order, the areas form can break it.

Keyboard

KeyAction
—Not a focus stop and no keys of its own — a plain div wrapper

ARIA

AttributeValueDescription
auto-placementsource orderWithout areas/explicit placement the grid places children in DOM order across the tracks — reading order and visual order agree (WCAG 1.3.2).
the areas tradeplacement vs sequencegrid-template-areas can place any item anywhere; a template that visually reorders meaningful content breaks source-order reading — keep the template a rearrangement of regions, not of reading order.
rest-spread ARIAverbatimaria-label, role, data-* — anything in the rest lane lands on the single root after the spread, so consumer semantics compose with the layout stamps.
rolenone authoredThe container is a plain div; give it a role only when its children need grouping semantics.
theme / density stampssubtree-scopedThe .dark bridge and data-density rung re-scope token chains for descendants — visible only to children that read them.
jixoai-ui ui.jixoai.com the jixoai design language

Theme

Brand hue

0°

Auto cycle · 24h