Navigation
ListMapToggle
A two-button segmented switch between a List view and a Map view.
Guidelines#
Use it for record pages that can be shown as a table or on the WorldGlobe: Saved › People and Saved › Organizations. It sits first in the page's header actions, before Share, Import CSV and Add.
What you provide: view: "list" | "map" and onChange(next). In Max the state comes from useListMapView(), in the same file. That hook stores the choice in the view URL parameter, so a shared link opens on the same side. Only map is written; list is the default and leaves the URL clean. The hook calls router.replace without scrolling, and it is not exported on window.DigitalCrew.
Anatomy:
- The track is
bg-muted inline-flex items-center rounded-md p-0.5. - Two small
Buttons,h-8 gap-1.5, with 16pxListandMapicons. - The selected button uses the outline variant with
bg-background shadow-sm. The other is ghost withborder-transparent. - Each button sets
aria-pressed.
Don't use it for more than two views; use Tabs or ToggleGroup instead. Don't keep the view only in component state on a shareable page: the URL parameter is what lets a link open on the map.
Facts#
| Group | Navigation |
|---|---|
| Product | Max |
| Global | window.DigitalCrew.ListMapToggle |
| Source | max-agent: src/components/shared/list-map-toggle.tsx |
| Import in the app | import { ListMapToggle } from "@/components/shared/list-map-toggle"; |
API#
TypeScript declarations emitted from src/components/shared/list-map-toggle.tsx.
export type ListMapView = "list" | "map";
export declare function useListMapView(): {
view: ListMapView;
setView: any;
};
export declare function ListMapToggle({ view, onChange, }: {
view: ListMapView;
onChange: (next: ListMapView) => void;
}): JSX.Element;Example#
The code of the preview above: plain React.createElement against window.DigitalCrew, with realistic data.
<div id="root" class="p-6"></div>
<script>
(function () {
var h = React.createElement, DC = window.DigitalCrew, I = DC.Icons;
function App() {
var s = React.useState("list"), view = s[0], setView = s[1];
return h("div", { className: "space-y-3" },
h("div", { className: "flex flex-wrap items-end justify-between gap-2" },
h("div", { className: "space-y-1" },
h("h1", { className: "text-2xl font-bold tracking-tight" }, "People"),
h("p", { className: "text-sm text-muted-foreground" }, "Everyone in your workspace's knowledge base.")),
h("div", { className: "flex flex-wrap items-center gap-2" },
h(DC.ListMapToggle, { view: view, onChange: setView }),
h(DC.Button, null, h(I.Plus, { className: "h-4 w-4" }), "Add person"))),
h("p", { className: "text-xs text-muted-foreground" }, view === "map" ? "Showing 21 people on the map." : "Showing 21 people in the table."));
}
ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>