Pular para o conteúdo

Toolbars (docked + floating)

components specs/components/toolbars.kmd

Material 3 Expressive Toolbars — substituem o legado Bottom App Bar. Two variants: docked (anchored bottom, 56dp) and floating (horizontal bottom-center OR vertical side, hide-on-scroll). Companion to FAB. Bottom app bar marked deprecated-in-expressive.

Quando esta spec se aplica

Triggers primários

Todos os triggers

Corpo da especificação

Spec — Toolbars (docked + floating)

Sibling: app-bars.kmd (navegação principal). Esta spec cobre contextual actions (toolbars), distintos de navegação.

Princípios

  1. App-bar ≠ Toolbar — app-bar é navegação principal (app-bars.kmd). Toolbar é ações contextuais.
  2. Two anchored variants — docked (anchor fixo bottom) vs floating (translucent, hide-on-scroll).
  3. Pair com FAB — floating toolbar mais comum pareando com FAB no canto.
  4. Bottom app bar deprecated-in-expressive — manter retro-compat, mas não recomendar pra novos surfaces.

R1 — Decision tree

Need contextual actions row?
├── NO → use app bar (navegação)
└── YES:
    ├── Few actions, persistent → docked toolbar (R2)
    ├── Many actions OR auto-hide preferred → floating toolbar (R3)
    │   ├── Horizontal default (bottom-center)
    │   └── Vertical (tablet/desktop, side-anchored)
    └── Legacy/migration → bottom app bar (deprecated)

R2 — Docked toolbar

  • Anchor: bottom of viewport (above safe-area inset per app-layout/safe-area.kmd).
  • Height: 56dp.
  • Max actions: 5 (above → migrate to floating OR menu).
  • Background: surface per color-roles.kmd.
  • Elevation: 1dp (subtle).
  • Scroll behavior: lift-on-scroll (slight elevation increase) OR hide-on-scroll-down (configurable).

R2.1 — Anatomia

┌──────────────────────────────────────────┐
│  [Action] [Action] [Action] [Action] [⋯] │   ← 56dp height
└──────────────────────────────────────────┘

Actions: icon-only OR icon+label (configurable per action). Overflow quando > 5.

R3 — Floating toolbar

R3.1 — Horizontal floating

  • Anchor: bottom-center, floating above content (with backdrop blur OR translucent).
  • Width: hug-content (min 240dp / max 80% viewport).
  • Padding: 16dp from bottom edge (above safe-area).
  • Elevation: 3dp.
  • Shape: shape-corner-extra-large (pill).
  • Background: surface-container-high per color-roles.kmd.
  • Behavior: hide-on-scroll-down + reveal-on-scroll-up via spring (motion.kmd R9.1 motion-spatial-default).

R3.2 — Vertical floating

  • Anchor: right-edge (LTR) or left-edge (RTL); vertically centered or top.
  • Tablets/desktops (Medium+ window class).
  • Auto-pin/unpin via drag.
  • Same elevation + shape + background as horizontal.

R3.3 — FAB pairing

Floating toolbar comumente paired com FAB:

                                       ┌─┐
                                       │+│   ← FAB
                                       └─┘
   ┌──────────────────────┐
   │ [A] [B] [C]          │   ← Floating toolbar (bottom-left)
   └──────────────────────┘

FAB scrolls/hides independently OR paired (configurable per surface).

R4 — Bottom app bar deprecation

app-bars.kmd bottom variant marked deprecated-in-expressive:

  • Retain support pra apps que ainda usam (no breaking change).
  • New surfaces SHOULD use docked toolbar instead.
  • Migration warning visible em koder-spec-audit quando bottom app bar detected em new code.

R5 — Surface bindings

SurfaceAPI
FlutterKoderDockedToolbar({actions}) + KoderFloatingToolbar({actions, direction}) em koder_kit/ (futuro)
Web<koder-docked-toolbar> + <koder-floating-toolbar direction="horizontal|vertical">
Compose AndroidKoderDockedToolbar + KoderFloatingToolbar (futuro)
SwiftUI iOSidem (futuro)
CLI / TUIStatus line actions; no floating

R6 — Acessibilidade

  • Toolbar: role="toolbar" aria-label="<context>".
  • Actions: standard button semantic per buttons.kmd.
  • Floating: focus-trap NOT applied (open / not modal).
  • Hide-on-scroll: aria-hidden="true" when hidden; revealed restores.
  • Keyboard: Tab through actions; arrow keys navigate (per Material toolbar pattern).

R7 — i18n

Keyen-USpt-BR
toolbar.label.actions"Actions""Ações"
toolbar.overflow"More""Mais"

R8 — Reduced-motion

Hide-on-scroll: instant (no spring slide). Lift-on-scroll: elevation change instant.

R9 — Per-preset variation

PresetToolbar style
material3 / material_expressiveDefault (docked + floating com shape pill)
material2Docked only (sharp corners); floating not supported
terminal_classicBottom row text-only; no floating
brutalistSharp corners; flat (no elevation/shadow)
cyberpunk_neonDefault + neon outline on floating
minimalist_monoSingle border-top; no fill
glassmorphismFloating backdrop-blur 30% (heavier)

