Soren Learning

Chapter 4

Visual Hierarchy for Dashboards and Admin Panels

Listen to this article

If you spend your career as an engineer, the UI you'll ship most often isn't a polished consumer landing page. It's a dashboard. An admin panel. An internal tool. A B2B view that shows numbers, lists, and forms to people whose job depends on understanding them.

These surfaces are also where developers most consistently underinvest in visual design — partly because they're "just internal", partly because the prevailing belief is "as long as the data's right, the layout's fine." Both assumptions are wrong. Visual hierarchy is what determines whether someone glancing at a dashboard understands what's happening in 3 seconds or 30. And in operational contexts, that difference is the difference between a useful tool and one people work around.

This chapter covers what visual hierarchy actually is, the three ways developers consistently break it, and how to fix it in Tailwind code.


What hierarchy actually is

Visual hierarchy is the arrangement and presentation of elements such that some are perceived as more important than others. The key word is perceived — hierarchy is a property of how the user reads the screen, not a property of what's on it.

Five tools build hierarchy, in rough order of how much weight they pull:

  1. Size — bigger elements grab attention first.
  2. Weight — bold > semibold > regular > light.
  3. Colour — high-contrast > low-contrast; saturated > desaturated.
  4. Position — top-left dominates in left-to-right reading; center dominates over edges.
  5. Whitespace — isolated elements feel important; crowded ones feel secondary.

Elite dashboard design uses only the minimum amount of hierarchy needed. A common mistake is layering all five — bigger AND bolder AND brighter AND centered AND with more whitespace — which creates noise rather than clarity.


How users actually read dashboards

Two reading patterns dominate:

The F-pattern

For text-heavy screens (long pages, articles, lists), eyes track an F-shape: the top horizontal bar gets full attention, then the second horizontal bar gets partial, then a vertical scan down the left side, with diminishing engagement.

Implication: the top of the screen is where you put what matters. The further down a user has to scan, the less attention each element gets. Important metrics belong at the top. Critical actions belong at the top. Secondary navigation can live below.

The Z-pattern

For sparser screens (landing pages, simple dashboards with a few large elements), eyes track a Z-shape: top-left to top-right, diagonal to bottom-left, then bottom-right. The four corners and the diagonal carry the most attention.

Implication: the bottom-right corner is the second-most important position on a screen. It's where the primary CTA tends to live in well-designed marketing pages — the "Start now" or "Sign up" button.

These aren't laws — eye-tracking studies show heavy individual variation — but they're useful priors. If you're not sure where to put something, the top-left earns the most attention; the center gets the second-most; the bottom-right gets the third.


The three ways developers break hierarchy

Most "this dashboard feels off" reactions trace to one of three patterns. Each is an over-correction of an engineering instinct.

1. The "everything is equal" wall

Twelve cards in a 4×3 grid, all the same size, same border, same colour. Same data point in each. The screen tells the user: I have 12 things to show you, and I have no opinion about which one matters.

// Anti-pattern: visually flat
<div className="grid grid-cols-4 gap-4">
  {metrics.map((m) => (
    <div key={m.id} className="rounded border p-4">
      <div className="text-sm text-gray-500">{m.label}</div>
      <div className="text-2xl">{m.value}</div>
    </div>
  ))}
</div>

The fix is to differentiate by importance. The 1–2 metrics the user actually cares about become bigger. The rest become a row of smaller stats below.

// Differentiated: primary metrics get more visual weight
<div>
  <div className="grid grid-cols-2 gap-4 mb-6">
    {primaryMetrics.map((m) => (
      <div key={m.id} className="rounded-lg bg-white p-6 shadow-sm">
        <div className="text-sm text-gray-500">{m.label}</div>
        <div className="text-4xl font-semibold mt-2">{m.value}</div>
        <div className="text-sm text-gray-600 mt-1">{m.delta}</div>
      </div>
    ))}
  </div>
  <div className="grid grid-cols-4 gap-3">
    {secondaryMetrics.map((m) => (
      <div key={m.id} className="rounded border p-3">
        <div className="text-xs text-gray-500">{m.label}</div>
        <div className="text-lg">{m.value}</div>
      </div>
    ))}
  </div>
</div>

The move that matters is deciding which metrics are primary in the first place. That's a product question, not a styling one. Don't ship a dashboard where every metric is equally important — it almost always means the team hasn't decided.

2. The "every action is a button of the same colour" panel

A Jira-style row of buttons: Save, Cancel, Delete, Archive, Export, Share, Duplicate, Print. All filled, all blue, all the same size. Visual noise that fails the user.

The fix is action hierarchy — one primary action, one or two secondary actions, the rest as tertiary (icons, dropdowns, or hidden behind a menu).

// Action hierarchy in three tiers
<div className="flex items-center gap-2">
  {/* Primary: filled, prominent */}
  <button className="bg-blue-600 text-white px-4 py-2 rounded font-medium">
    Save
  </button>
  {/* Secondary: outlined, less weight */}
  <button className="border px-4 py-2 rounded text-gray-700">
    Cancel
  </button>
  {/* Tertiary: ghost / icon-only / overflow menu */}
  <button className="p-2 text-gray-500 hover:text-gray-700">
    <MoreIcon />
  </button>
</div>

