Back to studio index

Style Studio — Foundations

Closed foundation batches for layout and inline wrappers.

Theme: light
Viewport: Desktop
Full-width stage

Batch 1a — Layout

Core layout primitives that every downstream surface composes through.

<Stack>

Vertical flex with tokenized gap / align / justify. Defaults: gap="md", align="stretch", justify="start". No visual chrome.

gap — every --space-* token
gap="xs"
one
two
three
gap="sm"
one
two
three
gap="md"
one
two
three
gap="lg"
one
two
three
gap="xl"
one
two
three
gap="2xl"
one
two
three
align — items of varying width
align="start"
short
a longer item
mid
align="center"
short
a longer item
mid
align="end"
short
a longer item
mid
align="stretch"
short
a longer item
mid
justify — container height 160px
justify="start"
top
bottom
justify="center"
top
bottom
justify="end"
top
bottom
justify="between"
top
bottom
responsive — gap={{ base: "xs", md: "lg", lg: "2xl" }} (resize viewport)
base=xs · md=lg · lg=2xl
gap grows at md (≥768px) and lg (≥1024px)
two
three

<Row>

Horizontal flex with tokenized gap / align / justify / wrap. Defaults: gap="md", align="center", wrap="nowrap". Same no-chrome discipline as Stack.

gap — horizontal
gap="xs"
one
two
three
gap="sm"
one
two
three
gap="md"
one
two
three
gap="lg"
one
two
three
gap="xl"
one
two
three
align — items of varying height
align="start"
tiny
taller item
middle
align="center"
tiny
taller item
middle
align="end"
tiny
taller item
middle
align="baseline"
tiny
taller item
middle
justify
justify="start"
alpha
beta
gamma
justify="center"
alpha
beta
gamma
justify="between"
alpha
beta
gamma
justify="around"
alpha
beta
gamma
justify="evenly"
alpha
beta
gamma
wrap — 8 narrow items in a constrained container
wrap="nowrap"
item 1
item 2
item 3
item 4
item 5
item 6
item 7
item 8
wrap="wrap"
item 1
item 2
item 3
item 4
item 5
item 6
item 7
item 8
wrap="wrap-reverse"
item 1
item 2
item 3
item 4
item 5
item 6
item 7
item 8
composed — responsive gap + wrap (chip-row pattern)
gap={{ base: "xs", md: "md" }} wrap="wrap"
Camera
Audio
Books
Crafts
Film
AI assisted
Success

<Grid>

CSS grid with tokenized cols / rows / gap. Defaults: cols=1, gap="md". rows omitted by default. align / justify intentionally absent in v1.

cols
cols={2}
1
2
3
4
cols={3}
1
2
3
4
5
6
cols={4}
1
2
3
4
5
6
7
8
cols={6}
1
2
3
4
5
6
7
8
9
10
11
12
gap — fixed 4 columns
gap="xs"
cell 1
cell 2
cell 3
cell 4
cell 5
cell 6
cell 7
cell 8
gap="sm"
cell 1
cell 2
cell 3
cell 4
cell 5
cell 6
cell 7
cell 8
gap="md"
cell 1
cell 2
cell 3
cell 4
cell 5
cell 6
cell 7
cell 8
gap="lg"
cell 1
cell 2
cell 3
cell 4
cell 5
cell 6
cell 7
cell 8
gap="xl"
cell 1
cell 2
cell 3
cell 4
cell 5
cell 6
cell 7
cell 8
responsive cols
cols={{ base: 1, sm: 2, md: 3, lg: 4 }}
responsive 1
responsive 2
responsive 3
responsive 4
responsive 5
responsive 6
responsive 7
responsive 8
rows (flat enum, no responsive in v1)
cols={4} rows={2}
r1c1
r1c2
r1c3
r1c4
r2c1
r2c2
r2c3
r2c4

<Box>

Single-element wrapper. No flex / grid mechanism — use Stack / Row / Grid for that. Box applies tokenized padding + margin to a substrate. Last-resort layout primitive.

padding — dashed border shows the Box edge
padding="xs"
content
padding="sm"
content
padding="md"
content
padding="lg"
content
padding="xl"
content
padding="2xl"
content
margin — outer container shown as solid border
3 boxes with margin="md" in a Row
m=sm
m=md
m=lg
asChild — swap substrate to a semantic element
<Box asChild padding="lg"><article>...</article></Box>
rendered as <article> (via Radix Slot)

<Section>

Semantic <section> with tokenized padding / gap. Optional divider="top" renders a faded teal hairline — the scrapbook "stitched thread" page-break. Not a surface (no bg / border / shadow).

default — divider="none", padding="xl", gap="lg"
neutral section

Section heading

Body copy. Default padding is xl, internal gap is lg. No visual chrome — this block contributes semantic boundary and vertical rhythm only.

content slot
divider="top" — the brand accent
faded teal hairline, fades at both ends

Recent activity

The hairline above reads as a stitched-thread page-break. 2px tall, horizontal gradient from transparent → hsl(var(--primary)/0.55) → transparent.

first entry
stacked sections — divider separates clusters
three stacked sections; second + third use divider='top'

Profile

First section — no divider.

Preferences

Stitched thread reads cleanly between clusters.

Privacy

Third section — divider again.

padding variants — padding="sm" · "lg" · "xl" · "3xl"
padding="sm"
heading
content
padding="lg"
heading
content
padding="xl"
heading
content
padding="3xl"
heading
content

<Form>

Semantic <form> with tokenized gap + padding for field spacing. No asChild (form semantics must stay). Optional activeHighlight renders a teal focus-within aura.

