Map Marker Place
- Stable
- WCAG 2.2 evidence
- RTL
A place (an office, a site, a building) on a map:
a brand-coloured rounded pin with a building icon, an optional headcount pill and a pointer. Selected, it grows, gets a halo and
shows the name. The map is not part of the library: position the marker yourself with translate(-50%, -100%) so the pointer
tip sits on the coordinates. It is plain (an image named "Lahore HQ, 24 people") unless you give it onPress (a button) or href (a link). Interactive
markers are React Aria buttons and links: Enter and Space press, keyboard focus draws the focus ring around the pin, hover is
data-hovered (WCAG 2.1.1, 2.4.7, 4.1.2). The selected marker has aria-current. That it is a place is given by the building
icon and the name, and the headcount by text: colour never carries information alone (1.4.1). Consumer duties: use MapMarkerPerson for people; keep neighbouring markers 24 px apart or large enough (2.5.8).
import { MapMarkerPlace } from "@nexera-ui/react";- 9
- examples
- 13
- props
- 2
- live controls
- 1
- platform
- 8
- WCAG criteria
- 3
- blocks use it
Try every prop. Copy the code.
Change the props and the code updates. Check light and dark, LTR and RTL, and phone width.
import { MapMarkerPlace } from "@nexera-ui/react";
<MapMarkerPlace />Examples 8
The same examples as Storybook, rendered live. Open Code to copy one.
Without headcount
Show headcount off: the pill is shown only when a headcount is given.
import { MapMarkerPlace } from "@nexera-ui/react";
export function WithoutHeadcount() {
return (
<div className="flex items-end gap-8">
<MapMarkerPlace name="Lahore HQ" />
<MapMarkerPlace name="Lahore HQ" isSelected />
</div>
);
}
Selectable
A button that selects the place; the selected marker has a halo, a larger pin and its name, and aria-current.
import { useState } from "react";
import { MapMarkerPlace } from "@nexera-ui/react";
export function Selectable() {
function Sites() {
const [selected, setSelected] = useState("lhr");
const sites = [
{ id: "lhr", name: "Lahore HQ", headcount: 24 },
{ id: "khi", name: "Karachi office", headcount: 11 },
{ id: "isb", name: "Islamabad site", headcount: 6 },
];
return (
<div className="flex flex-wrap items-end gap-10">
{sites.map((site) => (
<MapMarkerPlace
key={site.id}
name={site.name}
headcount={site.headcount}
isSelected={selected === site.id}
onPress={() => {
setSelected(site.id);
}}
/>
))}
</div>
);
}
return <Sites />;
}
As link
A link to the place's page.
import { MapMarkerPlace } from "@nexera-ui/react";
<MapMarkerPlace name="Lahore HQ" headcount="24" href="#lahore-hq" />;
Long name
A long name wraps inside the selected marker's label (up to 150 px wide) instead of stretching the marker.
import { MapMarkerPlace } from "@nexera-ui/react";
<MapMarkerPlace
name="Karachi Regional Distribution and Fulfilment Centre"
headcount="24"
isSelected
/>;
Long headcount
Large headcounts are never truncated: the pill grows. Abbreviate them yourself where space is tight.
import { MapMarkerPlace } from "@nexera-ui/react";
<MapMarkerPlace name="Lahore HQ" headcount="1,248" />;
Right to left
Right-to-left: the headcount pill moves to the top-left corner of the pin; the map itself is not mirrored.
import { MapMarkerPlace } from "@nexera-ui/react";
export function RightToLeft() {
return (
<div dir="rtl" lang="ar" className="flex flex-wrap items-end gap-10">
<MapMarkerPlace name="المقر الرئيسي" headcount="24" headcountLabel="شخصًا" />
<MapMarkerPlace name="المقر الرئيسي" headcount="24" headcountLabel="شخصًا" isSelected />
</div>
);
}
Narrow width
Narrow container (320 px): markers are small; a wrapping row keeps them in view.
import { MapMarkerPlace } from "@nexera-ui/react";
export function NarrowWidth() {
return (
<div className="flex max-w-xs flex-wrap items-end gap-8">
<MapMarkerPlace name="Lahore HQ" headcount="24" onPress={() => undefined} />
<MapMarkerPlace name="Karachi office" headcount="11" onPress={() => undefined} />
<MapMarkerPlace name="Islamabad site" onPress={() => undefined} />
</div>
);
}
Disabled
Disabled: dimmed, out of the tab order.
import { MapMarkerPlace } from "@nexera-ui/react";
<MapMarkerPlace name="Lahore HQ" headcount="24" onPress={() => undefined} isDisabled />;
Props 13
Press "Try it" on a card to load that prop into the playground.
13 props shown
name*NexerastringThe place's name. It is the marker's accessible name (WCAG 1.1.1, 4.1.2) and the visible label when the marker is selected.
headcountNexerastring | numberNumber of people at the place: the pill on the pin. It is shown when provided and added to the accessible name ("Lahore HQ, 24 people"). Abbreviate a large number ("1.2k").
headcountLabelNexerastringWord that follows the headcount in the accessible name. Translate it, and use the singular or plural form yourself when it matters.
isSelectedNexerabooleanWhether the place is the selected marker: a larger pin with a halo and the name label, and
aria-current for assistive technology. Hover (State=Hover) is a pointer state that React Aria drives.
idNexerastringDOM id.
aria-describedbyNexerastringId(s) of the element(s) that describe the marker (for example a card with the address).
classNameNexerastringExtra classes, merged last so they win over the defaults.
styleNexeraCSSPropertiesInline style (typically the position on the map).
onPressNexera((event: PressEvent) => void) | ((event: PressEvent) => void)Called when the marker is pressed (pointer, Enter or Space). Makes the marker a button. Also called when the link is pressed.
hrefNexerastringMakes the marker a link to this URL.
targetNexerastringLink target.
relNexerastringLink relationship.
isDisabledNexerabooleanDisables the button. Disables the link.
* Required. React Aria props shown are the ones most apps use; the component accepts the rest of its React Aria props too.
Accessible by default.
Built on React Aria, and covered by the WCAG 2.2 evidence generated on every build.
WCAG 2.2 evidence
6 direct · 2 supporting- 1.1.1Non-text ContentLevel A · tested directly
- 1.3.2Meaningful SequenceLevel A · supporting test
- 1.4.1Use of ColorLevel A · tested directly
- 1.4.12Text SpacingLevel AA · supporting test
- 2.1.1KeyboardLevel A · tested directly
- 2.4.7Focus VisibleLevel AA · tested directly
- 2.5.3Label in NameLevel A · tested directly
- 4.1.2Name, Role, ValueLevel A · tested directly
Fits any width.
Nexera components respond to the space they are given. Drag the corner of the frame, or pick a width.
Styling hooks
Pass className to add Tailwind classes (merged last). State is exposed as data attributes, so you can style it with variants like data-pressed:.
data-disabled
<MapMarkerPlace className="data-disabled:opacity-90 shadow-sm" />Used in blocks
Related components
- AccordionItemOne collapsible section of an FAQ or settings page.
- AreaChartA stacked area chart: layers piled up over time with the title, range switch, actions and legend of the card.
- AvailabilityRowOne person's availability across a window of the day: an avatar with initials and the name, and a timeline with the busy periods drawn as bars.
- AvatarA person or organisation shown as a photo, initials or an icon.
- AvatarGroupA row of overlapping avatars with a "+N" chip for the rest.
- AvatarLabelAn avatar with a name and an optional subtitle beside it, for a person in a list, a header or a mention.
- BadgeShort status or category label: `Tone` x `Variant` x `Size`, with an optional dot, leading icon and remove button.
- BadgeGroupA pill that pairs a small badge with a short message, for an announcement or a status line.