Skip to content
Twentyfirst UIPro

Floating Layout

Navigation · Badge, FloatingLayout, IconButton, KeyValue, MapView, Panel, SearchField, Segmented

View as Markdown

UI floating over a full-bleed background: a map, a 3D scene, a video or a photo. Four slots sit along the edges (top, start, end, bottom) and everything in them is glass by default, translucent and blurred over what is behind.

  • The background stays interactive wherever no slot sits on it: drag the map, click a pin.
  • controls (zoom, compass, locate) and attribution (the map's source notes) sit in the free corner above the bottom bar, clear of the panels and the dock.
  • startWidth and endWidth size the side columns (320px and 340px by default).
  • The layout publishes --floating-safe-top, -start, -end and -bottom (px): how far its slots reach in. Use them to keep a map library's own controls clear, e.g. .maplibregl-ctrl-bottom-right { right: var(--floating-safe-end); bottom: var(--floating-safe-bottom) }.
  • Below 720px of width the slots stack (top, start, the background, bottom) and the layout grows with them; the end slot becomes a bottom sheet over the background whose handle expands and collapses it (endSheet={false} stacks it instead).
  • surface="solid" turns the glass off; surface="solid" on a single Panel or Card opts just that one out.
  • Panels, cards, the dock, map legends and controls, and loose controls (search field, chips, icon buttons, segmented controls) turn into glass inside it; menus, popovers and dialogs take the stronger glass fill.
  • Text on glass keeps 4.5:1 over any backdrop. Reduced transparency, more contrast and forced colours fall back to solid surfaces.
© OpenStreetMap contributors

Hamburg

Hub

On time
Parcels
840
Delayed
12
Next truck
14:20

Props

Badge

PropTypeNotes
tone?Tone
dot?boolean
live?boolean
children?ReactNode
className?stringExtra class on the root element.
style?CSSPropertiesInline style on the root element.

FloatingLayout

PropTypeNotes
background?ReactNodeWhat the UI floats over, filling the layout: a map, a 3D canvas, a video, a photo.
top?ReactNodeBar along the top edge (search, filters, title).
start?ReactNodeColumn on the start side (layers, lists, settings).
end?ReactNodeColumn on the end side (details of the selected thing).
bottom?ReactNodeBar along the bottom edge (dock, playback, a summary).
controls?ReactNodeControls of the background (zoom, compass, locate) in the free corner above the bottom bar.
attribution?ReactNodeSource notes of the background (map attribution), under `controls`, clear of every slot.
startWidth?number | stringWidth of the start column (default 320px) and of the end column (default 340px).
endWidth?number | string
endSheet?booleanBelow 720px of width the end slot becomes a bottom sheet over the background, with a handle that expands and collapses it (default true). `false` stacks it with the others.
height?number | stringHeight of the layout (default 640). Below 720px of width the slots stack: top, start, end, bottom. The layout sets `--floating-safe-top/-start/-end/-bottom` (px) to the space its slots take, so map libraries can keep their own controls clear of them.
surface?SurfaceGlass for every surface in the slots (default) or solid surfaces.
label?stringAccessible name of the region.
children?ReactNode
className?stringExtra class on the root element.
style?CSSPropertiesInline style on the root element.

IconButton

PropTypeNotes
iconIconNameRequired
labelstringAccessible name and tooltip (`aria-label` and `title`); `aria-label` or `title` override them.
variant?"soft" | "solid" | "outline" | "ghost"
size?"sm" | "md" | "lg"
type?"button" | "submit" | "reset"
onClick?(e: MouseEvent<HTMLButtonElement>) => void
disabled?boolean
asChild?booleanRender the single child element (a link) with the button's look; the icon is placed inside it.
children?ReactNode
id?string
name?stringForm field name and value, sent with the form when this button submits it.
value?string
form?stringThe id of the form this button belongs to, when it sits outside it.
title?string
tabIndex?number
autoFocus?boolean
aria-label?string
aria-labelledby?string
aria-describedby?string
aria-expanded?boolean | "true" | "false"For disclosure and menu triggers: whether what the button controls is open.
aria-controls?string
aria-haspopup?boolean | "true" | "false" | "menu" | "listbox" | "tree" | "grid" | "dialog"
aria-pressed?boolean | "true" | "false" | "mixed"For toggle buttons.
aria-current?boolean | "true" | "false" | "page" | "step" | "location" | "date" | "time"
className?stringExtra class on the root element.
style?CSSPropertiesInline style on the root element.

KeyValue

PropTypeNotes
itemsKeyValueItem[]Required
dense?boolean
className?stringExtra class on the root element.
style?CSSPropertiesInline style on the root element.

MapView

PropTypeNotes
points?MapPoint[]
bounds?{ n: number; s: number; w: number; e: number }
background?ReactNode
bubbles?boolean
selected?MapPoint["id"] | null
onSelect?(id: MapPoint["id"] | null) => void
renderPopup?(p: MapPoint) => ReactNode
legend?ReactNode
controls?ReactNode
height?number | stringHeight in px (default 320) or any CSS length, e.g. "100%" to fill a FloatingLayout.
label?string
surface?Surface`"glass"`: the legend, controls and popup float as glass over the map (for a live map in `background`).
className?string
style?CSSPropertiesInline style on the root element.

Panel

PropTypeNotes
side?boolean
title?string
subtitle?string
action?ReactNode
children?ReactNode
surface?Surface`"glass"`: translucent glass over what is behind (maps, 3D, video, photos); `"solid"` opts out inside a glass `UIProvider`.
className?stringExtra class on the root element.
style?CSSPropertiesInline style on the root element.

SearchField

PropTypeNotes
placeholder?string
label?stringAccessible name (default: the placeholder, or "Search").
shortcut?stringThe key hint, e.g. "⌘K" (hidden on touch screens).
bindShortcut?boolean⌘/Ctrl + the hint's last key (K for "⌘K") focuses the field, except while typing elsewhere.
value?string
defaultValue?string
onChange?(e: ChangeEvent<HTMLInputElement>) => void
onKeyDown?(e: KeyboardEvent<HTMLInputElement>) => void
onFocus?(e: FocusEvent<HTMLInputElement>) => void
onBlur?(e: FocusEvent<HTMLInputElement>) => void
id?string
name?string
autoFocus?boolean
inputProps?InputHTMLAttributes<HTMLInputElement>For a search with suggestions (combobox): role, aria-controls, aria-activedescendant …
className?stringExtra class on the root element.
style?CSSPropertiesInline style on the root element.

Segmented

PropTypeNotes
options(string | Option)[]Required
value?string
defaultValue?string
onChange?(v: string) => void
size?"sm"
block?boolean
label?string
className?stringExtra class on the root element.
style?CSSPropertiesInline style on the root element.