Layout
May 29, 2026 · View on GitHub
Core layout primitives
These are the fundamental building blocks for spacing, alignment, and visual structure. Use them to compose any UI inside a page.
Box
Box provides a set of padding options which can be used to create container elements with internal
spacing. All padding props accept a numeric value or a responsive object {mobile, tablet?, desktop}.
<Box paddingX={16} paddingY={32}>
<Text2>Example</Text2>
</Box>
:warning: Do not use Box to add external spacings or distribute items, instead use Stack or Inline.
You can also use Box as a fixed width container:
<Box width={80}>
<Text2>Example</Text2>
</Box>
Stack
Vertically distributes its children using the given space separation.
<Stack space={24}>
<Child1 />
<Child2 />
<Child3 />
</Stack>
Inline
Horizontally distributes its children using the given space separation. This component can be considered as
a horizontal Stack, and it covers the most common row-layout use cases you might otherwise solve with
display: flex.
It supports:
- horizontal distribution via
space={number}orspace="between" | "around" | "evenly" - vertical alignment of children via
alignItems="flex-start" | "flex-end" | "center" | "stretch" | "baseline" - wrapping via
wrapand row spacing viaverticalSpace
:information_source: Check Inline in
Storybook to learn more about it.
numeric space
<Inline space={16} alignItems="center">
<Child1 />
<Child2 />
<Child3 />
</Inline>
between
Distribute items evenly. The first item is flush with the start, the last is flush with the end
<Inline space="between">
<Child1 />
<Child2 />
<Child3 />
</Inline>
around
Distribute items evenly. Items have a half-size space on either end
<Inline space="around">
<Child1 />
<Child2 />
<Child3 />
</Inline>
evenly
Distribute items evenly. Items have equal space around them
<Inline space="evenly">
<Child1 />
<Child2 />
<Child3 />
</Inline>
nesting
Nest Inline components to compose richer rows. A common pattern groups a leading icon and label on the left
with a value on the right via space="between":
<Inline space="between" alignItems="center">
<Inline space={8} alignItems="center">
<IconTruckRegular size={24} color={skinVars.colors.neutralHigh} />
<Text2 regular>Envío:</Text2>
</Inline>
<Text2 regular>Mañana, gratis</Text2>
</Inline>
The outer Inline distributes the two groups to opposite ends; the inner Inline keeps the icon tightly
grouped with its label at a fixed gap.
Grow
Use the expand prop to make one or more children of an Inline grow to fill the remaining horizontal space.
It takes the index (or an array of indexes) of the children that should grow. Indexes follow
React.Children.toArray order, so empty nodes (null, false) are skipped but rendered elements always
count. You don't wrap the growing child in anything — Inline already wraps every child in its own element:
<Inline space={56} alignItems="center" expand={1}>
<Text7>4,6</Text7>
<InfoRating
value={4}
icon={{
ActiveIcon: IconStarFilled,
InactiveIcon: IconStarLight,
color: skinVars.colors.textPrimary,
}}
/>
<Text3 regular>150 valoraciones</Text3>
</Inline>
<Inline space={16} alignItems="center" expand={[1, 2]}>
<IconTruckRegular size={24} color={skinVars.colors.neutralHigh} />
<TextField name="firstName" label="First name" fullWidth />
<TextField name="lastName" label="Last name" fullWidth />
</Inline>
Common mistakes. Inline wraps each child in its own element, so growing a child by wrapping it in a
<div style={{flex: 1}}> (or flex-grow) does nothing useful. Neither does <Box style={{...}}> — Box has
no style prop, so a flex or width passed that way is silently dropped and the row collapses or overflows its
container. Reach for expand (and <Box width={N}> for any fixed sibling) instead.
Align
Positions its children within a container using CSS grid alignment. Useful for centering content or placing it at specific positions within a defined area.
<Align x="center" y="center" height="100%">
<Text2 regular>Centered content</Text2>
</Align>
<Align x="end">
<ButtonPrimary onPress={() => {}}>Action</ButtonPrimary>
</Align>
Grid / GridItem
A low-level CSS Grid component for creating custom grid layouts. For page-level column layouts, prefer
GridLayout instead. Grid is ideal for card grids, image galleries, or any layout needing explicit
row/column control.
<Grid columns={3} gap={{mobile: 8, desktop: 16}}>
<Card1 />
<Card2 />
<Card3 />
</Grid>
<Grid columns={4} gap={16}>
<GridItem columnSpan={2}>
<FeatureCard />
</GridItem>
<GridItem>
<SmallCard1 />
</GridItem>
<GridItem>
<SmallCard2 />
</GridItem>
</Grid>
NegativeBox
Some components, like non boxed Lists, need to be rendered overflowing its container, because the hover effect
is larger than the container. This can be achieved using a NegativeBox.
By default both sides get negative margins. Use the left or right props to apply margin on one side only.
Without NegativeBox
| Outline | Preview |
|---|---|
As you can see there are two problems. The hover is not filling available horizontal space and Row circles are
not aligned with the content container. These problems are solved using NegativeBox.
With NegativeBox
<ResponsiveLayout>
<NegativeBox>
<RowList>
<Row1 />
<Row2 />
<Row3 />
</RowList>
</NegativeBox>
</ResponsiveLayout>
| Outline | Preview |
|---|---|
Hover effect fills horizontal space and circles are aligned with the container edge.
Divider
A simple horizontal divider line. Theme-variant-aware (adapts its color to the current ThemeVariant
context). Takes no props.
<Stack space={16}>
<Text2 regular>Section A</Text2>
<Divider />
<Text2 regular>Section B</Text2>
</Stack>
HorizontalScroll
A container that enables horizontal scrolling for its children. Useful for scrollable rows of cards, chips, tags, or any horizontally overflowing content.
<HorizontalScroll>
<Inline space={8}>
<Chip value="Option 1">Option 1</Chip>
<Chip value="Option 2">Option 2</Chip>
<Chip value="Option 3">Option 3</Chip>
<Chip value="Option 4">Option 4</Chip>
</Inline>
</HorizontalScroll>
Boxed
A rounded container with background color and optional border. Theme-variant-aware: the background and border
automatically adapt based on the current and specified variant. Useful for creating visually distinct
sections or card-like containers without card semantics.
<Boxed>
<Box padding={16}>
<Text2 regular>Content inside a boxed container</Text2>
</Box>
</Boxed>
Overlay
A full-screen fixed overlay that covers the viewport. Used internally by dialogs, drawers, and sheets, but available for custom overlay use cases.
<Overlay onPress={handleClose} disableScroll>
<MyCustomModal />
</Overlay>
StackingGroup
Displays a group of items (typically avatars or icons) with optional overlapping. Shows a "+N" indicator when
items exceed maxItems.
<StackingGroup stacked maxItems={3} moreItemsStyle={{type: 'circle', size: 40}}>
<Avatar size={40} src={avatar1} />
<Avatar size={40} src={avatar2} />
<Avatar size={40} src={avatar3} />
<Avatar size={40} src={avatar4} />
<Avatar size={40} src={avatar5} />
</StackingGroup>
Page layouts
These components define the overall structure of a page or screen. They handle responsive breakpoints, constrain content width, and provide standard page patterns.
ResponsiveLayout
Creates a responsive container for your page content. The size of this container depends on the viewport size.
Supports a variant prop to set background color and theme variant, and fullWidth to remove margin
constraints.
<ResponsiveLayout>
<MyFeature />
</ResponsiveLayout>
| Mobile | Tablet | Desktop |
|---|---|---|
HeaderLayout
The HeaderLayout is responsible for render the page header and related components. It uses the
ResponsiveLayout internally so you must not wrap it inside one.
<HeaderLayout header={<Header title="Header" />} />
<ResponsiveLayout>
<MyFeature />
</ResponsiveLayout>
| Mobile | Tablet | Desktop |
|---|---|---|
Components that include ResponsiveLayout internally
The following components manage their own ResponsiveLayout internally. Do not wrap them inside a
ResponsiveLayout — that would create a double-nested layout that breaks spacing and alignment.
| Component | Reason |
|---|---|
HeaderLayout | Wraps its header content in a responsive container |
MainSectionHeaderLayout | Contains its own responsive wrapper |
Hero | Manages internal responsive layout for content and media |
CoverHero | Applies responsive layout to its text content column |
MasterDetailLayout | Full-width responsive grid managed internally |
ButtonFixedFooterLayout | Footer buttons aligned via an internal responsive container |
NavigationBar | All navigation bar variants (including MainNavigationBar and FunnelNavigationBar) center content using an internal ResponsiveLayout |
Tabs | Tab list constrained with ResponsiveLayout fullWidth |
SuccessFeedbackScreen | All feedback screen variants contain their own page layout |
LoadingScreen | BrandLoadingScreen also uses an internal responsive text layout |
These components are placed directly at the page level, side by side with ResponsiveLayout blocks, not
inside them:
<MainNavigationBar sections={[...]} selectedIndex={0} />
<HeaderLayout header={<Header title="Page Title" />} />
<Tabs selectedIndex={0} onChange={setTab} tabs={[{text: 'Tab 1'}, {text: 'Tab 2'}]} />
<ResponsiveLayout>
<Box paddingY={24}>
<Stack space={16}>
<Text2 regular>Content</Text2>
</Stack>
</Box>
</ResponsiveLayout>
GridLayout
A 12-column grid with predefined templates for common page layouts. Must be used inside a ResponsiveLayout.
Available templates:
- Split layouts (use
left/rightprops):'6+6','8+4','5+4','4+6','3+9' - Centered single-column layouts (use
children):'10','8' - No template (raw 12-column grid, use
children)
<ResponsiveLayout>
<GridLayout
template="6+6"
left={<LeftComponent />}
right={<RightComponent />}
/>
</ResponsiveLayout>
| Mobile | Tablet | Desktop |
|---|---|---|
MasterDetailLayout
A common layout pattern with a list of items in a left sidebar and a detail view in the main content area. In mobile, this translates to a navigation of 2 levels: a first screen with the list and a second screen with the content.
<MasterDetailLayout isOpen={isOpen} master={listView} detail={detailView} />
The isOpen prop controls whether the master (when false) or detail (when true) view is shown in mobile.
Take into account that the detail view is always visible in desktop, so if you want to show an empty state
in desktop when there isn't any selected item from the aside list, you can do something like this:
<MasterDetailLayout isOpen={isOpen} master={listView} detail={isOpen ? detailView : emptyCase} />
| Mobile Master | Mobile Detail | Desktop |
|---|---|---|
FixedFooterLayout
A layout with a footer that sticks to the bottom of the viewport. The footer becomes fixed when there is enough available height, and scrolls with the content otherwise. Includes an elevation shadow on mobile when content is scrollable.
<FixedFooterLayout
footer={
<Box paddingX={16} paddingY={8}>
<ButtonLayout primaryButton={<ButtonPrimary onPress={handleSubmit}>Confirm</ButtonPrimary>} />
</Box>
}
>
<ResponsiveLayout>
<Box paddingY={24}>
<Stack space={16}>{/* page content */}</Stack>
</Box>
</ResponsiveLayout>
</FixedFooterLayout>
ButtonFixedFooterLayout
A convenience wrapper around FixedFooterLayout specifically for pages that need a fixed footer with buttons.
Handles the button layout, responsive padding, and footer visibility automatically.
<ButtonFixedFooterLayout
button={<ButtonPrimary onPress={handleConfirm}>Confirm</ButtonPrimary>}
secondaryButton={<ButtonSecondary onPress={handleCancel}>Cancel</ButtonSecondary>}
>
<ResponsiveLayout>
<Box paddingY={24}>
<Stack space={16}>{/* page content */}</Stack>
</Box>
</ResponsiveLayout>
</ButtonFixedFooterLayout>
ButtonLayout
Arranges a primary button, secondary button, and/or link in a standardized layout. Handles responsive stacking and alignment.
<ButtonLayout
align="full-width"
primaryButton={<ButtonPrimary onPress={handlePrimary}>Accept</ButtonPrimary>}
secondaryButton={<ButtonSecondary onPress={handleSecondary}>Cancel</ButtonSecondary>}
/>
DoubleField
Places two form fields side by side with configurable width ratios ('50/50', '40/60', '60/40'). Used
inside forms to group related fields horizontally.
<DoubleField layout="50/50">
<TextField name="firstName" label="First name" />
<TextField name="lastName" label="Last name" />
</DoubleField>
Vertical rhythm
Vertical rhythm is an important concept in web design and development. It makes the page feel consistent and visually pleasant. It is important to maintain the rhythm across the site.
Elements inside our page content can be divided in 3 main groups:
- Container: should have a top and bottom space of 24px
- Sections: should have a 32px space between them
- Elements: should have a 16px separation between them
This is how a page layout could look like:
<HeaderLayout header={<Header title="Header" />} />
<ResponsiveLayout>
<Box paddingY={24}>
<Stack space={32}>
<Stack space={16}>
<Title1>Section 1</Title1>
<Text2 regular>
Some example text
</Text2>
</Stack>
<Stack space={16}>
<Title1>Section 2</Title1>
<NegativeBox>
<RowList>
<Row1 />
<Row2 />
<Row3 />
</RowList>
</NegativeBox>
</Stack>
</Stack>
</Box>
</ResponsiveLayout>
:pencil2: View this example in playroom
Doubts?
Don't hesitate to ask at Mistica Teams