The rule of thumb: one primary action per screen, occasionally two if the user is genuinely making a binary choice (Approve/Reject). More than that, you're hiding the right path.

3. The "30-item sidebar"

A nav with every page the application has, all visible, all the same. The user has to read every label every time they need to navigate.

The fix is the IA work from chapter 3, applied visually:

  • Group with section headers. "Workspace", "Projects", "Settings" — let users skip whole groups they don't need.
  • Collapse low-frequency sections. "Settings" doesn't need 14 child items expanded by default.
  • Use icons for pattern recognition. Users learn the shape of an icon faster than they read a label.
  • Show the active state clearly. Background colour or left border, not subtle text-weight changes.

GitHub's repo sidebar and Linear's project sidebar both apply these. The result: even with 20+ navigable items, the user can scan to the right one in milliseconds.


Tailwind hierarchy in code

A few classes carry most of the weight when building hierarchy in Tailwind. Worth memorizing the patterns.

Type weight progression

Primary heading:   text-3xl  font-semibold  text-gray-900
Section heading:   text-xl   font-semibold  text-gray-900
Body text:         text-base font-normal    text-gray-700
Secondary text:    text-sm   font-normal    text-gray-500
Disabled / hint:   text-xs   font-normal    text-gray-400

Notice how both size and colour shift together. A "secondary" piece of text is smaller AND lighter — both signals reinforcing that it's secondary. This is what makes hierarchy feel intentional rather than accidental.

Card weight progression

Primary card:    bg-white  shadow-md  rounded-lg  p-6  (with prominent content)
Secondary card:  bg-white  border     rounded-lg  p-4
Tertiary item:   bg-gray-50            rounded     p-3

The pattern: more important = more elevation (shadow, larger radius, more padding). Less important = flatter, lighter, tighter.

Button hierarchy

// Primary
className="bg-blue-600 text-white px-4 py-2 rounded font-medium hover:bg-blue-700"
 
// Secondary
className="border border-gray-300 text-gray-700 px-4 py-2 rounded font-medium hover:bg-gray-50"
 
// Tertiary (ghost)
className="text-gray-600 px-3 py-2 rounded font-medium hover:bg-gray-100"

Three levels is the max; using more starts to confuse rather than clarify.


The squint test

The single most useful diagnostic for whether a screen has hierarchy:

Squint at the screen until the text becomes illegible. Can you still tell what the most important thing is?

If yes — what you see is large blobs of contrast and subtle blobs of low-contrast — your hierarchy is working. The user's brain does the same compression even when they're reading carefully; the squint test just makes it visible.

If everything looks like a uniform grey haze when you squint, your screen has no hierarchy. Pick something to be the main element. Make it bigger, bolder, or more prominent until the squint test passes.


Real-world example: Linear vs typical Jira

Linear and Jira ship the same product — issue tracking — and the visual hierarchy comparison is one of the clearest in modern product UI.

Linear's issue view:

  • One large title at the top.
  • One primary action ("Edit" or status change) prominent.
  • Metadata (assignee, labels, due date) clustered as small text on the right.
  • Comments below in a clear vertical rhythm.
  • Sidebar minimal: 5–7 items, grouped.

Typical Jira issue view:

  • Title competing with breadcrumbs, status badges, project labels, three different action buttons, all top-of-screen.
  • 14 metadata fields visible by default.
  • Comments alongside attachments alongside activity log.
  • Sidebar: dozens of items, often expanded by default.

Both products solve the same problem. One feels usable; the other feels like work. The difference is hierarchy.

Going deeper. Most internal tools default to Jira-style layouts because the team builds them by adding features over time without ever pruning. Hierarchy work is destructive — it requires deciding what is less important and visually demoting it. That's politically harder than adding more, which is why most internal tools end up cluttered. Build the prune step into your design review.


A hierarchy checklist for dashboards

Run any dashboard or admin panel through these:

  1. Can you state the one most important metric/action on the screen in one sentence? If not, the screen doesn't have a primary task.
  2. Does the squint test pass? Fuzzy-out the text — is the most important element still visible?
  3. Is there exactly one primary action? Two only if the user is making a binary choice. Otherwise, demote.
  4. Are sidebar items grouped, with rarely-used groups collapsed?
  5. Do typography size and colour shift together? A "secondary" element should be both smaller and lower-contrast.
  6. Is the active nav state clearly visible? A subtle font-weight change is not enough.
  7. Is whitespace doing work? Cramped spacing flattens hierarchy; generous spacing reinforces it.

What you should walk away with

  • Hierarchy is the property that makes a screen scannable in 3 seconds. Without it, every glance is a re-read.
  • Five tools — size, weight, colour, position, whitespace — build hierarchy. Use the minimum that works; don't stack all five.
  • The three breaking patterns are flatness, equal-weight actions, and undifferentiated nav. Most internal tools fail at least one.
  • The squint test is the cheapest diagnostic in UX. Use it on every dashboard you ship.

In chapter 5 we go deeper into the typographic and spacing systems that make hierarchy feel intentional — the developer's survival kit for shipping UI without a designer holding your hand.


Next up — Chapter 5: Typography and Spacing — A Developer's Survival Kit. Type scales, line heights, line lengths, and the 4px grid that quietly powers most well-designed products in 2026.