diff --git a/SLASHED-for-WP/admin-app/.vendored-manifest.json b/SLASHED-for-WP/admin-app/.vendored-manifest.json index 6db4979..e222d61 100644 --- a/SLASHED-for-WP/admin-app/.vendored-manifest.json +++ b/SLASHED-for-WP/admin-app/.vendored-manifest.json @@ -3,313 +3,313 @@ "description": "Files vendored from the SLASHED framework configurator. DO NOT edit directly — make changes in codeslash-dev/SLASHED → configurator/src/ and re-run npm run sync.", "frameworkRepo": "https://github.com/codeslash-dev/SLASHED", "configuratorSrc": "configurator/src/", - "source": "github:codeslash-dev/slashed@v0.7.35", - "syncedAt": "2026-08-21T09:34:18.872Z" + "source": "github:codeslash-dev/slashed@v0.7.36", + "syncedAt": "2026-08-25T08:24:07.598Z" }, "vendoredFiles": [ { "file": "src/app.css", - "source": "github:codeslash-dev/slashed/configurator/src/app.css@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/app.css@v0.7.36" }, { "file": "src/App.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/App.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/App.svelte@v0.7.36" }, { "file": "src/components/CommandPalette.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/CommandPalette.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/CommandPalette.svelte@v0.7.36" }, { "file": "src/components/DomainPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/DomainPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/DomainPanel.svelte@v0.7.36" }, { "file": "src/components/inputs/AspectRatioInput.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/AspectRatioInput.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/AspectRatioInput.svelte@v0.7.36" }, { "file": "src/components/inputs/ClampField.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/ClampField.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/ClampField.svelte@v0.7.36" }, { "file": "src/components/inputs/ColorInput.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/ColorInput.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/ColorInput.svelte@v0.7.36" }, { "file": "src/components/inputs/OklchColorDesk.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/OklchColorDesk.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/OklchColorDesk.svelte@v0.7.36" }, { "file": "src/components/inputs/PowerKnobRow.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/PowerKnobRow.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/PowerKnobRow.svelte@v0.7.36" }, { "file": "src/components/inputs/RangeWithNumber.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/RangeWithNumber.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/RangeWithNumber.svelte@v0.7.36" }, { "file": "src/components/inputs/RawTokenRow.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/RawTokenRow.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/RawTokenRow.svelte@v0.7.36" }, { "file": "src/components/inputs/ScaleShadowNotice.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/ScaleShadowNotice.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/ScaleShadowNotice.svelte@v0.7.36" }, { "file": "src/components/inputs/Section.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/Section.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/Section.svelte@v0.7.36" }, { "file": "src/components/inputs/SliderRow.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/SliderRow.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/SliderRow.svelte@v0.7.36" }, { "file": "src/components/inputs/Toggle.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/Toggle.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/Toggle.svelte@v0.7.36" }, { "file": "src/components/inputs/TokenRow.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/TokenRow.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/TokenRow.svelte@v0.7.36" }, { "file": "src/components/inputs/TypeSpecimenRow.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/TypeSpecimenRow.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/TypeSpecimenRow.svelte@v0.7.36" }, { "file": "src/components/inputs/ValueField.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/ValueField.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/inputs/ValueField.svelte@v0.7.36" }, { "file": "src/components/panels/AccessibilityPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/AccessibilityPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/AccessibilityPanel.svelte@v0.7.36" }, { "file": "src/components/panels/AllTokensTab.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/AllTokensTab.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/AllTokensTab.svelte@v0.7.36" }, { "file": "src/components/panels/BordersPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/BordersPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/BordersPanel.svelte@v0.7.36" }, { "file": "src/components/panels/ChangesPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/ChangesPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/ChangesPanel.svelte@v0.7.36" }, { "file": "src/components/panels/CheatsheetPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/CheatsheetPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/CheatsheetPanel.svelte@v0.7.36" }, { "file": "src/components/panels/ColorsPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/ColorsPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/ColorsPanel.svelte@v0.7.36" }, { "file": "src/components/panels/ComponentsPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/ComponentsPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/ComponentsPanel.svelte@v0.7.36" }, { "file": "src/components/panels/DepthPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/DepthPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/DepthPanel.svelte@v0.7.36" }, { "file": "src/components/panels/EffectsPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/EffectsPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/EffectsPanel.svelte@v0.7.36" }, { "file": "src/components/panels/ExportPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/ExportPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/ExportPanel.svelte@v0.7.36" }, { "file": "src/components/panels/GenericTokenPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/GenericTokenPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/GenericTokenPanel.svelte@v0.7.36" }, { "file": "src/components/panels/HomePanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/HomePanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/HomePanel.svelte@v0.7.36" }, { "file": "src/components/panels/LayoutPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/LayoutPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/LayoutPanel.svelte@v0.7.36" }, { "file": "src/components/panels/MacrosPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/MacrosPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/MacrosPanel.svelte@v0.7.36" }, { "file": "src/components/panels/MiscPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/MiscPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/MiscPanel.svelte@v0.7.36" }, { "file": "src/components/panels/MotionPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/MotionPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/MotionPanel.svelte@v0.7.36" }, { "file": "src/components/panels/ShadowsPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/ShadowsPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/ShadowsPanel.svelte@v0.7.36" }, { "file": "src/components/panels/SpacingPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/SpacingPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/SpacingPanel.svelte@v0.7.36" }, { "file": "src/components/panels/ThemesPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/ThemesPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/ThemesPanel.svelte@v0.7.36" }, { "file": "src/components/panels/TypographyPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/TypographyPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/TypographyPanel.svelte@v0.7.36" }, { "file": "src/components/panels/WcagPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/panels/WcagPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/panels/WcagPanel.svelte@v0.7.36" }, { "file": "src/components/shell/PreviewPanel.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/shell/PreviewPanel.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/shell/PreviewPanel.svelte@v0.7.36" }, { "file": "src/components/shell/SidebarNav.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/shell/SidebarNav.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/shell/SidebarNav.svelte@v0.7.36" }, { "file": "src/components/shell/StatusBar.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/shell/StatusBar.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/shell/StatusBar.svelte@v0.7.36" }, { "file": "src/components/shell/StudioHeader.svelte", - "source": "github:codeslash-dev/slashed/configurator/src/components/shell/StudioHeader.svelte@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/components/shell/StudioHeader.svelte@v0.7.36" }, { "file": "src/data/api-index.generated.json", - "source": "github:codeslash-dev/slashed/configurator/src/data/api-index.generated.json@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/data/api-index.generated.json@v0.7.36" }, { "file": "src/data/bundles.generated.json", - "source": "github:codeslash-dev/slashed/configurator/src/data/bundles.generated.json@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/data/bundles.generated.json@v0.7.36" }, { "file": "src/data/classes.generated.json", - "source": "github:codeslash-dev/slashed/configurator/src/data/classes.generated.json@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/data/classes.generated.json@v0.7.36" }, { "file": "src/data/domain-map.json", - "source": "github:codeslash-dev/slashed/configurator/src/data/domain-map.json@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/data/domain-map.json@v0.7.36" }, { "file": "src/data/google-fonts.generated.json", - "source": "github:codeslash-dev/slashed/configurator/src/data/google-fonts.generated.json@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/data/google-fonts.generated.json@v0.7.36" }, { "file": "src/data/token-registry.generated.json", - "source": "github:codeslash-dev/slashed/configurator/src/data/token-registry.generated.json@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/data/token-registry.generated.json@v0.7.36" }, { "file": "src/data/token-renames.generated.json", - "source": "github:codeslash-dev/slashed/configurator/src/data/token-renames.generated.json@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/data/token-renames.generated.json@v0.7.36" }, { "file": "src/lib/basics.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/basics.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/basics.ts@v0.7.36" }, { "file": "src/lib/codec.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/codec.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/codec.ts@v0.7.36" }, { "file": "src/lib/colorConvert.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/colorConvert.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/colorConvert.ts@v0.7.36" }, { "file": "src/lib/colorUtils.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/colorUtils.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/colorUtils.ts@v0.7.36" }, { "file": "src/lib/domains.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/domains.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/domains.ts@v0.7.36" }, { "file": "src/lib/history.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/history.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/history.ts@v0.7.36" }, { "file": "src/lib/importOverrides.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/importOverrides.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/importOverrides.ts@v0.7.36" }, { "file": "src/lib/lumlockerPreview.svelte.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/lumlockerPreview.svelte.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/lumlockerPreview.svelte.ts@v0.7.36" }, { "file": "src/lib/persistence.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/persistence.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/persistence.ts@v0.7.36" }, { "file": "src/lib/powerKnobs.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/powerKnobs.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/powerKnobs.ts@v0.7.36" }, { "file": "src/lib/preview/catalog.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/preview/catalog.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/preview/catalog.ts@v0.7.36" }, { "file": "src/lib/preview/index.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/preview/index.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/preview/index.ts@v0.7.36" }, { "file": "src/lib/preview/sections.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/preview/sections.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/preview/sections.ts@v0.7.36" }, { "file": "src/lib/preview/skin.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/preview/skin.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/preview/skin.ts@v0.7.36" }, { "file": "src/lib/preview/specimen.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/preview/specimen.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/preview/specimen.ts@v0.7.36" }, { "file": "src/lib/previewResolver.svelte.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/previewResolver.svelte.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/previewResolver.svelte.ts@v0.7.36" }, { "file": "src/lib/savedThemes.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/savedThemes.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/savedThemes.ts@v0.7.36" }, { "file": "src/lib/scaleShadow.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/scaleShadow.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/scaleShadow.ts@v0.7.36" }, { "file": "src/lib/theme.svelte.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/theme.svelte.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/theme.svelte.ts@v0.7.36" }, { "file": "src/lib/themeFile.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/themeFile.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/themeFile.ts@v0.7.36" }, { "file": "src/lib/tokenModel.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/tokenModel.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/tokenModel.ts@v0.7.36" }, { "file": "src/lib/valueField.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/valueField.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/valueField.ts@v0.7.36" }, { "file": "src/lib/variableScales.ts", - "source": "github:codeslash-dev/slashed/configurator/src/lib/variableScales.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/lib/variableScales.ts@v0.7.36" }, { "file": "src/main.ts", - "source": "github:codeslash-dev/slashed/configurator/src/main.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/main.ts@v0.7.36" }, { "file": "src/types.ts", - "source": "github:codeslash-dev/slashed/configurator/src/types.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/types.ts@v0.7.36" }, { "file": "src/vite-env.d.ts", - "source": "github:codeslash-dev/slashed/configurator/src/vite-env.d.ts@v0.7.35" + "source": "github:codeslash-dev/slashed/configurator/src/vite-env.d.ts@v0.7.36" } ] } diff --git a/SLASHED-for-WP/admin-app/framework-css/dist/slashed.full.css b/SLASHED-for-WP/admin-app/framework-css/dist/slashed.full.css index 2ddadce..9d711a3 100644 --- a/SLASHED-for-WP/admin-app/framework-css/dist/slashed.full.css +++ b/SLASHED-for-WP/admin-app/framework-css/dist/slashed.full.css @@ -1,4 +1,4 @@ -/*! SLASHED v0.7.35 — slashed.full.css | MIT License | github.com/codeslash-dev/SLASHED */ +/*! SLASHED v0.7.36 — slashed.full.css | MIT License | github.com/codeslash-dev/SLASHED */ /* ─── core/layers.css ─── */ /* SLASHED — core/layers.css diff --git a/SLASHED-for-WP/admin-app/src/App.svelte b/SLASHED-for-WP/admin-app/src/App.svelte index 38ec8a9..4c33c00 100644 --- a/SLASHED-for-WP/admin-app/src/App.svelte +++ b/SLASHED-for-WP/admin-app/src/App.svelte @@ -53,13 +53,50 @@ let showPalette = $state(false); // Mobile category drawer (replaces the cramped icon rail on narrow screens). let navDrawerOpen = $state(false); + // The shell root — also our container-query context (see the wrapper below). + // A ResizeObserver on it reconciles the drawer when the *container* (not the + // viewport) crosses the desktop breakpoint: `@3xl:hidden` would otherwise only + // CSS-hide an open drawer, leaving a hidden aria-modal dialog mounted and its + // focus-restore (use:drawerFocus) un-run. Container width, not viewport, is + // what actually decides whether the persistent rail is showing. + let shellEl = $state(null); + // The desktop icon rail wrapper — used as a focus fallback when a breakpoint + // close hides the drawer's original trigger (see drawerFocus above). + let railEl = $state(null); + // Mirror of the `@3xl` container breakpoint, expressed in rem so it tracks the + // CSS even when a host sets a non-16px root font size. `rem` (and therefore + // Tailwind's container breakpoints) resolve against the *root* font size, so + // convert to px against that — a hardcoded 768 would drift from `@3xl` the + // moment `html { font-size }` isn't the 16px default. + const DESKTOP_SHELL_REM = 48; + function desktopShellPx(): number { + const root = + typeof document !== "undefined" + ? parseFloat(getComputedStyle(document.documentElement).fontSize) + : NaN; + return DESKTOP_SHELL_REM * (Number.isFinite(root) && root > 0 ? root : 16); + } // When the drawer (a modal dialog) opens, move focus into it so keyboard users // land inside the modal — the dialog's Escape handler then receives the event, // and screen readers announce it. On close, focus returns to the trigger. function drawerFocus(node: HTMLElement) { const prev = document.activeElement as HTMLElement | null; node.focus(); - return { destroy() { prev?.focus?.(); } }; + return { + destroy() { + // Restore focus to whatever was focused before the drawer opened — + // normally the mobile trigger. But when the drawer closes because the + // shell reached desktop width (the ResizeObserver below), that trigger + // is now `@3xl:hidden` (offsetParent === null); focusing a hidden node + // drops focus to . In that case move focus to the visible desktop + // rail's current item instead so keyboard focus stays in the nav. + if (prev && prev.offsetParent !== null) { prev.focus?.(); return; } + const target = + railEl?.querySelector('[aria-current="page"]') ?? + railEl?.querySelector("button"); + target?.focus?.(); + }, + }; } // Close on Escape and trap Tab/Shift+Tab inside the modal drawer so keyboard // focus can't wander to the controls behind an aria-modal dialog. @@ -331,8 +368,25 @@ } }; window.addEventListener("keydown", handler); + + // Close the mobile drawer once the shell is wide enough to show the + // persistent rail. Without this, growing the container past the breakpoint + // (e.g. an embedded host resizing, or rotating to landscape) merely + // `@3xl:hidden`s an open drawer — the aria-modal dialog stays in the DOM and + // use:drawerFocus never restores focus to the trigger. Observing the shell's + // own box (our @container element) matches exactly what the CSS reacts to. + let ro: ResizeObserver | undefined; + if (shellEl && typeof ResizeObserver !== "undefined") { + ro = new ResizeObserver((entries) => { + const width = entries[0]?.contentRect.width ?? 0; + if (width >= desktopShellPx() && navDrawerOpen) navDrawerOpen = false; + }); + ro.observe(shellEl); + } + return () => { window.removeEventListener("keydown", handler); + ro?.disconnect(); if (saveStateTimer) clearTimeout(saveStateTimer); if (importStatusTimer) clearTimeout(importStatusTimer); }; @@ -354,7 +408,15 @@ {/snippet} -
+ +