Rename the app shell to the scaffold and give it a FAB slot
Plan step 35: <x-app-shell> becomes <x-scaffold>, M3's and Compose's name for the structure of bars, rails and panes, with no alias; every package view, the showcase, the tests, the skills, README and UPGRADE follow. Its markup and Tailwind classes stay for the navigation rewrite. The new fab slot places the FAB as Compose's Scaffold does - bottom-end, 16px from the edges below medium and 24px from it, clear of the navigation bar and of a snackbar on screen (resources/css/layout/scaffold.css) - and the content region tells a pane inside that the margin is already drawn. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Opus 5
parent
acd6ba21ae
commit
0013e0154d
@@ -44,7 +44,7 @@
|
||||
* the same 37.5rem, so a bar in a narrow column lays out by its own width.
|
||||
*
|
||||
* Everything here is in `@layer components` except the blocks after it, which reach past the
|
||||
* component into what an application wrote — the bottom offset <x-app-shell> publishes, a FAB put
|
||||
* component into what an application wrote — the bottom offset <x-scaffold> publishes, a FAB put
|
||||
* in the rail: those have to beat a utility, and a layer never does.
|
||||
*/
|
||||
|
||||
@@ -296,7 +296,7 @@
|
||||
}
|
||||
|
||||
/* `--material-banner` is the height of a bar pinned across the top of the window — what
|
||||
<x-app-shell>'s `banner` slot holds, if the application made it sticky. The rail sticks
|
||||
<x-scaffold>'s `banner` slot holds, if the application made it sticky. The rail sticks
|
||||
under it rather than behind it; 0 without one. */
|
||||
[data-navigation-rail-panel] {
|
||||
position: sticky;
|
||||
@@ -795,7 +795,7 @@
|
||||
/* A bar that has slid off the bottom of the window is no longer there to clear, so the offset
|
||||
* everything pinned to the bottom reads drops to the bottom safe area and whatever the application
|
||||
* has docked on the bar — a `fab` button, the snackbar and the page's own bottom padding all follow
|
||||
* it down and come back up with the bar. Unlayered on purpose: <x-app-shell> publishes the variable
|
||||
* it down and come back up with the bar. Unlayered on purpose: <x-scaffold> publishes the variable
|
||||
* with a utility, and a rule in any layer loses to one. */
|
||||
[data-app-shell]:has([data-navigation-bar][data-hide-on-scroll][data-hidden]) {
|
||||
--material-bottom-bar: calc(var(--material-safe-bottom, env(safe-area-inset-bottom)) + var(--material-bottom-extra, 0px));
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
/* Placed over the page: centred above the bottom edge, or centred against the end edge.
|
||||
*
|
||||
* A toolbar at the bottom shares the screen region with a navigation bar, so it clears the one
|
||||
* <x-app-shell> publishes as --material-bottom-bar, exactly as the FAB and the snackbar do —
|
||||
* <x-scaffold> publishes as --material-bottom-bar, exactly as the FAB and the snackbar do —
|
||||
* `max()`, not a sum, because that height already swallows the bottom safe area; without a bar
|
||||
* the safe area alone applies. A *docked* toolbar and a navigation bar must never be on screen
|
||||
* together at all (docs/reference/m3/components-navigation-selection-inputs.md § Toolbars); the
|
||||
|
||||
@@ -14,3 +14,4 @@
|
||||
@import './layout/list-detail.css';
|
||||
@import './layout/supporting-pane.css';
|
||||
@import './layout/feed.css';
|
||||
@import './layout/scaffold.css';
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* <x-scaffold>: the FAB it places, and the margin its content region already draws.
|
||||
*
|
||||
* The rest of the scaffold — the rail, the navigation bar, the content region — is still drawn by
|
||||
* its Tailwind classes until its rewrite (plan step 36); this file holds only what step 35 added.
|
||||
*
|
||||
* `data-md-scaffold-fab` places the page's FAB as Compose's Scaffold places its floating action
|
||||
* button: fixed at the bottom-end corner (M3's adaptive placement for a FAB, "lower right (bottom
|
||||
* trailing) corner", docs/reference/m3/components-actions-communication-containment.md § FAB →
|
||||
* Behaviour), with M3's margin from the window's edges — 16px below medium and 24px from 600px
|
||||
* (docs/reference/m3/foundations-supplement.md § Breakpoints). `inset-inline-end` is the trailing
|
||||
* edge, so a right-to-left document puts it on the left, clear of the safe area on that side.
|
||||
*
|
||||
* From the bottom it clears, in order: the navigation bar, or the bottom safe area where there is
|
||||
* none — `max()`, since `--material-bottom-bar` already includes the safe area (the navigation bar
|
||||
* publishes it on the scaffold below medium); then a snackbar while one shows. <x-toast> sits 16px
|
||||
* above the bar and publishes its height as `--material-snackbar-height` while it is on screen, so
|
||||
* the FAB adds that height and the snackbar's own 16px (`min()` of the height and 16px is 16px when
|
||||
* a snackbar shows and 0px when none does) — M3: "snackbars should appear above FABs — never in
|
||||
* front of or behind one" (§ Snackbar → Placement). It moves there on the spatial spring, which
|
||||
* reduced motion makes instant. z-index 30 is the navigation bar's own layer: over the page, under
|
||||
* a scrim and the snackbar.
|
||||
*
|
||||
* `--md-layout-margin: 0px` on the content region tells a pane or canonical layout inside that the
|
||||
* region already keeps the window margin (layout/pane.css), so neither draws it a second time.
|
||||
*
|
||||
* In `material.layout`.
|
||||
*/
|
||||
|
||||
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
|
||||
|
||||
@layer material.layout {
|
||||
[data-md-scaffold] main {
|
||||
--md-layout-margin: 0px;
|
||||
}
|
||||
|
||||
[data-md-scaffold-fab] {
|
||||
--md-scaffold-fab-margin: var(--md-sys-measurement-space200);
|
||||
|
||||
position: fixed;
|
||||
z-index: 30;
|
||||
inset-inline-end: max(
|
||||
var(--md-scaffold-fab-margin),
|
||||
var(--material-safe-right, env(safe-area-inset-right))
|
||||
);
|
||||
inset-block-end: calc(
|
||||
max(var(--material-bottom-bar, 0px), var(--material-safe-bottom, env(safe-area-inset-bottom)))
|
||||
+ var(--md-scaffold-fab-margin)
|
||||
+ var(--material-snackbar-height, 0px)
|
||||
+ min(var(--material-snackbar-height, 0px), var(--md-sys-measurement-space200))
|
||||
);
|
||||
transition: inset-block-end var(--md-sys-motion-spatial-default-duration) var(--md-sys-motion-spatial-default);
|
||||
|
||||
@media (width >= 600px) {
|
||||
--md-scaffold-fab-margin: var(--md-sys-measurement-space300);
|
||||
}
|
||||
}
|
||||
|
||||
[data-md-scaffold-fab]:dir(rtl) {
|
||||
inset-inline-end: max(
|
||||
var(--md-scaffold-fab-margin),
|
||||
var(--material-safe-left, env(safe-area-inset-left))
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user