Action Island
A floating tray of actions over a canvas, with one clear next step.
import { ActionIsland, ActionIslandGroup, ActionIslandMark, ActionIslandSeparator, ActionIslandTile } from '@youj/react'
Installation & usage
npm i @youj/reactFor an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.
Use an action island for the few actions that belong to a canvas, a preview or a map, and that should float above it. Each action is its own tile, a pressed tile marks the view that's showing, and one primary tile is the next step. For a dense row of editing controls, use a Toolbar.
import { ActionIsland, ActionIslandGroup, ActionIslandMark, ActionIslandSeparator, ActionIslandTile } from '@youj/react'
import { CodeIcon, EyeIcon, LayersIcon, SparklesIcon } from '@youj/icons'
export function Viewer() {
return (
<ActionIsland aria-label="Preview actions">
<ActionIslandMark aria-hidden>
<LayersIcon />
</ActionIslandMark>
<ActionIslandGroup aria-label="View">
<ActionIslandTile label="Preview" pressed>
<EyeIcon />
</ActionIslandTile>
<ActionIslandTile label="Code" pressed={false}>
<CodeIcon />
</ActionIslandTile>
</ActionIslandGroup>
<ActionIslandSeparator />
<ActionIslandTile label="Open" variant="primary" showLabel>
<SparklesIcon />
</ActionIslandTile>
</ActionIsland>
)
}Every tile is an icon with a label: its tooltip, and its accessible name. showLabel draws the label beside the icon, for a primary action. ActionIslandMark names what the island acts on and isn't a control. Pass render to make a tile a menu's trigger or a link.
Description
A preview toolbar over a canvas: a mark, a Preview, Code and Info view switch, a copy-link tile and a More menu.
Put a tile inside a Dropdown Menu and pass render={<DropdownMenuTrigger />}. The tile stays in the island's arrow-key order and keeps its accent outline while the menu is open. The More tile in the demo shows it.
The island centered over a canvas, with its tiles in a row and the primary Open tile showing its label.
Center the island over a canvas with a wrapper; it sizes to its tiles. The tooltips open above by default; set side on a tile to change that.
The same island in an Arabic interface, mirrored.
The tiles run from the right, and the arrow keys rove the other way.
Code
action-island-demo.tsx, the Demo story. The component itself comes from the package.
Reference
Propslabel, pressed, variant… (8)
Props
ActionIslandTile
| Prop | Type | |
|---|---|---|
labelRequired | stringThe tooltip and the accessible name (keep any shown text inside it: "Story: Default" for a tile that shows "Default"). | – |
children | ReactNodeThe icon (and, with | – |
pressed | booleanA two-state tile (a view that's showing, a mode that's on): aria-pressed, drawn with an accent outline. | – |
variant | 'quiet' | 'primary'
default 'quiet' | 'quiet' |
showLabel | boolean | ReactNodeDraw the label beside the icon (a primary action, a picker's current value). The tooltip stays for a truncated one. | – |
side | 'top' | 'bottom' | 'left' | 'right'The tooltip's side. default 'top' | 'top' |
render | ReactElementRenders the tile through another element: a menu's trigger, or a link ( | – |
ref | Ref<HTMLButtonElement>Allows getting a ref to the component instance.
Once the component unmounts, React will set | – |
Other props pass through: extends ToolbarPrimitive.Button.Props. | ||
ActionIsland takes Base UI's toolbar props (orientation, loopFocus, disabled). ActionIslandGroup labels a cluster of tiles with aria-label.
MotionPress, release and hover · reduced motion
Motion
| Moment | Tokens | ||
|---|---|---|---|
| Presseach tile scales to 0.96 while held | duration.instantease.standard80ms · cubic-bezier(0.2, 0, 0, 1) | 80mscubic-bezier(0.2, 0, 0, 1) | |
| Release and hoverscale back, background, outline and text colors | duration.fastease.standard140ms · cubic-bezier(0.2, 0, 0, 1) | 140mscubic-bezier(0.2, 0, 0, 1) |
Reduced motion
Tiles don't scale when pressed.
Reduced motion
Tiles don't scale when pressed. Colors still change on hover and press.
AccessibilityKeyboard, ARIA
Accessibility
- The root is a
toolbar; name it witharia-label. It's a single tab stop, and the arrow keys move between tiles and wrap at the ends, mirrored in right-to-left layouts. Home and End jump to the ends. - A pressed tile exposes
aria-pressed. A disabled tile stays in the arrow-key order. - A tile's
labelis its accessible name and its tooltip, which also opens on a long press on touch. The mark is out of the tab order; hide it witharia-hiddenwhen it's only an icon.