Layout with Box
Build the dashboard shell with Flexbox in cells: a top bar, a sidebar and cards.
In this chapter
- A top bar
- Sidebar and cards
- Responsive by default
The console is a grid of cells. Text.js lays it out with Yoga, the same Flexbox engine React Native uses, so <Box> follows the CSS flexbox rules. Units are cells: p-1 is one column and one row of padding.
A top bar
Most screens are a column: a one-row bar, then everything else. Give the bar a fixed height with h-1 and let the content take the rest with grow.
Removed: import { Box, Text, useInput } from "@textjs/next";Added: import { Box, Spacer, Text, useInput } from "@textjs/next";export default function Page() { return (Removed: <Box className="flex-col border rounded px-2 py-1">Removed: <Text bold>▼ Acme Deploys</Text>Removed: <Text color="muted">Hello, console.</Text>Added: <Box className="flex-col grow">Added: <Box className="flex-row h-1 px-1 gap-2 shrink-0">Added: <Text bold>▼ Acme</Text>Added: <Text color="subtle">acme.local</Text>Added: <Spacer />Added: </Box>Added: <Box className="flex-row grow">{/* sidebar + cards */}</Box> </Box> );}<Spacer> is a growing box: anything after it is pushed to the right edge.
Sidebar and cards
A fixed-width sidebar with a right border, and three cards that share the remaining width. basis-0 with grow gives each card an equal share regardless of its content.
Added: const NAV = ["Overview", "Deployments", "Settings"];Added: Added: function Card({ title, value }: { title: string; value: string }) {Added: return (Added: <Box className="flex-col border rounded px-1 grow shrink basis-0" minWidth={14} minHeight={4}>Added: <Text color="subtle">{title}</Text>Added: <Text bold>{value}</Text>Added: </Box>Added: );Added: }Added: export default function Page() {Added: const [sidebar, setSidebar] = useState(true);Added: const [stacked, setStacked] = useState(false);Added: Added: useInput((e) => {Added: if (e.input === "s") setSidebar((v) => !v);Added: if (e.input === "d") setStacked((v) => !v);Added: });Added: return ( <Box className="flex-col grow"> {/* top bar */}Removed: <Box className="flex-row grow">{/* sidebar + cards */}</Box>Added: <Box className="flex-row grow">Added: {sidebar && (Added: <Box className="flex-col w-18 shrink-0 border-r px-1 pt-1">Added: {NAV.map((item) => <Text key={item}>{item}</Text>)}Added: </Box>Added: )}Added: <Box className={stacked ? "flex-col grow gap-1 p-1" : "flex-row grow items-start gap-1 p-1"}>Added: <Card title="Production" value="acme-web" />Added: <Card title="Deployments" value="6 today" />Added: <Card title="Build time" value="38s p50" />Added: </Box>Added: </Box> </Box> );}Press s and d in the console. Yoga recomputes the layout and only the rows that changed are repainted, so toggling the sidebar costs a single console.log.
Responsive by default
The grid follows the docked DevTools panel. Drag the console wider or taller and the cards reflow. When you need breakpoints, useBreakpoint() returns the current one, in cells.
Try it
This is Acme Deploys at the end of the chapter, running in DevTools. Click the pad, then use the keys below.
Open the console
The app renders in DevTools. Then click here and press s.
Open on a desktop
This demo renders in the Chrome DevTools console, which needs a desktop browser.
Quiz
2 questionsAnswer every question to complete the chapter.