Skip to content
Components

Map tools & search

The floating chrome over the map — tool tiles, the scale bar and the omnisearch that tells a suburb from an address from a lot/plan.

Map tools

Code
<GdMapTool stack>
  <button type="button" aria-label="Zoom in">…</button>
  <button type="button" aria-label="Zoom out">…</button>
</GdMapTool>

<GdMapTool>
  <button type="button" aria-label="Locate me">…</button>
</GdMapTool>

<GdMapTool pill>
  <button type="button">
    <GdIcon :size="16" :stroke="1.9">…</GdIcon>
    <span>Layers</span>
    <GdCode tinted>3 on</GdCode>
  </button>
</GdMapTool>

Approval legend

NoneBuildingCouncilNotice
Assembled on the page from APPROVAL_ICONS — the same icons the approval stack uses, never coloured, words beside them. There is no legend component; the icons are the shared part.
Code
import { APPROVAL_ICONS } from "@gridd/ui/approvals"

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

Scale bar

20 m
500 m
1 km
Code
<GdScaleBar label="20 m" />
<GdScaleBar label="500 m" :width="62" />
<GdScaleBar label="1 km" :width="80" />

API

GdMapTool

Props

PropTypeDefault
stackbooleanfalse

Several buttons as one divided unit — zoom in / zoom out, with a hairline between them. Each child is a 38px square holding one glyph.

pillbooleanfalse

One labelled control rather than an icon square: 38px tall, width from its own content, laid out as glyph · label · optional count.

Slots

default

The buttons. The GEOMETRY is the component's, not the caller's — the shape prop decides it.

GdScaleBar

Props

PropTypeDefault
labelrequiredstring—

The distance the rule represents — "20 m", "500 m", "1 km". Set in mono.

widthnumber—

The rule's drawn length in px, as the map computes it. No declared default; omitted, the rule falls back to 44px.

GdSearchSuggest

Props

PropTypeDefault
modelValuestring""

`v-model` on the query. Escape clears it.

suggestionsrequiredGdSuggestion[]—

The results: `{ id, name, sub?, d?, tag? }`. `d` is a 24×24 path for the KIND of thing this is; `tag` is a mono tag on the right. Filtering is the CALLER's — a map search hits a geocoder, not an array.

placeholderstring"Suburb, address, lot/plan or city"

The field's placeholder. The default names the four kinds the component distinguishes.

headingstring"Suggestions"

The group label above the list.

loadingbooleanfalse

The results are still coming.

Events

select[item: GdSuggestion]

The chosen result — from Enter on the active option or a click. The component does not navigate; the caller decides what opening one means.

Usage Guidelines

  • Use stack when two or more icon buttons belong together as one unit — zoom in and zoom out, nothing else on the map qualifies today.
  • Use pill when the control needs a word. The layers button is the case: "Layers · 3 on" cannot survive as a glyph.
  • Use the bare tool for a single icon control, such as locate.
  • Position the tool from the map, never from inside it. The component sets no position at all — the page that owns the corners places it.
  • Use GdScaleBar, not a map tool, for anything that reads the map. Controls float; readings sit flat.
  • Pass width from the map's own computation. A scale bar whose rule does not match its label is worse than no scale bar.
  • Give every suggestion a d path. The glyph is the component's whole reason for existing over a plain list — a suburb, an address and a lot/plan are easy to confuse when typed.
  • Filter in the caller. GdSearchSuggest owns presentation and the keyboard and emits what was chosen; it never decides what matches.

Behavior & Anatomy

One component for the chrome

The white tile at overlay elevation is one component because the CHROME is what is shared — the elevation, the 38px module, the hairline between stacked buttons — and the contents are not. The tool never positions itself: controls must not fight for the same corner, and only the map knows which corners are free. The geometry is the component's too. An earlier cut forced 38×38 on every child, and the labelled layers button had to fight it with !important at the call site — which is the signal that the component's API was wrong, not the page's CSS.

Four tools, and that is the whole set

Zoom, locate, the layers pill and the approval legend. The layers glyph is the one coloured icon on the map, because it is the only control that changes what the map is showing; its count is a mono chip, not a badge, because "3 on" is a machine fact about layers rather than a notification. The legend uses the same icons the approval stack uses — never coloured, words beside them — so the map's key and the panel's verdict are visibly one system.

Why the scale bar is not a tool

A scale bar reads the map rather than controlling it, so it wears the plain bordered chip and casts no shadow. The distance is mono, because it is a machine fact.

Why every result carries a glyph

A suburb, an address and a lot/plan are easy to confuse when typed — and a lot/plan is tagged in mono so it reads as the identifier it is. That distinction is the component's whole reason for existing over a plain list.

The input keeps focus while arrows move aria-activedescendant through the options — the combobox pattern, so a screen reader announces each result without focus leaving the field. Filtering is the caller's: a map search hits a geocoder, not an array.

Navigate

Esc