Canvas Design System
Main Site Tokens

App Dock

The floating toolbar at the foot of a tool shell: what you have on the left, the ways to add to it in the middle, what happens next on the right.

When to Use

Use when: A screen has a small set of ways to act on what is in front of the reader, and one of them is the way forward. The dock keeps all of them in reach without closing the page the way the rail does, so the work can scroll underneath.
Don't use when: The screen's action is a single button, or the actions need labels to be understood. A dock of one glyph is a floating button; a dock of six unfamiliar glyphs is a puzzle. Use the rail, or ws_button() in the page. Laying out the view itself is the page grid, .app-page: a six-column main beside the two-column rail (App Shell Layouts).

The dock

As Synthesize wears it on the material screen. The lead pill is a read-out ('static' => true), the six slots open the intake's own pickers, and the trail pill is the screen's primary. Each slot's label is its accessible name and its tooltip, which opens upward because the dock sits at the foot of the window.

Variants

Slots only

Four steps of a phase, nothing to count and no separate way forward. This is the shape Strategize draws.

Not ready yet

The trail pill disables under the same condition the screen's primary would, and says why in its tooltip. The dock never hides the way forward; it shows it closed.

Narrow

Under a 720px viewport the slots take a row of their own and the two labelled pills share the row beneath, so nothing is squeezed out of reach of a thumb. The rule reads the viewport, not the stage, so it does not show in a narrow box on this page: resize the window to see it.

Usage

<?= ws_app_dock([
    'id'    => 'synthDock',
    'lead'  => ['label' => '3 Sources', 'id' => 'synthDockCount', 'static' => true],
    'items' => [
        ['icon' => 'videocam', 'label' => 'Add a video', 'attrs' => ['data-act' => 'dockAdd', 'data-kind' => 'video']],
        ['icon' => 'mic',      'label' => 'Add audio',   'attrs' => ['data-act' => 'dockAdd', 'data-kind' => 'audio']],
    ],
    'trail' => ['label' => 'Synthesize', 'icon' => 'auto_awesome', 'iconPosition' => 'right', 'id' => 'synthDockGo'],
]) ?>

The shell that wears it sets position: relative on itself and pads its scroll region by --app-dock-clearance while the dock is showing. Synthesize does that with a has-app-dock class its screen sync toggles.

Accessibility

  • The dock is a <nav> landmark with the label you pass as ariaLabel. Keep it truthful to what the slots do.
  • Every slot's label is its aria-label, so a glyph on its own is never the whole name. The same text is the tooltip on hover and focus.
  • A slot passed 'active' => true announces as pressed (aria-pressed), for docks that mark where the reader is.
  • A static lead pill is a <span>. Give it role="status" through attrs when the count it shows changes while the reader works, as Synthesize does.
  • Focus rings are the platform's white-on-red ring, the same as the app bar's actions. Under prefers-reduced-motion the state layer and press scale hold still.