Add menu enable toggle, user status, and mobile/UI polish
- Admin menu page: mobile item cards now put Actions in the top-right
corner next to Status, matching the desktop row layout instead of
stacking at the bottom; same treatment applied to announcements and
users for consistency across all three admin lists
- Center button label text everywhere via .btn { justify-content: center }
instead of one-off overrides
- Add a Disable/Enable Menu toggle to the admin menu toolbar; the public
menu page shows its existing "menu being updated" message while disabled
- Add an Enabled/Disabled status to user accounts, with its own toggle
badge, guardrails against disabling your own account or the last
enabled account, and an immediate session kick for anyone disabled
mid-session
- Fix the announcement banner / hero tagline "·" separators to hide only
when their neighboring text actually wraps onto a different line,
instead of a fixed breakpoint or always-on dot
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
eab20899de
commit
cd4c6c1969
13 files changed
+405
-50
No files matched your search
+116
-22
@@ -34,6 +34,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- wrap-aware separators (JS-toggled, see main.js) ----------
|
||||
Shared hook used by the announcement banner and hero tagline row: a
|
||||
"·" between two pieces of text that can independently wrap onto
|
||||
separate lines. No CSS selector exists for "am I on the same line as
|
||||
my sibling," so main.js measures and toggles this class instead of a
|
||||
fixed breakpoint. Visible by default so a no-JS visitor always sees
|
||||
the dot (today's behavior), never hidden by default.
|
||||
|
||||
display, not visibility: a hidden separator must take no space, or
|
||||
it still gets counted when justify-content: center balances its flex
|
||||
line — a lone badge sharing its line with a space-reserving invisible
|
||||
dot renders off-center. Safe from the "text merges together" bug that
|
||||
originally motivated reserving space: both wrap-sep contexts space
|
||||
their siblings with a real flex `gap` (see .announcement-inner,
|
||||
.tagline-row) rather than the separator's own margin, so removing it
|
||||
from flow still leaves normal spacing behind, never a collision. */
|
||||
.wrap-sep-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background: var(--ground);
|
||||
@@ -478,17 +498,28 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.6rem 0;
|
||||
/* column-gap carries the spacing now (was 0 — the dot's own margin
|
||||
used to be the only thing separating the phrases). Needs to be a
|
||||
real flex gap, not a margin on the dot, so removing a hidden dot
|
||||
from flow (see .wrap-sep-hidden) still leaves normal spacing
|
||||
between the two phrases instead of running them together. */
|
||||
gap: 0.6rem 0.7rem;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.82rem;
|
||||
letter-spacing: 0.04em;
|
||||
color: var(--ink-muted);
|
||||
}
|
||||
|
||||
.tagline-row span:not(:last-child)::after {
|
||||
content: "·";
|
||||
/* Real element instead of a ::after pseudo-element — needs to be a
|
||||
measurable, independently-toggleable DOM node for the wrap-aware
|
||||
script in main.js to hide it when its neighbors wrap apart. No margin
|
||||
of its own: the column-gap above already provides 0.7rem on each
|
||||
side of it (matching the old margin-inline's total spacing exactly),
|
||||
and still applies directly between the two phrases whenever the dot
|
||||
itself is removed from flow. */
|
||||
.tag-sep {
|
||||
color: var(--gold-dim);
|
||||
margin-inline: 0.7rem;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.hero-ctas {
|
||||
@@ -502,6 +533,11 @@
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
/* Centers label text horizontally too — matters once a button is
|
||||
stretched wider than its content (e.g. action-stack children filling
|
||||
a fixed-width column) or wraps to multiple lines; a no-op otherwise,
|
||||
so every button gets this instead of one-off overrides per case. */
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.8rem 1.5rem;
|
||||
font-family: var(--font-mono);
|
||||
@@ -1330,6 +1366,14 @@
|
||||
width: 7.25rem;
|
||||
}
|
||||
|
||||
/* "○ Disabled" is the longer of the two user labels. Not scoped to
|
||||
button.status-badge like the two above — your own row's badge is a
|
||||
plain non-interactive span (see users.php), and it still needs to line
|
||||
up in the same column. */
|
||||
.user-row .status-badge {
|
||||
width: 7rem;
|
||||
}
|
||||
|
||||
/* Admin row actions: the button-group styling shared by every admin
|
||||
list (menu items/categories, announcements, users). The actual
|
||||
row/column layout for each list is its own CSS Grid, defined where
|
||||
@@ -1576,7 +1620,7 @@
|
||||
}
|
||||
|
||||
.user-grid-wrap {
|
||||
grid-template-columns: minmax(0, 1fr) auto auto auto;
|
||||
grid-template-columns: auto minmax(0, 1fr) auto auto auto;
|
||||
}
|
||||
|
||||
.item-grid-wrap,
|
||||
@@ -1640,12 +1684,13 @@
|
||||
}
|
||||
|
||||
.user-grid-head, .user-row {
|
||||
grid-template-areas: "username role created actions";
|
||||
grid-template-areas: "status username role created actions";
|
||||
}
|
||||
|
||||
.col-status,
|
||||
.item-row [data-label="Status"],
|
||||
.ann-row [data-label="Status"] {
|
||||
.ann-row [data-label="Status"],
|
||||
.user-row [data-label="Status"] {
|
||||
grid-area: status;
|
||||
}
|
||||
|
||||
@@ -1726,10 +1771,37 @@
|
||||
columns: subgrid` from the desktop rule, so this one change is all
|
||||
it takes to reflow the whole list (see grid-template-areas per row
|
||||
further down for how each field then stacks within that column). */
|
||||
/* Every list's cards get a second column on mobile so Actions can sit
|
||||
in the top-right corner alongside that list's leading field, instead
|
||||
of stacking at the very bottom of the card — overrides the shared
|
||||
single-column rule that would otherwise apply here too.
|
||||
minmax(0, auto), not plain auto, so this column can still shrink
|
||||
below its content's natural width under pressure instead of forcing
|
||||
the whole row to overflow the card. */
|
||||
.item-grid-wrap,
|
||||
.ann-grid-wrap,
|
||||
.user-grid-wrap {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-columns: 1fr minmax(0, auto);
|
||||
}
|
||||
|
||||
/* Users' actions column gets a fixed cap instead of auto: "Change
|
||||
Password" is long enough that its max-content size (what auto would
|
||||
size the column to) is wider than this corner has room for, which
|
||||
pushed the button past the card edge. A firm cap plus the
|
||||
wrap/stretch rules below keep it predictable instead. */
|
||||
.user-grid-wrap {
|
||||
grid-template-columns: minmax(0, 1fr) 6rem;
|
||||
}
|
||||
|
||||
/* Every row's Actions cell holds one or two .action-stacks (move
|
||||
up/down, edit/delete, etc. — each stacked vertically, see
|
||||
.action-stack itself further up) side by side. Keeps those stacks
|
||||
from wrapping onto their own lines in this narrow corner, which is
|
||||
what the shared .row-actions wrap rule below would otherwise do. */
|
||||
.item-row .row-actions,
|
||||
.ann-row .row-actions,
|
||||
.user-row .row-actions {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.item-grid-head,
|
||||
@@ -1770,28 +1842,50 @@
|
||||
|
||||
.item-row {
|
||||
grid-template-areas:
|
||||
"status"
|
||||
"item"
|
||||
"price"
|
||||
"actions";
|
||||
"status actions"
|
||||
"item item"
|
||||
"price price";
|
||||
/* Overrides the shared align-items: center above — on desktop that
|
||||
vertically centers Status against the taller Item cell in one wide
|
||||
row, which is fine, but here it also centers Status against the
|
||||
taller Actions block above, pushing its badge down instead of
|
||||
keeping both flush with the card's top edge. */
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.ann-row {
|
||||
grid-template-areas:
|
||||
"status"
|
||||
"headline"
|
||||
"type"
|
||||
"schedule"
|
||||
"placements"
|
||||
"actions";
|
||||
"status actions"
|
||||
"headline headline"
|
||||
"type type"
|
||||
"schedule schedule"
|
||||
"placements placements";
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.user-row {
|
||||
grid-template-areas:
|
||||
"username"
|
||||
"role"
|
||||
"created"
|
||||
"actions";
|
||||
"status actions"
|
||||
"username username"
|
||||
"role role"
|
||||
"created created";
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
/* Stretches Actions' whole flex chain out to the fixed 6rem column
|
||||
above (each is shrink-wrapped by default), then lets "Change
|
||||
Password" — long enough on its own to blow out this corner next to a
|
||||
username — wrap onto two lines within that width instead of forcing
|
||||
the column wider. Every other action-stack button here (Edit,
|
||||
Delete, ↑/↓) is short enough to stay on one line regardless. */
|
||||
.user-row .row-actions,
|
||||
.user-row .action-stack,
|
||||
.user-row .row-actions .btn {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.user-row .btn-change-password {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.category-panel .panel-head {
|
||||
|
||||
Reference in new issue
Block a user