Skip to the content

Kongens Nytorv

Metro M1, M2 and M3.

Variants and states

RestDisabled
Default
Default
  • Rest
  • Disabled

Props

NameTypeDefaultDescription
orientation'horizontal' | 'vertical''vertical'Which way the bar runs, and so which arrow keys move through it: Up and Down for vertical, the map's column at the bottom right; Left and Right for horizontal.
disabledbooleanfalseWhether every button is disabled, such as while the map loads. The buttons stay focusable and in the arrow-key order.
zoomInDisabledbooleanfalseWhether the zoom in button is disabled, at the map's closest zoom. It stays focusable and announces that it is dimmed, and a click fires no onZoomIn.
zoomOutDisabledbooleanfalseWhether the zoom out button is disabled, at the map's farthest zoom. It stays focusable and announces that it is dimmed, and a click fires no onZoomOut.
centerMapDisabledbooleanfalseWhether the centre button is disabled, such as before the map can be moved, while the pause button stays enabled. It stays focusable and announces that it is dimmed, and a click fires no onCenterMap.
onZoomIn(event: MouseEvent<HTMLButtonElement, MouseEvent>) => void—Called when the zoom in button is pressed, by click, Enter or Space, with the click event. The screen zooms the map in by one step.
onZoomOut(event: MouseEvent<HTMLButtonElement, MouseEvent>) => void—Called when the zoom out button is pressed, by click, Enter or Space, with the click event. The screen zooms the map out by one step.
onCenterMap(event: MouseEvent<HTMLButtonElement, MouseEvent>) => void—Called when the centre button is pressed, by click, Enter or Space, with the click event. The screen moves and zooms the map to show the whole network.
pausedbooleanfalseWhether the map's motion is paused, held by the screen. The pause button shows the play icon and is named "Resume" while it is true, and the pause icon and "Pause" while it is false.
onPausedChange(event: React.MouseEvent<HTMLButtonElement>, paused: boolean) => void—Called when the pause button is pressed, by click, Enter or Space, with the click event and the state the press asks for: true while the map moves, false while it is paused. Given, it adds the pause button after the centre button; the screen stops or starts the map's motion and passes the new paused.
tiltedbooleanfalseWhether the map is tilted into 3D, held by the screen, by the 3D toggle or a gesture alike. The 3D toggle is pressed, aria-pressed="true" on its on fill, while it is true.
onTiltedChange(event: React.MouseEvent<HTMLButtonElement>, tilted: boolean) => void—Called when the 3D toggle is pressed, by click, Enter or Space, with the click event and the state the press asks for: true while the map is flat, false while it is tilted. Given, it adds the 3D toggle after the centre button; the screen tilts the map or lays it flat and passes the new tilted.
headingnumber0The map's heading in degrees, its bearing clockwise from north, held by the screen. The compass's needle turns by minus heading, so it points to north on the map, and the compass is described as turned away from north while it is turned; a value that isn't finite points it up.
onResetNorth(event: MouseEvent<HTMLButtonElement, MouseEvent>) => void—Called when the compass is pressed, by click, Enter or Space, with the click event. Given, it adds the compass after the centre button, and after the 3D toggle when there is one; the screen turns the map back to north and passes the new heading.
mapControlsLabelstringThe locale'sOverrides "Map controls", the bar's name.
zoomInLabelstringThe locale'sOverrides "Zoom in", the zoom in button's name.
zoomOutLabelstringThe locale'sOverrides "Zoom out", the zoom out button's name.
centerMapLabelstringThe locale'sOverrides "Centre the map", the centre button's name.
pauseLabelstringThe locale'sOverrides "Pause", the pause button's name while the map moves.
resumeLabelstringThe locale'sOverrides "Resume", the pause button's name while the map is paused.
view3dLabelstringThe locale'sOverrides "3D view", the 3D toggle's name.
resetNorthLabelstringThe locale'sOverrides "Reset to north", the compass's name.
turnedFromNorthLabelstringThe locale'sOverrides "Map turned away from north", the compass's description while the map is turned.
classNamestring—Reaches the root, the role="toolbar" element. className is merged after pn-Toolbar and pn-MapControls.
styleCSSProperties—Reaches the root, the role="toolbar" element. className is merged after pn-Toolbar and pn-MapControls.
refRef<HTMLDivElement>—Reaches the root, the role="toolbar" element. className is merged after pn-Toolbar and pn-MapControls.
orientation'horizontal' | 'vertical', default 'vertical'
Which way the bar runs, and so which arrow keys move through it: Up and Down for vertical, the map's column at the bottom right; Left and Right for horizontal.
disabledboolean, default false
Whether every button is disabled, such as while the map loads. The buttons stay focusable and in the arrow-key order.
zoomInDisabledboolean, default false
Whether the zoom in button is disabled, at the map's closest zoom. It stays focusable and announces that it is dimmed, and a click fires no onZoomIn.
zoomOutDisabledboolean, default false
Whether the zoom out button is disabled, at the map's farthest zoom. It stays focusable and announces that it is dimmed, and a click fires no onZoomOut.
centerMapDisabledboolean, default false
Whether the centre button is disabled, such as before the map can be moved, while the pause button stays enabled. It stays focusable and announces that it is dimmed, and a click fires no onCenterMap.
onZoomIn(event: MouseEvent<HTMLButtonElement, MouseEvent>) => void, default —
Called when the zoom in button is pressed, by click, Enter or Space, with the click event. The screen zooms the map in by one step.
onZoomOut(event: MouseEvent<HTMLButtonElement, MouseEvent>) => void, default —
Called when the zoom out button is pressed, by click, Enter or Space, with the click event. The screen zooms the map out by one step.
onCenterMap(event: MouseEvent<HTMLButtonElement, MouseEvent>) => void, default —
Called when the centre button is pressed, by click, Enter or Space, with the click event. The screen moves and zooms the map to show the whole network.
pausedboolean, default false
Whether the map's motion is paused, held by the screen. The pause button shows the play icon and is named "Resume" while it is true, and the pause icon and "Pause" while it is false.
onPausedChange(event: React.MouseEvent<HTMLButtonElement>, paused: boolean) => void, default —
Called when the pause button is pressed, by click, Enter or Space, with the click event and the state the press asks for: true while the map moves, false while it is paused. Given, it adds the pause button after the centre button; the screen stops or starts the map's motion and passes the new paused.
tiltedboolean, default false
Whether the map is tilted into 3D, held by the screen, by the 3D toggle or a gesture alike. The 3D toggle is pressed, aria-pressed="true" on its on fill, while it is true.
onTiltedChange(event: React.MouseEvent<HTMLButtonElement>, tilted: boolean) => void, default —
Called when the 3D toggle is pressed, by click, Enter or Space, with the click event and the state the press asks for: true while the map is flat, false while it is tilted. Given, it adds the 3D toggle after the centre button; the screen tilts the map or lays it flat and passes the new tilted.
headingnumber, default 0
The map's heading in degrees, its bearing clockwise from north, held by the screen. The compass's needle turns by minus heading, so it points to north on the map, and the compass is described as turned away from north while it is turned; a value that isn't finite points it up.
onResetNorth(event: MouseEvent<HTMLButtonElement, MouseEvent>) => void, default —
Called when the compass is pressed, by click, Enter or Space, with the click event. Given, it adds the compass after the centre button, and after the 3D toggle when there is one; the screen turns the map back to north and passes the new heading.
mapControlsLabelstring, default The locale's
Overrides "Map controls", the bar's name.
zoomInLabelstring, default The locale's
Overrides "Zoom in", the zoom in button's name.
zoomOutLabelstring, default The locale's
Overrides "Zoom out", the zoom out button's name.
centerMapLabelstring, default The locale's
Overrides "Centre the map", the centre button's name.
pauseLabelstring, default The locale's
Overrides "Pause", the pause button's name while the map moves.
resumeLabelstring, default The locale's
Overrides "Resume", the pause button's name while the map is paused.
view3dLabelstring, default The locale's
Overrides "3D view", the 3D toggle's name.
resetNorthLabelstring, default The locale's
Overrides "Reset to north", the compass's name.
turnedFromNorthLabelstring, default The locale's
Overrides "Map turned away from north", the compass's description while the map is turned.
classNamestring, default —
Reaches the root, the role="toolbar" element. className is merged after pn-Toolbar and pn-MapControls.
styleCSSProperties, default —
Reaches the root, the role="toolbar" element. className is merged after pn-Toolbar and pn-MapControls.
refRef<HTMLDivElement>, default —
Reaches the root, the role="toolbar" element. className is merged after pn-Toolbar and pn-MapControls.

