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
Code
import { APPROVAL_ICONS } from "@gridd/ui/approvals"
<GdIcon :d="APPROVAL_ICONS.council.d" :size="13" /> CouncilScale bar
Code
<GdScaleBar label="20 m" />
<GdScaleBar label="500 m" :width="62" />
<GdScaleBar label="1 km" :width="80" />Search suggestions
- 42 Jarrah StreetMillbrook · Riverton City
- Jarrah CloseHarrowgate · Riverton City
- L14 RP80432812 m² · Millbrook
Lot/plan
Code
<GdSearchSuggest
v-model="query"
:suggestions="results"
:loading="pending"
@select="open"
/>API
GdMapTool
Props
stackbooleanfalseSeveral buttons as one divided unit — zoom in / zoom out, with a hairline between them. Each child is a 38px square holding one glyph.
pillbooleanfalseOne labelled control rather than an icon square: 38px tall, width from its own content, laid out as glyph · label · optional count.
Slots
defaultThe buttons. The GEOMETRY is the component's, not the caller's — the shape prop decides it.
GdScaleBar
Props
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
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.
loadingbooleanfalseThe 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
stackwhen two or more icon buttons belong together as one unit — zoom in and zoom out, nothing else on the map qualifies today. - Use
pillwhen 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
positionat 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
widthfrom 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
dpath. 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.
GdSearchSuggestowns 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.