default — neutral form, gap="md"
<Form onSubmit={…}>
activeHighlight — click into an input to see the teal aura
activeHighlight={false} (default)
activeHighlight={true}
composed — Form owns field rhythm, Stack owns field internals
Form gap="lg" · Stack gap="xs" for label+control pairs

All fields required.

Batch 2 — Inline

Inline wrapper family for icon-text, meta pairs, field pairs, and shortcuts.

<IconText>

Inline icon + text pair. intent colors both icon and text together via currentColor inheritance. Defaults: intent="none", size="md", gap="xs", align="center". Not a list-item — use IconBadge + Stack for that shape.

intent matrix (size="md")
intent="none"
Tampa Bay
intent="muted"
Tampa Bay
intent="accent"
Tampa Bay
intent="success"
Tampa Bay
intent="warning"
Tampa Bay
intent="destructive"
Tampa Bay
intent="info"
Tampa Bay
size × sm / md / lg
size="sm"
2 minutes ago
size="md"
2 minutes ago
size="lg"
2 minutes ago
composed — rendering evidence sites from the span inventory
activity feed row (MapPin + location)
Downtown St. Pete
quick-glance label (Target + caption)
My Wants
status row (success check)
Verified trader
warning strip (shield + destructive)
Review needed before listing
trailing slot (count badge)
Notifications
3 new
nested in a Row for layout
Today
12 replies
Matching

<MetaPair>

Small-caps label + value. Label ALWAYS renders as <Text variant="overline" color="muted">; value defaults to body-sm. Two orientations; horizontal optionally takes a fixed labelWidth for column alignment.

stacked — default
orientation="stacked"
Created2 days ago
long value
TraderMaya Alvarez (@maya_makes)
numeric stat (QuickGlance shape)
Trades42
rich value
Status
Active
horizontal — labelWidth variants
orientation="horizontal" labelWidth="auto"
Username@maya_makes
MemberSince Jan 2024
labelWidth="xs" (24px) — "Gives" / "Gets" column alignment
GivesVintage Polaroid camera
GetsLeather journal set
labelWidth="md" (48px) — wider fixed column
LocationTampa, FL
ActivityLast seen 3h ago
Rating4.9 / 5.0 across 28 trades
composed — stat-card shape (QuickGlance pattern rebuilt)
My Posts
My Posts
12
My Wants
My Wants
8
Trades
Trades
42
Community
Groups
5

<FieldPair>

Label on top, value below. labelFor wraps the label in semantic <Label htmlFor> (form pairs); omit it for display pairs. Optional hint, error, required. Defaults: gap="xs".

form pair — Input child with label + hint
labelFor="title" (semantic Label)
with hint
Shown on the post detail page and in search results.
required
We only use this for transactional messages.
error state
Please enter a valid 5-digit US zip code.
display pair — no labelFor, plain caption label
readonly value
Trade partner

Maya Alvarez

value with hint
Offered item

Vintage Polaroid SX-70 camera

This item was listed with 3 photos
required display
Verification status*
Verified
Required for trades over $100
error display
Phone number

Not set

Missing — add one in account settings

<AvatarIdentity>

Avatar + name + optional subtitle + optional trailing slot. Auto-derives initials from a name string. Size drives both avatar dimensions and text variants.

size × sm / md / lg
size="sm" (h-8)
MA
Maya Alvarez@maya_makes
size="md" (h-10, default)
MA
Maya Alvarez@maya_makes
size="lg" (h-12)
MA
Maya Alvarez@maya_makes
auto-derived initials from name strings
"Maya Alvarez"
MA
Maya AlvarezTwo words → MA
"Maya"
MA
MayaOne word → MA
"Jordan K. Smith"
JS
Jordan K. SmithFirst + last → JS
"" (empty) → "?"
?
Graceful fallback
trailing slot
trailing=Badge (verified)
MA
Maya Alvarez@maya_makes · joined 2024
Verified
trailing=IconText (timestamp)
JS
Jordan K. SmithLast seen 3h ago
3h
trailing=Button (action)
RC
River Chen@river_trades · 28 trades
composed — chat sidebar row + trader list (evidence sites)
chat sidebar row (ConversationList shape)
MA
Maya AlvarezSee you tomorrow!
2
JS
Jordan K. SmithSent you a polaroid
RC
River ChenInterested in the lens
1
chain participant (ChainParticipantList shape)
YO
Yougives Polaroid camera
in chain
MA
Maya Alvarezgives Film canister bundle
in chain
JS
Jordan K. Smithgives Leather journal set
in chain

<KeyboardShortcut>

OS-adaptive keycap chain. "mod" resolves to ⌘ on Mac / Ctrl on PC. SSR-safe: server + first client render show PC glyphs; useEffect flips to Mac on mount. The dev/style "os" prop lets both code paths render side-by-side.

auto detection (matches your current OS)
keys="mod+k"
Ctrl+K
keys="mod+shift+p"
Ctrl+Shift+P
keys="esc"
Esc
os="mac" vs os="pc" — both code paths rendered
os="mac"
+K
open command menu
++P
new post
+
accept offer
os="pc"
Ctrl+K
open command menu
Ctrl+Shift+P
new post
Alt+Enter
accept offer
size × sm / md
size="sm" (default — inline within running text)
+K
++
size="md" (standalone in help overlays)
+K
++
separator variants
separator="+" (default)
++K
separator="" (tight grouping)
K
separator="then"
GthenP
composed — command-menu row (the future callsite)
<Row> + <IconText> + <KeyboardShortcut> inside a Card
Search posts
+K
New post
++P
Open messages
+M
Show help
?