Use it

import { MapControls } from '@mylder/perron'

Ask your agent

search_docs({ query: "MapControls" })

Keyboard and ARIA

From the Base UI reference for Toolbar.Root, Toolbar.Button and Toolbar.Separator, as the Toolbar spec gives them. "From" says who does it.

KeyDoesFrom
Tab, Shift+TabMoves focus into the bar, to the button that last had it (zoom in at first), and out again: the bar is one tab stopBase UI
ArrowDown, ArrowUpIn the vertical bar, the default, move focus to the next and the previous button, skipping the separators, wrapping while loopFocus is on: zoom in, zoom out, centre, then the 3D toggle, the compass and pause, each when it is thereBase UI
ArrowRight, ArrowLeftIn a horizontal bar, move focus to the next and the previous button, in the same order, wrapping while loopFocus is onBase UI
Enter, SpacePress the focused button: call its onZoomIn, onZoomOut, onCenterMap or onResetNorth, or onTiltedChange or onPausedChange with the state it asks for, unless it is disabled; focus stays on the button as the toggle's aria-pressed, the compass's needle or the pause button's icon and name changeThe browser

Home and End do nothing, as on Toolbar. + and − zoom the map from the map canvas (Accessibility), not from these controls.

MapControls listens to no keys of its own and sets no aria-keyshortcuts, leaving + and − to the map. Accessibility gives those keys to the screen ("+ and − zoom, arrow keys pan"), the map canvas has focus when they are pressed, and the controls can't know that the screen binds them, so announcing a shortcut could promise one that does nothing.

