Files
Andreas Reinhold / reiniandClaude Opus 5 d0bed0da69 Lift the snackbar above a toolbar placed at the bottom
SealShare's only navigation is a floating toolbar at place="bottom". In
1.x it set --material-bottom-bar to lift the snackbar over it; in 2.0.0
the toolbar reads that variable to place itself, so an application can
no longer set it, and the snackbar landed on the toolbar. M3 nudges a
snackbar "upward to avoid overlapping FABs/docked toolbars" and never
puts one in front of navigation.

A bottom-placed toolbar now publishes --material-bottom-toolbar, the
distance from the window's bottom edge to its top: floating 64px (as
tall as an md or lg FAB beside it), docked 64px plus the safe area it
pads, rounded docked floating from 840px. It is declared on :root and
again on the scaffold's root, the only place its formula sees the bar.
The snackbar clears whichever of the bar and the toolbar reaches higher,
and a page pads its end with it. Two Chromium tests, both failing on the
old formula: a docked toolbar on a scaffold's navigation bar, and a
floating toolbar without a scaffold (plan step 46).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 10:47:50 +02:00

89 lines
4.5 KiB
PHP

{{-- M3 Expressive's toolbar: a set of actions for the current page, in a bar of its own.
`variant`: `floating` (the default: a pill at elevation 3; `vibrant` in primary-container,
`vertical` stands it on end) or `docked` (a full-width bar in surface-container, for the bottom
of a screen). `place` puts it over the page: `bottom` (centred above the bottom edge; a docked
toolbar spans it) or `end` (centred against the end edge, for a vertical one); without it the
toolbar sits where it is written. A `fab` slot sets an `<x-fab>` beside a floating toolbar,
and at the end of a docked one — M3's "With FAB" configuration for both. On a docked toolbar the
controls then gather at the start and the FAB rests on the bar, flat: M3 gives a FAB nested in
another component elevation 0 (Compose's bottomAppBarFabElevation is 0 at every state), where
one beside a floating toolbar keeps its own. It is one of the toolbar's controls then, so the
arrow keys reach it. `label` names it for screen readers.
`rounded` gives a docked toolbar the form M3 lets it take on web and large screens: "the docked
toolbar can be rounded. Dividers can be used to organize large amounts of items", and it "can be
… placed in different parts of the page" (docs/reference/m3/components-navigation-selection-inputs.md
§ Toolbars Behaviour and guidelines). From `expanded` (840px) it is a fully rounded bar that
spans what it is written in, and at `place="bottom"` it lifts clear of the window's edges; below
`expanded` it is the square, full-width docked toolbar, as M3 requires there. Separate groups of
controls with `<x-divider vertical />` between them (in a vertical toolbar, `<x-divider />`):
inside a toolbar it stands as tall as an icon button rather than across the whole bar. The
floating toolbar has no such form — it is fully rounded already, and M3's large-screen advice
for it is to show more controls, or two toolbars at opposite edges.
A docked toolbar and a navigation bar occupy the same region of the screen and M3 says never to
show both at once: the bar belongs on a primary page, the toolbar on a secondary or contextual
one. Either way a toolbar placed at `bottom` clears `--material-bottom-bar`, so it is never
buried under `<x-scaffold>`'s bar. It publishes what it covers in turn, as
`--material-bottom-toolbar` (the distance from the window's bottom edge to its top): the
snackbar lifts above it, and a page pads its end with it.
Put `<x-button icon="…" tooltip="…" />` controls in the slot (`:selected` for toggles). It is a
`role="toolbar"`: the arrow keys move between its controls (resources/js/toolbar.js,
resources/css/components/toolbar.css).
The toolbar renders `data-md-toolbar` with `data-md-variant`, `data-md-vertical`,
`data-md-vibrant`, `data-md-rounded` and `data-md-toolbar-place`; a FAB beside a floating
toolbar sits in `data-md-toolbar-group` (with the toolbar itself), one docked in
`data-md-toolbar-fab`. Drawn by resources/css/components/toolbar.css, which the view renders
no other component into a caller's own `<x-button>`, `<x-fab>` and `<x-divider>` bring
their own stylesheets. --}}
@props([
'variant' => 'floating',
'vibrant' => false,
'vertical' => false,
'place' => null,
'label' => null,
'rounded' => false,
])
@php
$variant = $variant === 'docked' ? 'docked' : 'floating';
$vertical = $vertical && $variant === 'floating';
$place = in_array($place, ['bottom', 'end'], true) ? $place : null;
$rounded = $rounded && $variant === 'docked';
$grouped = isset($fab) && $variant === 'floating';
$docksFab = isset($fab) && $variant === 'docked';
@endphp
@if ($grouped)
<div data-md-toolbar-group @if ($vertical) data-md-vertical @endif @if ($place) data-md-toolbar-place="{{ $place }}" @endif>
@endif
<div
role="toolbar"
x-data="materialToolbar({{ $vertical ? 'true' : 'false' }})"
x-on:keydown="move($event)"
data-md-toolbar
data-md-variant="{{ $variant }}"
@if ($vertical) data-md-vertical aria-orientation="vertical" @endif
@if ($vibrant && $variant === 'floating') data-md-vibrant @endif
@if ($rounded) data-md-rounded @endif
@if ($place && ! $grouped) data-md-toolbar-place="{{ $place }}" @endif
@if (filled($label)) aria-label="{{ $label }}" @endif
{{ $attributes }}
>
{{ $slot }}
@if ($docksFab)
<div data-md-toolbar-fab>{{ $fab }}</div>
@endif
</div>
@if ($grouped)
{{ $fab }}
</div>
@endif