Structures
Structures: anatomy, keyboard behavior, state, and theming in Askr.
Example
import { Button, Dialog, DialogContent, DialogTitle, DialogTrigger } from '@askrjs/themes/components';
<Dialog>
<DialogTrigger asChild><Button>Open settings</Button></DialogTrigger>
<DialogContent>
<DialogTitle>Project settings</DialogTitle>
<ProjectSettings />
</DialogContent>
</Dialog>Purpose
Block is described in the theme's own docs as "the only layout engine" — the single primitive responsible for spacing, sizing, alignment, and responsive flex direction across the whole component catalog. Canonical structural components such as Container, Section, and Grid compose that layout contract rather than introducing separate systems. Use Block direction="column" or Block direction="row" instead of the legacy Stack and Inline aliases in new code.
Install and import
Import structural components from the themes catalog: import { Block, Container, Section, Grid } from '@askrjs/themes/components'. Broader layout components such as Main, Sidebar, Header, and Footer are exported the same way and compose the same Block layout contract. Use Block with an explicit direction for row or column composition; Stack, Inline, and Shell are legacy compatibility aliases, not recommendations for new code.
Live examples
The example on this page composes Dialog with its trigger, content, and title as you would in application code. The pattern generalizes across the structural components: a root that owns open state, a trigger that trips it, and a portalled content region that takes focus. Read the composition rather than copying it verbatim — your own content, labels, and actions belong in the same slots.
Anatomy
Block's layout props are genuinely extensive: padding, paddingX, paddingY, margin, width, height, direction, align, justify, gap, grow, shrink, background, radius, shadow, sticky, top, and zIndex, among others. Every one of these accepts a ResponsiveValue<T> — either a bare value or a Partial<Record<'base' | 'sm' | 'md' | 'lg' | 'xl', T>> — so a single prop can carry a full mobile-first breakpoint schedule.
State model
Structural components are stateless by design — they're pure layout, driven entirely by the props you pass in on each render, not by internal open/closed or selected flags the way interactive components are. direction, for instance, is just one of Block's ResponsiveValue props, resolving to "row" | "column" | "row-reverse" | "column-reverse" at whichever breakpoint applies.
Keyboard and accessibility
Because Block and its presets render plain structural elements rather than interactive controls, there's no dedicated keyboard contract to document here — accessibility for structural components mostly comes down to choosing sensible native elements and letting content inside them (buttons, links, form controls) carry their own accessible behavior. Main, Header, and similar presets do map to meaningful landmark elements, which is worth preserving when you customize them.
Styling and tokens
Block-owned layout variables are explicitly called out as part of the public theme contract, meaning they resolve through theme tokens rather than hard-coded pixel values, so retheming spacing or breakpoints doesn't require touching component code. Responsive behavior is additive and mobile-first: base styles apply everywhere, and sm, md, lg, xl values layer on top via min-width media queries, never the other way around.
API
The real Block prop types are worth knowing by name: BlockSpace for padding/gap/margin scale ("0" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "page"), BlockSize for width/height ("auto" | "full" | "screen" | "content" | "sidebar" | "page" | "sm" | "md" | "lg" | "xl"), BlockAlign, BlockJustify, BlockBackground, BlockRadius, BlockShadow, and BlockZIndex ("header" | "sticky" | "fixed" | "dropdown" | "modal" | "popover" | "toast" | "tooltip"). Field and InputGroup, by contrast, are pure visual composition wrappers with no comparable layout prop surface — they exist to arrange form controls, not to lay out arbitrary content.
Edge cases
Because Block is the only layout engine, resist the temptation to reach for raw flexbox or grid CSS around it for one-off adjustments — inconsistent layout approaches are exactly what the single-engine design is meant to prevent. Also remember that broad slots like main, sidebar, and navbar are semantic presets over Block, not independent components with their own prop vocabulary, so their responsive behavior follows the same breakpoint rules as everything else.
Related pages
See Portals and Layers for how overlay content escapes normal document flow rather than being laid out by Block, and Customization for how Block's own CSS variables participate in the token override system.