ElementRoleAccessible name fromStates announced
roottoolbar, from Base UIaria-label, the mapControls owned string, or the caller's aria-labelledbyaria-orientation
zoomInbutton, nativearia-label, the zoomIn owned stringaria-disabled when zoomInDisabled or disabled
zoomOutbutton, nativearia-label, the zoomOut owned stringaria-disabled when zoomOutDisabled or disabled
centerMapbutton, nativearia-label, the centerMap owned stringaria-disabled when centerMapDisabled or disabled
tiltbutton, native, a toggle button by its aria-pressedaria-label, the view3d owned string, the same while tilted and flataria-pressed, true while tilted and false while not; aria-disabled when disabled
compassbutton, nativearia-label, the resetNorth owned string, at every headingIts description, the turnedFromNorth owned string in turned, through aria-describedby, while the map is turned; aria-disabled when disabled; no aria-pressed
pausebutton, nativearia-label, the pause owned string while the map moves, resume while pausedaria-disabled when disabled; no aria-pressed
separator, angleSeparator, pauseSeparatorseparator, from Base UInonearia-orientation, across the bar's
iconnone: inside aria-hiddennonenone
turnednone: text out of sight, the compass's descriptionnonenone

The pause button swaps its name, "Pause" or "Resume", and sets no aria-pressed. The APG's button pattern gives a two-state button one of two forms: a toggle whose label stays the same while aria-pressed says its state, such as "Mute", pressed or not; or a button whose label changes with the state, such as Play and Pause, which then has no aria-pressed, since "Pause, pressed" says the opposite of what it means. The icon swaps between pause and play, each naming the action a press takes, and the contract asks that everything the eye is told the ear is told, so the name swaps with the icon: a fixed "Pause" with aria-pressed would be heard as "Pause, pressed" while the eye sees play. The name says what the press does, as zoom in and zoom out do, and it is the name Mylder's map already gives the button. A screen reader may not announce the new name on the press itself; the vehicles stopping or moving is the press's feedback, and the name is read the next time focus reaches the button.

The 3D toggle takes the APG's other form: its name, "3D view", stays the same while aria-pressed says whether the map is tilted, heard as "3D view, toggle button, pressed" or "not pressed". Its icon, the cube, stays the same too, and its on fill is what the eye is told. The state is the map's, which a gesture changes as well as a press, so it is a state to announce rather than an action to name, as "Pause" is: a name that swapped, "Tilt the map" and "Lay the map flat", would leave the ear without the map's state once a gesture had tilted it. aria-pressed follows tilted, so a gesture the screen passes on is heard the next time focus reaches the toggle.

The compass's name says what a press does, "Reset to north", at every heading, as the zoom and centre buttons name theirs, and it sets no aria-pressed: the press is an action, not a state.

The compass tells the ear what its needle tells the eye: whether the map is turned away from north. While the needle is drawn turned, a finite heading that isn't a whole turn from north, the compass is described by the turnedFromNorth owned string, "Map turned away from north", through aria-describedby pointing at a VisuallyHidden span after it, the contract's part for words the eye gets from an icon, heard after its name as "Reset to north, button, Map turned away from north"; at north, and for a heading that isn't finite, which draws the needle unturned, the span and the aria-describedby are gone. aria-describedby is ARIA 1.0, which every screen reader reads, where ARIA 1.3's aria-description is not yet read evenly. The description changes only between north and turned, never at each degree, so a turn the screen passes frame by frame doesn't change what is heard until the map reaches north, where a screen reader would repeat or drop a number that changed at every frame; the name stays "Reset to north", what a press does, at every heading. The exact angle stays the map's to describe, as the zoom is: the needle's angle tells the eye no number either, only which way north lies, and the ear learns that north is not up.