T-suite

  • T1 Docked mount: 3 actions render at bottom; height 56dp.
  • T2 Docked overflow: 6 actions → 5 visible + overflow menu.
  • T3 Floating horizontal mount: bottom-center; pill shape; elevation 3dp.
  • T4 Floating hide-on-scroll: scroll down 100px → toolbar slides out; scroll up → slides back.
  • T5 Floating vertical: Medium window class → side-anchored.
  • T6 FAB pair: floating toolbar + FAB → both anchor independently OR paired per config.
  • T7 Bottom app bar deprecation: existing instances continue to work; audit warns on new uses.
  • T8 Reduced-motion: hide/reveal instant.
  • T9 A11y: role="toolbar"; keyboard nav functional.

Requirements (testable)

Requirement: Docked toolbar anchoring and capacity {#req-toolbars-docked}

The docked toolbar SHALL anchor to the bottom of the viewport above the safe-area inset with a fixed height of 56dp, render at most 5 actions inline, and collapse any actions beyond the fifth into an overflow () menu.

Scenario: Mount with three actions

  • GIVEN a docked toolbar configured with 3 actions
  • WHEN the toolbar mounts
  • THEN all 3 actions render in a single row anchored at the bottom of the viewport
  • AND the toolbar height measures 56dp
  • AND the toolbar sits above the safe-area inset

Scenario: Overflow beyond five actions

  • GIVEN a docked toolbar configured with 6 actions
  • WHEN the toolbar mounts
  • THEN exactly 5 actions render inline
  • AND a trailing overflow control is shown
  • AND activating reveals the 6th action in an overflow menu

Requirement: Horizontal floating toolbar presentation and hide-on-scroll {#req-toolbars-floating-horizontal}

The horizontal floating toolbar SHALL float bottom-center above content with shape-corner-extra-large (pill) shape and 3dp elevation, and SHALL hide on scroll-down and reveal on scroll-up.

Scenario: Mount bottom-center as pill

  • GIVEN a horizontal floating toolbar
  • WHEN the toolbar mounts
  • THEN it is anchored bottom-center, floating above the content
  • AND its shape is shape-corner-extra-large (pill)
  • AND its elevation is 3dp

Scenario: Hide on scroll down and reveal on scroll up

  • GIVEN a visible horizontal floating toolbar
  • WHEN the content is scrolled down by 100px
  • THEN the toolbar slides out of view
  • WHEN the content is subsequently scrolled up
  • THEN the toolbar slides back into view

Requirement: Vertical floating toolbar on Medium+ window class {#req-toolbars-floating-vertical}

The vertical floating toolbar SHALL side-anchor (right edge in LTR, left edge in RTL) only on Medium or larger window classes, retaining the same elevation, shape, and background as the horizontal variant.

Scenario: Side-anchored on a Medium window

  • GIVEN a floating toolbar with vertical direction on a Medium window class
  • WHEN the toolbar mounts in an LTR layout
  • THEN the toolbar is anchored to the right edge
  • AND it uses the same 3dp elevation, pill shape, and surface-container-high background as the horizontal variant

Requirement: Bottom app bar deprecation without breakage {#req-toolbars-deprecation}

Existing bottom app bar instances SHALL continue to function with no breaking change, and koder-spec-audit SHALL emit a migration warning when a bottom app bar is detected in new code while docked toolbar remains the recommended replacement.

Scenario: Existing instance keeps working

  • GIVEN a surface already using a bottom app bar
  • WHEN the surface is rendered after the deprecation
  • THEN the bottom app bar renders and functions unchanged

Scenario: Audit warns on new usage

  • GIVEN new code that introduces a bottom app bar
  • WHEN koder-spec-audit runs against that code
  • THEN a migration warning is reported recommending the docked toolbar

Requirement: Toolbar accessibility semantics and keyboard navigation {#req-toolbars-a11y}

A toolbar SHALL expose role="toolbar" with an aria-label for its context, SHALL support Tab-into and arrow-key navigation across its actions, SHALL NOT apply a focus trap to floating toolbars, and SHALL set aria-hidden="true" while hidden by scroll and restore it on reveal.

Scenario: Role, label, and keyboard traversal

  • GIVEN a mounted toolbar with multiple actions
  • WHEN the toolbar is inspected
  • THEN it exposes role="toolbar" with a non-empty aria-label
  • AND Tab moves focus into the toolbar
  • AND arrow keys move focus between actions

Scenario: Floating toolbar is not modal

  • GIVEN a visible floating toolbar
  • WHEN focus moves via Tab while the toolbar is open
  • THEN focus is able to leave the toolbar
  • AND no focus trap is applied

Scenario: Hidden state marks aria-hidden

  • GIVEN a floating toolbar hidden by scroll-down
  • WHEN its accessibility state is inspected
  • THEN it exposes aria-hidden="true"
  • WHEN it is revealed on scroll-up
  • THEN aria-hidden is removed

Requirement: Reduced-motion instant transitions {#req-toolbars-reduced-motion}

Under a reduced-motion preference, the toolbar SHALL perform hide-on-scroll and reveal without a spring slide and SHALL apply lift-on-scroll elevation changes instantly.

Scenario: Instant hide under reduced motion

  • GIVEN reduced-motion is enabled
  • AND a visible floating toolbar
  • WHEN the content is scrolled down past the hide threshold
  • THEN the toolbar disappears instantly with no slide animation

Referências