Layout
Organize components in your view
Layout basics
Views use the
Stack
component to organize items on the page.The simplest layout uses
Stack
without any props. This will lay out items vertically some with
spacing in between each item.tsxCopied1<Stack>2<Card>Content</Card>3<Card>Content</Card>4<Card>Content</Card>5</Stack>
You can also lay out items horizontally by using the
direction
prop.tsxCopied1<Stack direction="row">2<Card>Content</Card>3<Card>Content</Card>4<Card>Content</Card>5</Stack>
Nesting layouts
You can achieve more complex layouts by nesting stacks.
In the following example, multiple
Stack
components are nested inside each other to create a
search bar, action group, and list of content.tsxCopied1<Stack spacing="lg">2<Stack direction="row" justify="space-between">3<Stack direction="row" justify="end">4<TextInput placeholder="Enter a search term" />5<Button>Search</Button>6</Stack>7<Stack direction="row">8<Button preset="tertiary">Action 1</Button>9<Button preset="tertiary">Action 2</Button>10</Stack>11</Stack>12<Stack>13<Card>14<Stack direction="row" justify="space-between">15<Label>Content</Label>16<Stack direction="row">17<PencilIcon />18<TrashIcon />19</Stack>20</Stack>21</Card>22<Card>23<Stack direction="row" justify="space-between">24<Label>Content</Label>25<Stack direction="row">26<PencilIcon />27<TrashIcon />28</Stack>29</Stack>30</Card>31</Stack>32</Stack>
Main detail
In the following example, the main content of the page is a table. The detail section has details
about the cat.
When a row is selected, the detail section pops up with the details about the cat and shrinks to
about
2/3
of the width. The detail section takes up 40u
(see Sizing) and
grows to fill the remaining space. If the screen gets too small, the detail section will get wrapped
to the next row.tsxCopied1<Stack direction="row" wrap>2<Table3id={catsTable.id}4title="Cats"5rowSelection="single"6defaultPageSize={3}7task="list_cats"8grow9width={catsTable.selectedRow ? "2/3" : "full"}10/>11{catsTable.selectedRow && (12<Card width="40u" grow>13<Title order={3}>{catsTable.selectedRow.name}</Title>14<Text>{`My name is ${catsTable.selectedRow.name}`}</Text>15<Text>{`I am a ${catsTable.selectedRow.breed}`}</Text>16</Card>17)}18</Stack>
Grid
You can emulate a grid layout by using a row
Stack
for each row.In the following example, we have a 2x2 grid of tables. Each table fills up the entire row. If a row
gets small enough where both tables can no longer fit, a table will wrap to the next row. You can
test this out by resizing your browser.
tsxCopied1<Stack>2<Stack direction="row" wrap>3<Table showFilter={false} defaultPageSize={3} task="list_dogs" width="72u" grow />4<Table showFilter={false} defaultPageSize={3} task="list_dogs" width="72u" grow />5</Stack>6<Stack direction="row" wrap>7<Table showFilter={false} defaultPageSize={3} task="list_cats" width="72u" grow />8<Table showFilter={false} defaultPageSize={3} task="list_cats" width="72u" grow />9</Stack>10</Stack>
Dashboard
You can combine these concepts to lay out a fairly complex and responsive dashboard.
tsxCopied1<Stack>2<Stack direction="row" justify="space-between">3<Title>Dashboard</Title>4<Stack direction="row">5<TextInput placeholder="Enter a search term" />6<Button>Search</Button>7</Stack>8</Stack>9<Stack direction="row" wrap>10<Table title="Cats" defaultPageSize={3} task="list_cats" width="1/2" grow />11<Card grow>Content</Card>12<Card grow>Content</Card>13</Stack>14<Stack direction="row" wrap>15<Card grow>Content</Card>16<Card grow>Longer content</Card>17<Card grow>This content takes up a lot of space</Card>18</Stack>19<Table title="Dogs" defaultPageSize={3} task="list_dogs" />20</Stack>
Sizing
Most of our components have the
width
and height
sizing props, which controls how much space the
component takes up. width
and height
take in tokens that represent the size.Relative sizing
These are tokens that represent a fraction of the available space.
Token | Value |
---|---|
1/2 | 50% |
1/3 , 2/3 | 33.333333%, 66.666667% |
1/4 , 2/4 , 3/4 | 25%, 50%, 75% |
1/5 , 2/5 , 3/5 , 4/5 | 20%, 40%, 60%, 80% |
1/6 , 2/6 , 3/6 , 4/6 , 5/6 | 16.666667%, 33.333333%, 50%, 66.666667%, 83.333333% |
1/12 , 2/12 , 3/12 , 4/12 , 5/12 , 6/12 , 7/12 , 8/12 , 9/12 , 10/12 , 11/12 | 8.333333%, 16.666667%, 25%, 33.333333%, 41.666667%, 50%, 58.333333%, 66.666667%, 75%, 83.333333%, 91.666667% |
full | 100% |
Absolute sizing
These are tokens that represent an absolute size. We use a 4px sizing unit that we represent using
u
, for unit
. For example, a width of 4u
is 16px.We use a 4px scale to help to better align components in your View without having to tweak raw pixel
values.
Token | Value |
---|---|
0.5u | 0.125rem (2px) |
1u | 0.25rem (4px) |
1.5u | 0.375rem (6px) |
2u | 0.5rem (8px) |
2.5u | 0.625rem (10px) |
3u | 0.75rem (12px) |
3.5u | 0.875rem (14px) |
4u | 1rem (16px) |
5u | 1.25rem (20px) |
6u | 1.5rem (24px) |
7u | 1.75rem (28px) |
8u | 2rem (32px) |
9u | 2.25rem (36px) |
10u | 2.5rem (40px) |
11u | 2.75rem (44px) |
12u | 3rem (48px) |
14u | 3.5rem (56px) |
16u | 4rem (64px) |
20u | 5rem (80px) |
24u | 6rem (96px) |
28u | 7rem (112px) |
32u | 8rem (128px) |
36u | 9rem (144px) |
40u | 10rem (160px) |
44u | 11rem (176px) |
48u | 12rem (192px) |
52u | 13rem (208px) |
56u | 14rem (224px) |
60u | 15rem (240px) |
64u | 16rem (256px) |
72u | 18rem (288px) |
80u | 20rem (320px) |
96u | 24rem (384px) |
128u | 32rem (512px) |
192u | 48rem (768px) |
256u | 64rem (1020px) |
We discourage working with raw pixel values. However, you can pass a px value into
width
or
height
, e.g. width="100px"
.