Skip to content
Foundations

Iconography

One vocabulary, one grid, owned end to end. Line art on 24×24, 2px stroke, round caps and joins, drawn in currentColor — planning atoms, interface chrome and the GIS workbench alike. There is no second icon library and no third-party icon package.

The family

searchclosecheckmenuchevron-downchevron-upchevron-leftchevron-rightexternalinfoplusminusplus-circlecircle-dashedloaderwrenchcheck-circlewarningstarbookmarkexportdownloadsavehouseflaskideacursor-clicktrend-uppincrosshairglobepulseeyefoldertablegriparrows-outfunneltogglehashquotesbracessigmaimagefoundationsblocksmapsetback-frontsetback-rearsetback-sidesetback-secondaryboundary-wallbuild-towaterwayheight-mheight-storeysplanesite-coverplot-ratiogfa-capbuilding-lengthseparationpodiumdensity-maxdensity-mindwellings-maxlot-areafrontagerectangleposbalconycommunallandscapedeep-plantingsolarprivacyacousticparkingparking-visitorbicycledrivewayrear-lanewastegaragearticulationroofentryfenestrationmaterialsfenceactive-frontagestreet-treefloodbushfireearthworksimpervioustree-retentionceilingroomdwelling-arealightstairdoorcar-spacefire-separationaiunknownlayersdatabasedriveshistorytoolboxflow-arrowchart-barbinocularsrulercubecompasspolygonline-stringline-segmentpathgrid-fourseal-checkbarricadebuildingscircles-threecircles-three-plusheatmappaletteswatches
Every name in the registry — 131 of them, in the order icons.ts declares them (interface, then the planning atoms: siting, bulk, lot and density, amenity, movement, character, hazard, building code, AI, fallback). d takes a single path on the same grid for a genuine one-off; the default slot takes anything more complex — circles, multiple strokes.
Code
<GdIcon name="search" />
<GdIcon name="flood" :size="20" />
<GdIcon name="setback-front" :size="24" :stroke="1.8" />

<!-- a one-off, and the escape hatch for a multi-part glyph -->
<GdIcon d="M12 5v14M5 12h14" :size="16" />
<GdIcon :size="20"><circle cx="11" cy="11" r="7" /><path d="M21 21l-4.3-4.3" /></GdIcon>

Sets that carry meaning

Two small sets ship as their own exports rather than as registry names, because each entry is more than a glyph: it carries the word for the thing, the order it belongs in, and the tone it must be drawn with. A registry name would give you the picture and lose all three.

Approvals — @gridd/ui/approvals

Building approvalCouncil approvalPublic noticeState approvalNo approval needed
Code
import { APPROVAL_ICONS } from "@gridd/ui/approvals"

<GdIcon :d="APPROVAL_ICONS.council.d" :size="22" />

Status — @gridd/ui/status

SuccessInformationCautionError
The glyph takes its colour from the filled tile it sits in, never from the path. Stroke 2.6 here: a small tick inside a fill needs the extra weight.
Code
import { STATUS } from "@gridd/ui/status"

<GdTile tone="success" :size="40">
  <GdIcon :d="STATUS.success.d" :size="20" :stroke="2.6" />
</GdTile>

Rules

  • Reach for name first. Use d only for a glyph used once, and the default slot only when one path cannot draw it.
  • Add a glyph to the registry if it is used in more than one place, or if it carries planning meaning and must look the same in every app.
  • Never install an icon package. Interface chrome, planning atoms and the GIS workbench are all in this one registry, on one grid. A glyph that is missing gets drawn and added here.
  • Use filled only on closed shapes. It paints the glyph solid as well as stroking it — right for star or bookmark as the ON half of a toggle, wrong for anything open like trend-up, which will smear.
  • Never give an icon a colour prop. It inherits currentColor from whatever it sits in.
  • Never colour an approval icon. The stack must read in greyscale; the words beside it carry the verdict.
  • Colour a status glyph by colouring the tile, not the path.
  • Leave label off an icon that sits beside text. It is hidden from assistive tech, which is right — announcing the thing twice is noise.
  • Set label when the icon is the ONLY carrier of meaning. An icon-only control without one is announced as just "button".
  • Go thinner for large glyphs (1.8) and heavier for a small tick inside a fill (2.6). The default 2 is for everything between.

Behavior & Anatomy

Why currentColor and no colour prop

currentColor is the whole design. It is what lets one path serve a neutral tile, an accent link and a filled danger button with no variant and no colour prop — the icon inherits its ink from whatever it sits in, so it can never disagree with the text beside it. An icon that takes a colour prop is an icon that will eventually be the wrong colour.

Why there is a registry at all

d at a call site is path data nobody reviews, so the same glyph drifts between apps one bezier at a time and no reviewer ever notices. Without a registry the pressure is always toward one app growing a private name→glyph table, at which point every other app either imports a component across an app boundary or hand-carries path data.

So the table lives in the design system as DATA rather than as a component. Data crosses the package boundary without dragging a render function with it, and GdIconName makes a typo a typecheck failure instead of an empty box at runtime. The names are one flat namespace on purpose — a caller asking for an icon does not care which layer of the product minted it, and a second namespace would only mean deciding which one to look in.

Why approvals and status ship separately

Their meaning is content, not chrome. What approvals a property needs is carried by the layered approval icons and by words — never by hue — so each of those two modules carries its own path beside the meaning it belongs to, rather than being a name in a general-purpose registry.

Why the approval stack is never coloured

The stack has to read in pure greyscale, because colour is never allowed to be the only carrier of meaning and because a coloured authority icon would be read as a verdict. The words beside the stack carry the verdict; the icons carry who has to say yes.

Navigate

Esc