Home

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.