update 2026-09-25 19:24:22
marry-jell / merge (push) Canceled after 0s

This commit is contained in:
action committed 2026-09-25 19:24:22 +08:00
1 parent e8f9e08c4a
commit ba0a17863f
145 files changed
+23807 -5960

No files matched your search

@@ -1,37 +1,17 @@
@layer theme {
/* ---- the top-layout bar: :root[data-layout="top"], every width ----
*
* A DELTA, not a layout. The bar itself — sticky, blurred, row, popup submenus, square icon
* buttons, right cluster — is the unguarded base in 20-shell.css, the bar being what the chrome
* IS unless the vertical sidebar overrides it. This file adds what the top-layout bar wants on
* top of that:
* - a designed bar height, and padding aligned to the content column;
* - the menu on the brand's row instead of wrapped beneath it.
*
* No `@media` floor: "does the menu fit on the brand's row?" is a property of the CONTENT (5
* sections stock, eleven with a few luci-app-*), not of the viewport, so the whole bar is
* MEASURED — fs-chrome.js shrinks the pills, collapses the poll pill to an icon, then stacks the
* menu onto its own row, at any width. The under-item dropdown and its clamp therefore apply at
* every width too. */
/* a DELTA on top of the bar's unguarded base (20-shell.css), every width — no @media floor,
* fitChrome measures instead — docs/css.md "Toplayout: measured, not media-queried". */
:root[data-layout="top"] .fs-sidebar {
/* min-height, not height: the bar has a designed height but must be able to GROW —
* a long hostname wraps onto a second line inside the capped brand (20-shell.css),
* and a fixed height would clip it. */
/* min-height not height: a long hostname wraps the capped brand onto a second line (20-shell.css) */
min-height: var(--fs-bar-h); height: auto;
gap: var(--fs-space-3);
/* nowrap while the menu rides the brand's row. Without it flexbox wraps the BAR, carrying the
* menu onto a second line by itself while its own pills stay in one row — a stacked bar in
* everything but the styling. It also destroys the fits-on-one-row measurement, a menu handed
* a whole row of course fitting. Forbidding the wrap forces the menu to share the row and to
* wrap its OWN pills when it cannot, which is the signal fitChrome measures. */
/* nowrap or flexbox wraps the BAR itself instead of the menu's own pills — the signal fitChrome measures */
flex-wrap: nowrap;
/* align the bar's contents to the .fs-content column, so the brand and the menu line
* up with the headings and the cards below */
/* aligns the bar to .fs-content so the brand/menu line up with the headings below */
padding: 0 max(20px, calc((100% - var(--fs-content-max)) / 2 + var(--fs-content-pad)));
}
/* the menu rides the brand's row; its flex:1 opens the gap that pushes the right-hand
* cluster to the content column's right edge */
/* flex:1 opens the gap pushing the right cluster to the column's edge */
:root[data-layout="top"] .fs-sidebar ul.nav {
order: 2; flex: 1 1 auto; margin-inline-start: var(--fs-space-2);
}
@@ -39,30 +19,16 @@
:root[data-layout="top"] .fs-themerow,
:root[data-layout="top"] .fs-logout { order: 3; margin-inline-start: 0; }
/* The under-item dropdown anchor, its hover bridge and the clamp are NOT here: they belong to
* the BAR and live unguarded in 20-shell.css. They used to be this file's, and that WAS issue
* #19 — the sidebar layout collapsed onto a bar is the same chrome, and it inherited a panel
* pinned to the bar's left edge with no bridge, unreachable by hover. This file is the top
* layout's delta; a rule every bar state needs is not a delta. */
/* dropdown anchor/bridge/clamp live unguarded in 20-shell.css, not here (issue #19) */
/* the mode strip (only rendered when a router has more than one top-level mode) takes
* its own full-width row under the bar */
/* :not(:empty):not(.single) instead of a hide pair — the bar's base rule (20-shell.css)
* already hides the strip; see the sidebar twin there for why the pair was folded. */
/* :not(:empty):not(.single), not a hide pair: 20-shell.css already hides the mode strip */
:root[data-layout="top"] .fs-modemenu:not(:empty):not(.single) {
display: flex; order: 4; flex: 1 1 100%; margin: 0; gap: var(--fs-space-1);
}
/* the bar replaces the sidebar's 22px top padding with the top-nav's 26px */
:root[data-layout="top"] .fs-content { padding-top: var(--fs-space-6); }
/* ---- the menu does not fit on the brand's row: .fs-bar-stack ----
*
* Set by fs-chrome.js (fitChrome), not by a media query: whether the menu fits beside the brand
* depends on how many sections the router HAS, so the width at which the bar must stack is a
* property of the content and a hard-coded breakpoint gets it wrong in both directions. The JS
* shrinks the pills first, then collapses the poll pill, and stacks only when even that still
* overflows. */
/* .fs-bar-stack: set by fitChrome (fs-chrome.js), not a media query — same reasoning as the header above */
:root[data-layout="top"] .fs-sidebar.fs-bar-stack {
flex-wrap: wrap; height: auto; padding: var(--fs-space-2-5) var(--fs-space-4);
}
@@ -75,16 +41,8 @@
:root[data-layout="top"] .fs-sidebar.fs-bar-stack #indicators,
:root[data-layout="top"] .fs-sidebar.fs-bar-stack .fs-themerow { margin-inline-start: auto; }
:root[data-layout="top"] .fs-sidebar.fs-bar-stack #indicators:not(:empty) ~ .fs-themerow { margin-inline-start: 0; }
/* Two .fs-themerow buttons, Search then Appearance: only the FIRST rendered far-edge item may
* keep the auto inline-start margin, exactly as in the base bar, or flexbox splits the free
* space between the two autos and Search drifts to mid-bar. The base `.fs-themerow ~
* .fs-themerow` guard is out-specified by the auto rule above (0,4,0 against 0,2,0), so it must
* be restated here. Bites when #indicators is :empty — right after an SPA nav, before
* the poll pill returns. */
/* only the FIRST far-edge item keeps the auto margin, restated here — base guard is out-specified (0,4,0 vs 0,2,0) */
:root[data-layout="top"] .fs-sidebar.fs-bar-stack .fs-themerow ~ .fs-themerow { margin-inline-start: 0; }
/* The right cluster's own escalation — .fs-ind-compact and .fs-bar-actrow — is NOT here: it
* belongs to the BAR, and the sidebar layout is a bar too once fitShell has stamped
* data-narrow. Both live with the bar in 20-shell.css; this file is only the top layout's
* delta, and the menu's .fs-bar-stack above is the part that really is top-only. */
/* .fs-ind-compact/.fs-bar-actrow live with the bar in 20-shell.css too — only the top delta lives here */
}