Layout
Tessera UI uses a systematic spacing scale with a comfortable default density. This ensures visual rhythm, consistent alignment, and predictable component composition.
Spacing Scale
Section titled “Spacing Scale”All spacing — padding, margins, gaps — uses tokens from this scale. Never use arbitrary pixel values.
| Token | Value | Pixels | Common Usage |
|---|---|---|---|
--ts-spacing-0 | 0 | 0 | Reset, no spacing |
--ts-spacing-1 | 0.375rem | 6px | Tight gaps (label-to-field, badge padding) |
--ts-spacing-2 | 0.625rem | 10px | Default inline gap, button padding (sm) |
--ts-spacing-3 | 1rem | 16px | Component internal padding (alert, modal sections) |
--ts-spacing-4 | 1.25rem | 20px | Standard padding (md), section gaps |
--ts-spacing-5 | 1.5rem | 24px | Modal header/footer padding |
--ts-spacing-6 | 2rem | 32px | Card padding (lg), modal body |
--ts-spacing-8 | 2.5rem | 40px | Large section spacing, button padding (xl) |
--ts-spacing-10 | 3rem | 48px | Section separators |
--ts-spacing-12 | 4rem | 64px | Page section spacing |
--ts-spacing-16 | 5rem | 80px | Large layout gaps, modal max-height offset |
Spacing Rhythm
Section titled “Spacing Rhythm”The spacing scale uses a comfortable progression (6/10/16/20/24/32px) that provides natural visual rhythm:
6px— minimum spacing between closely related elements10px— default inline spacing (between icon and label, form field gap)16px— standard padding for medium-density components24px— comfortable padding for spacious components32px+— layout-level spacing between sections
Spacing Patterns in Components
Section titled “Spacing Patterns in Components”Component internal padding
Section titled “Component internal padding”| Component | Padding | Token |
|---|---|---|
| Button (md) | 10px 20px | spacing-2 spacing-4 |
| Input (md) | 10px 16px | spacing-2 spacing-3 |
| Card (md) | 20px | spacing-4 |
| Card (lg) | 32px | spacing-6 |
| Alert | 16px 20px | spacing-3 spacing-4 |
| Modal body | 16px 32px | spacing-3 spacing-6 |
Gaps between elements
Section titled “Gaps between elements”| Context | Gap | Token |
|---|---|---|
| Button icon ↔ label | 10px | spacing-2 |
| Toggle track ↔ label | 10px | spacing-2 |
| Alert icon ↔ message | 16px | spacing-3 |
| Modal footer buttons | 10px | spacing-2 |
| Label ↔ input field | 6px | spacing-1 |
| Input ↔ help text | 6px | spacing-1 |
Grid Tokens
Section titled “Grid Tokens”Tessera UI provides grid tokens for building consistent page layouts:
| Token | Value | Usage |
|---|---|---|
--ts-grid-columns | 12 | Number of columns in the grid |
--ts-grid-gutter | var(--ts-spacing-6) (32px) | Gap between columns |
--ts-grid-margin | var(--ts-spacing-4) (20px) | Outer margin of the grid container |
These tokens are designed for use with CSS Grid:
.page-grid { display: grid; grid-template-columns: repeat(var(--ts-grid-columns), 1fr); gap: var(--ts-grid-gutter); padding-inline: var(--ts-grid-margin);}Grid values adapt automatically in density modes — compact density reduces the gutter to spacing-4 (16px), and spacious density increases it to spacing-8 (40px).
Breakpoint Tokens
Section titled “Breakpoint Tokens”Breakpoint values are available as CSS custom properties for reference and JavaScript access. Because CSS custom properties cannot be used in @media queries, use the raw values in your media queries but reference these tokens as the source of truth.
| Token | Value | Usage |
|---|---|---|
--ts-breakpoint-sm | 640px | Mobile |
--ts-breakpoint-md | 768px | Tablet |
--ts-breakpoint-lg | 1024px | Desktop |
--ts-breakpoint-xl | 1280px | Wide desktop |
--ts-breakpoint-2xl | 1536px | Ultra-wide |
Density Modes
Section titled “Density Modes”Tessera UI supports three density modes that remap spacing and font-size tokens globally. Apply a density by adding data-density to any ancestor element:
<body data-density="compact"> <!-- All components use tighter spacing --></body>Spacing comparison across densities
Section titled “Spacing comparison across densities”| Token | Compact | Comfortable (default) | Spacious |
|---|---|---|---|
--ts-spacing-1 | 4px | 6px | 8px |
--ts-spacing-2 | 8px | 10px | 12px |
--ts-spacing-3 | 12px | 16px | 20px |
--ts-spacing-4 | 16px | 20px | 24px |
--ts-spacing-5 | 20px | 24px | 32px |
--ts-spacing-6 | 24px | 32px | 40px |
--ts-font-size-xs | 11px | 12px | 12px |
--ts-font-size-sm | 12px | 14px | 16px |
--ts-font-size-md | 14px | 16px | 18px |
--ts-grid-gutter | spacing-4 | spacing-6 | spacing-8 |
When to use each density:
- Compact — Data-dense UIs (tables, dashboards, admin panels) where screen real estate is at a premium
- Comfortable (default) — General-purpose applications with balanced readability and density
- Spacious — Content-focused pages (marketing, documentation, onboarding) where breathing room aids comprehension
Density can be applied at any level of the DOM tree, so you can mix densities within a single page (e.g., a compact data table inside a comfortable page layout).
Touch Target Minimum Sizes
Section titled “Touch Target Minimum Sizes”Interactive elements must meet minimum size requirements for accessible touch input:
| Token | Value | Usage |
|---|---|---|
--ts-touch-target-min | 44px | Default minimum (WCAG 2.5.5 AAA) |
--ts-touch-target-compact | 32px | Compact mode minimum (WCAG 2.5.8 AA) |
In compact density mode, --ts-touch-target-min is automatically remapped to the compact value. Even in compact mode, ensure touch targets are never smaller than 32px.
Container Patterns
Section titled “Container Patterns”Modal widths
Section titled “Modal widths”Modals provide five size options for different content needs:
| Size | Max Width | Usage |
|---|---|---|
xs | 320px | Confirmations, simple prompts |
sm | 440px | Forms, notifications |
md | 560px | Standard dialogs |
lg | 720px | Complex forms, data entry |
xl | 960px | Tables, rich content |
Layout Components
Section titled “Layout Components”Tessera UI provides five layout primitives that eliminate the need for manual display: flex / display: grid styling. Default to these components for all structural layout.
Stack-first approach
Section titled “Stack-first approach”Start with <ts-stack> for vertical flow and <ts-row> for horizontal flow. These cover the majority of layout needs with built-in gap support using the spacing scale.
Component reference
Section titled “Component reference”<ts-stack> — Vertical flex layout
Section titled “<ts-stack> — Vertical flex layout”| Prop | Type | Default | Description |
|---|---|---|---|
gap | 0–16 | 4 | Spacing between children (maps to --ts-spacing-{n}) |
align | start | center | end | stretch | stretch | Cross-axis alignment |
<ts-row> — Horizontal flex row
Section titled “<ts-row> — Horizontal flex row”| Prop | Type | Default | Description |
|---|---|---|---|
gap | 0–16 | 2 | Spacing between children |
align | start | center | end | stretch | baseline | center | Cross-axis alignment |
justify | start | center | end | between | around | evenly | start | Main-axis distribution |
wrap | boolean | true | Whether items wrap to the next line |
stack-at | sm | md | lg | xl | 2xl | — | Breakpoint at which the row stacks vertically |
<ts-grid> — CSS Grid layout
Section titled “<ts-grid> — CSS Grid layout”| Prop | Type | Default | Description |
|---|---|---|---|
columns | 1–12 | auto | 3 | Number of columns, or auto for auto-fill |
gap | 0–16 | 4 | Spacing between grid items |
min-column-width | CSS length | 200px | Minimum column width when columns="auto" |
<ts-container> — Centered max-width wrapper
Section titled “<ts-container> — Centered max-width wrapper”| Prop | Type | Default | Description |
|---|---|---|---|
size | sm | md | lg | xl | full | lg | Max-width preset (sm=640px, md=768px, lg=1024px, xl=1280px) |
padding | boolean | true | Whether to add horizontal padding |
<ts-spacer> — Explicit spacing element
Section titled “<ts-spacer> — Explicit spacing element”| Prop | Type | Default | Description |
|---|---|---|---|
size | 0–16 | 4 | Vertical space (maps to --ts-spacing-{n}) |
Responsive stacking
Section titled “Responsive stacking”Use the stack-at prop on <ts-row> to collapse a horizontal row into a vertical stack at a given breakpoint:
<ts-row gap="4" stack-at="md"> <ts-card>Sidebar</ts-card> <ts-card>Main content</ts-card></ts-row>Below the md breakpoint (768px), the row becomes a stack automatically.
Auto-grid
Section titled “Auto-grid”Set columns="auto" with a min-column-width to create a responsive grid that fills columns based on available space — no media queries needed:
<ts-grid columns="auto" min-column-width="280px" gap="4"> <ts-card>Item 1</ts-card> <ts-card>Item 2</ts-card> <ts-card>Item 3</ts-card> <ts-card>Item 4</ts-card></ts-grid>Container widths
Section titled “Container widths”Use <ts-container> to center page content with a maximum width:
<ts-container size="lg"> <p>This content is constrained to 1024px and centered on the page.</p></ts-container>Nesting layout components
Section titled “Nesting layout components”Combine all layout primitives to build complete page structures:
<ts-container size="lg"> <ts-stack gap="6"> <h1>Dashboard</h1> <ts-grid columns="auto" min-column-width="280px" gap="4"> <ts-card>...</ts-card> <ts-card>...</ts-card> <ts-card>...</ts-card> </ts-grid> <ts-row gap="2" justify="end"> <ts-button>Cancel</ts-button> <ts-button variant="primary">Save</ts-button> </ts-row> </ts-stack></ts-container>Responsive Considerations
Section titled “Responsive Considerations”Tessera UI components are Web Components — they adapt to their container rather than the viewport. Components do not ship with built-in responsive breakpoints. Instead:
- Use
blockprop on buttons to make them full-width on small screens - Use CSS container queries in your layout to adjust component sizing
- Modal widths use
max-width— they naturally shrink on narrow viewports - Spacing tokens are
rem-based — they scale if the user changes their browser font size
Container Queries
Section titled “Container Queries”Because Tessera UI components are Web Components with Shadow DOM, container queries are a natural fit for responsive component behavior. Wrap components in a container-type element to adapt layout based on available space rather than viewport width:
.component-wrapper { container-type: inline-size;}
@container (max-width: 400px) { /* Stack buttons vertically in narrow containers */ .button-group { flex-direction: column; }}Container queries are preferred over media queries for component-level responsiveness because they respond to the component’s actual space, not the page viewport.