What axe won't catch, from the contract, each with how this component meets it:

  • Everything the eye is told, the ear is told, for every shape each prop accepts: each icon is aria-hidden inside its button, and the button's aria-label says the action it shows ("Zoom in", "Zoom out", "Centre the map", "Reset to north", and "Pause" or "Resume" as the pause or play icon shows), or, for the 3D toggle, the view it turns on, "3D view"; the toggle's on fill is its aria-pressed; the compass's turned needle is its description, "Map turned away from north", through aria-describedby and VisuallyHidden, while heading turns it, and none at north, as the paragraph above says; a dimmed button is announced through aria-disabled; the separators are announced as such.
  • Every landmark and named region has an accessible name: the bar is a toolbar named "Map controls" by its owned string, so it tells itself apart from the top bar's toolbars.
  • Every default label can be overridden: mapControlsLabel, zoomInLabel, zoomOutLabel, centerMapLabel, view3dLabel, resetNorthLabel, turnedFromNorthLabel, pauseLabel and resumeLabel.
  • Every shape the type accepts renders, in every variant: the props take no ReactNode; both orientations, every …Disabled combination and disabled render all three buttons, square, in the same order, and the 3D toggle in either state of tilted, the compass at any heading, 0, negative, past 360 or not finite, and the pause button in either state of paused after them when their handlers are given.
  • A hidden copy kept for animation is aria-hidden, and a collapsed region is inert: none here; the controls keep no hidden copy and collapse nothing.
  • Native semantics first: native <button>s from Toolbar.Button, Base UI's toolbar and separator roles, with ARIA only for the names an icon can't give.
  • Focus moves in reading order and returns on close: the arrow keys move zoom in, zoom out, centre, then the 3D toggle, the compass and pause, in document order; the controls open nothing; a button that hits a zoom limit stays focusable, the 3D toggle stays the same element as tilted changes, the compass stays in the bar at north, and the pause button stays the same element as its icon and name swap, so focus never jumps away from the key a person pressed.
  • Every target is at least size.target-min square: each button is size.control (34 px) square.
  • Loops stop when the system asks for less motion: none here; the controls have no loop and no transition, and the compass's needle jumps to each heading it is given, so the motion is the screen's own turn of the map, which reads the motion tokens' reduced values (CR-12).

Owned strings

Every word MapControls announces is its own; it shows none. No key in packages/perron/src/locale/en.ts said any of these, so all nine are new, each added when its button joined, each with a JSDoc line like its neighbours, and agents write the Danish, Swedish and Norwegian.

The four new keys are mapControls "Map controls", zoomIn "Zoom in", zoomOut "Zoom out" and centerMap "Centre the map", overridden by mapControlsLabel, zoomInLabel, zoomOutLabel and centerMapLabel. They are the words the Toolbar spec's map stories and the IconButton spec's examples already use, packages/perron/icons/icons.json gives locate the use "Centre the map on the network", each names the action as a verb and what it acts on, in sentence case (Content design), and the keys take the American spelling of code names.

The pause button's two keys joined later: pause "Pause" and resume "Resume", overridden by pauseLabel and resumeLabel. They are the names Mylder's map gives the button in English, and in Danish, "Pause" and "Fortsæt", from its dictionary; the Swedish, "Pausa" and "Fortsätt", and the Norwegian, "Pause" and "Fortsett", were written for Perron, since Mylder has no Swedish or Norwegian. Each is the verb of the press, and packages/perron/icons/icons.json gives pause and play the uses "Stop the vehicles moving on the map" and "Set the vehicles moving again". "Resume" rather than "Play": the map isn't media, and the press resumes the motion the reader paused.

The 3D toggle's and the compass's two keys joined with them, for perron#186, whose changeset names them: view3d and resetNorth, overridden by view3dLabel and resetNorthLabel. Agents write the Danish, Swedish and Norwegian, since Mylder's dictionary has neither yet.

The compass's English, "Reset to north", is the issue's: the verb of the press and where it turns the map, in sentence case, as packages/perron/icons/icons.json gives compass the use "turn the map back to it". The key is resetNorth, the action as the other buttons' keys are.

