Skip to content
Foundations

Surfaces & elevation

Seven named levels, each pairing a surface with a shadow.

The levels

Sunkennone

A recessed group — the segmented track, the layers list, an icon tile.

Flatnone

A card at rest. Border only, no shadow — the border is what says where it ends.

Raised--gd-shadow-sm

A segmented control's selected thumb, a raised tile.

Float--gd-shadow-float

Map chrome — a layers pill, a filter pill, a scale bar.

Overlay--gd-shadow-md

Popovers, menus, dropdowns.

Toast--gd-shadow-lg

Toasts.

Modal--gd-shadow-xl

Dialogs. The only level allowed to dim what is behind it.

--gd-elevation-sunkennonea recessed group — segmented track, layer list
--gd-elevation-flatnonea card at rest: border only, no shadow
--gd-elevation-raisedvar(--gd-shadow-sm)a segmented thumb, a raised tile
--gd-elevation-floatvar(--gd-shadow-float)map chrome — lighter than overlay, so tools do not read as modal over the cartography
--gd-elevation-overlayvar(--gd-shadow-md)popovers, menus, dropdowns
--gd-elevation-toastvar(--gd-shadow-lg)toasts
--gd-elevation-modalvar(--gd-shadow-xl)dialogs

Interaction states

Rest — surfaceHovered — surface-hoverPressed — surface-pressedSelected — surface-selected
Code
background: var(--gd-surface);
background: var(--gd-surface-hover);
background: var(--gd-surface-pressed);
background: var(--gd-surface-selected);

Rules

  • Take the pair, never half of it. A card that borrows the overlay shadow without the overlay surface reads as a bug.
  • Use --gd-surface-raised for anything that floats — a pill, a popover, a menu. Not --gd-surface, which is 1.00 against its own ground in the dark.
  • Use sunken for a GROUP of things — a segmented track, a layers list, an icon-tile grid — not for a single item.
  • Use float, not overlay, for map chrome. At overlay weight the tools read as modal over the cartography.
  • Change the SURFACE on hover and pressed, never the shadow. A list row darkens; it does not lift.
  • Never add a shadow to compensate for the dark theme. The dark ladder collapses on purpose; the surface carries the level instead.
  • Do not invent a level. Seven is the whole ladder, and an eighth is a design change.

Behavior & Anatomy

Why elevation is a token PAIR

Each level names a surface and a shadow, and the two are never mixed. In the dark the shadows collapse and the SURFACE carries the level instead by getting lighter as it rises — that fork is why elevation is a pair rather than a shadow token.

The surface that says "lifted off its ground"

--gd-surface-raised is the semantic token for exactly that. Without it a component reaches for --gd-surface and comes out at 1.00 against the surface beneath it — the dark theme's whole elevation mechanism, with nothing to say it with. On a light ground a black shadow does the entire job, so the token is a no-op there; on a dark ground --gd-shadow-md is rgba(0,0,0,.45), which over near-black is very nearly nothing.

The step is chosen against the light theme's own precedent: a white pill on the page tint is 1.101, and #1D1F26 on #17181E is 1.076 — the same relationship, not a new one.

Why map chrome gets its own level

float is lighter than overlay on purpose: a control floating over a busy cartographic ground needs to separate from it without casting the deep shadow a popover uses. At overlay weight the tools read as modal over the cartography, which is the opposite of what a map tool is.

Why sunken is the one people get wrong

A GROUP of things is recessed, not raised — the layers list and the segmented track sit below the surface, so the panel stays the highest thing on the map. The instinct is to lift the group to show it is a group; lifting it puts it above the panel that contains it.

Why hover and pressed are surface changes

Hover and pressed are SURFACE changes, not shadow changes. A list row darkens; it does not lift. That keeps rows quiet in a long list and stops the panel shimmering as the pointer crosses it.

Navigate

Esc