Designing a layout system for big-screen dashboards
Adam Mark
Background
From 2020 to 2023, I developed dashboards and mapping tools for a warehouse automation system using TypeScript and React.
Problem
Our customers wanted to display system dashboards on large monitors. To support this requirement, our developers needed a way to build a variety of dashboards using a simple but flexible layout system.
Solution
I created a system of layout "strategies" that could handle any conceivable configuration of one to four panels:
A single strategy could take on multiple forms by moving the "breakpoints" between panels:
The code
First, I defined eight basic strategies:
type LayoutStrategy =
| 'one'
| 'one-by-one'
| 'one-by-two'
| 'two-by-one'
| 'two-by-two'
| 'one-over-one'
| 'one-over-two'
| 'two-over-one';
Then I used CSS Grid Layout to establish the default attributes of each strategy:
.dashboard {
display: grid;
...
}
.dashboard[data-strategy='one-by-one'] {
grid-template-areas: 'a b';
grid-template-columns: 1fr 3fr;
}
.dashboard[data-strategy='one-over-two'] {
grid-template-areas: 'a a' 'b c';
grid-template-rows: 15vh 85vh;
grid-template-columns: 1fr 1fr;
}
...
Then I created a utility method to manually override grid-template-rows and grid-template-columns if given custom breakpoints:
function computeBreakpoints(
strategy: LayoutStrategy,
breakpoints: number[]
): React.CSSProperties => {
...
return style;
}
}
Finally, I created a simple Dashboard component that accepts a strategy, optional breakpoints and child panels:
<Dashboard strategy="one-over-two" breakpoints={[0.15, 0.65]}>
<Panel color={Color.Red}>
Top
</Panel>
<Panel color={Color.Green}>
Left
</Panel>
<Panel color={Color.Blue}>
Right
</Panel>
</Dashboard>
Conclusion
My solution allowed us to spin up new dashboard designs with no fuss and a light code footprint.