The compass's description is the key turnedFromNorth, "Map turned away from north", overridden by turnedFromNorthLabel, which joined when the review held the compass to the contract's "everything the eye is told, the ear is told": a statement of the map's state, as the needle shows it, rather than an action, since the name already says the press. Agents write the Danish, Swedish and Norwegian: "Kortet er drejet væk fra nord", "Kartan är roterad bort från norr" and "Kartet er dreid bort fra nord".

The 3D toggle's name is the key view3d, "3D view", overridden by view3dLabel. A toggle's name stays the same while aria-pressed says its state (see Keyboard and ARIA), so it names what the press turns on rather than the press itself: "3D view, pressed" says the map is in 3D, where a verb, "Tilt the map, pressed", reads as a step already taken. "3D" is what the issue and the cube icon's use call the view, and is written alike in all four locales; the key puts the noun first, as mapControls does, since a key can't start with a digit.

KeyEnglishOverrideSeen or heard where
mapControls"Map controls"mapControlsLabelroot, heard as the toolbar's name through aria-label
zoomIn"Zoom in"zoomInLabelzoomIn, heard as the button's name through aria-label
zoomOut"Zoom out"zoomOutLabelzoomOut, heard as the button's name through aria-label
centerMap"Centre the map"centerMapLabelcenterMap, heard as the button's name through aria-label
view3d"3D view"view3dLabeltilt, heard as the toggle's name through aria-label, then "pressed" or "not pressed"
resetNorth"Reset to north"resetNorthLabelcompass, heard as the button's name through aria-label, at every heading
turnedFromNorth"Map turned away from north"turnedFromNorthLabelcompass, heard as its description through aria-describedby while the map is turned
pause"Pause"pauseLabelpause, heard as the button's name through aria-label while paused is false
resume"Resume"resumeLabelpause, heard as the button's name through aria-label while paused is true

Do and don't

For a caller using the component, with the reason. Each row is a rule: a must row's Don't is never right, a should row's needs a reason, and Checked by says what catches the Don't in a caller's code.

RuleLevelDoDon'tChecked by
DD-1shouldUse MapControls for the map's zoom and centre buttons, once per mapBuild the same bar from IconButtons or from your own Toolbar: an IconButton in a toolbar adds a tab stop, and a second copy drifts from this onereview
DD-2shouldPlace it from the screen, at the bottom right, size.panel-gap from the edges, at z-index.map-controlsExpect MapControls to position itself, or give it a z-index through the component: it sizes to its content and the screen places itreview
DD-3mustSet zoomInDisabled or zoomOutDisabled when the map reaches a zoom limitHide or unmount a button at a limit: focus on it is lost and the bar changes shape under the pointerreview
DD-4mustCentre the map on the whole network in onCenterMap, as its words promiseWire it to the reader's own location: its words, "Centre the map", and the locate icon's use promise the networkreview
DD-5mustRename the bar or a button with its …Label prop, such as zoomInLabelPass aria-label to the root: the bar's own name is set after it and replaces itreview
DD-6mustBind + and − on the map canvas, where Accessibility puts themExpect MapControls to listen for keys: it adds none beyond the toolbar's arrowsreview
DD-7shouldGive onPausedChange and paused to add the pause button, and set paused from the handlerPut the pause in a Toolbar of its own beside MapControls: it is the map's own control, and a bar of its own adds a second bar and a second tab stopreview
DD-8mustPut another map action, such as a layers switch, in a Toolbar of its own beside itWrap MapControls to add buttons inside it: it takes no children, so its buttons stay the same on every screen; only the map's own controls, the 3D toggle, the compass and the pause, join the bartypes
DD-9mustGive onTiltedChange and tilted to add the 3D toggle, and set tilted from the map's own tilt, whether the rider tilted it with the toggle or a gestureSet tilted only in the handler: a gesture that tilts the map then leaves the toggle off, and the ear hears "not pressed" over a tilted mapreview
DD-10mustGive onResetNorth and heading to add the compass, pass the map's bearing in degrees clockwise from north at each frame of a turn, and turn the map back to north in the handler, with the motion tokens' reduced values when the system asks for less motionPass the needle's own angle, a counter-clockwise or radian value, or only the heading the turn ends at: the needle turns by minus heading and jumps to each value it is givenreview
DD-11shouldKeep the compass in the bar at northUnmount the compass or drop onResetNorth while the map faces north: the pause button moves under the pointer and the rider can't find the compass when the map is first turnedreview