mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-11-01 16:44:45 +08:00
251 lines
13 KiB
CSS
251 lines
13 KiB
CSS
@layer theme {
|
|
/* buttons straight in a field (Enable/Disable, Start/Restart/Stop) only get whitespace
|
|
* spacing inline-block, collapsing rows on wrap — wrapping flex with a real gap instead */
|
|
.cbi-value-field:has(> .cbi-button) {
|
|
display: inline-flex; flex-wrap: wrap; gap: var(--fs-space-2); align-items: center; justify-content: flex-end;
|
|
}
|
|
|
|
/* native input types listed on purpose: LuCI also emits <input type=submit|reset|button>
|
|
* (sysauth, luci-compat cbi/*.htm), mostly with .cbi-button; luci-app-splash emits bare ones.
|
|
* Base only gives those width/height: auto — coverage is a contract (docs/gallery.html) */
|
|
.cbi-button, .btn,
|
|
input[type="button"], input[type="submit"], input[type="reset"] {
|
|
display: inline-flex; align-items: center; justify-content: center;
|
|
/* auto, stated: theme/60-inputs.css's generic input box says 210x32px, a base reset would lose to it by layer */
|
|
width: auto; height: auto;
|
|
min-height: var(--fs-ctl-h);
|
|
padding: var(--fs-space-2) var(--fs-space-3-5);
|
|
font-family: var(--fs-font-sans); font-weight: var(--fs-weight); line-height: 1.1;
|
|
color: var(--fs-text);
|
|
background: var(--fs-panel2);
|
|
border: var(--fs-hairline);
|
|
border-radius: var(--fs-radius);
|
|
box-shadow: none; text-shadow: none;
|
|
/* border-COLOR not the shorthand, which also animates width — a layout animation on every hover */
|
|
transition: var(--fs-field-transition);
|
|
}
|
|
/* bare `button` rides along: harmless on a border:0 box, meaningful once an app gives it one */
|
|
.cbi-button:hover, .btn:hover, button:hover,
|
|
input[type="button"]:hover, input[type="submit"]:hover, input[type="reset"]:hover { border-color: var(--fs-dim); }
|
|
|
|
/* keyboard focus only: box-shadow:none above kills any stray glow, plain mouse :focus shows
|
|
* nothing on purpose — the pressed cue below already answers a click */
|
|
.cbi-button:focus-visible, .btn:focus-visible,
|
|
input[type="button"]:focus-visible, input[type="submit"]:focus-visible, input[type="reset"]:focus-visible {
|
|
outline: none;
|
|
border-color: var(--fs-accent);
|
|
box-shadow: var(--fs-focus-ring);
|
|
}
|
|
/* solid variants sit ON --fs-accent/-good/-danger, an accent-tinted ring is invisible against
|
|
* them — ring in the surface colour with a solid accent halo (--fs-focus-ring-solo) instead */
|
|
.cbi-button-positive:focus-visible, .cbi-button-action:focus-visible,
|
|
.cbi-button-negative:focus-visible, .cbi-button-remove:focus-visible,
|
|
.cbi-button-apply:focus-visible, .cbi-button-save:focus-visible,
|
|
.btn.primary:focus-visible, .btn.danger:focus-visible,
|
|
.btn.error:focus-visible, .btn.success:focus-visible, .btn.info:focus-visible {
|
|
outline: none;
|
|
border-color: transparent;
|
|
box-shadow: var(--fs-focus-ring-solo);
|
|
}
|
|
|
|
/* the sole copy of the pressed inset shadow (base's identical one was absorbed) */
|
|
.cbi-button:active, .btn:active, .btn.active,
|
|
input[type="button"]:active, input[type="submit"]:active, input[type="reset"]:active {
|
|
box-shadow: inset 0 2px 4px color-mix(in srgb, var(--fs-border) 40%, transparent);
|
|
}
|
|
|
|
/* three fills, each shared by `.cbi-button-*` (LuCI's own views) and `.btn.<colour-word>` (third-party
|
|
* apps), or a recolour lands on one half and not the other.
|
|
* The `.important` twins are needed: at 0,2,0 they beat the neutral `input[type=button]` paint (0,1,1)
|
|
* for dockerman's `<input type=button class="cbi-button-action important">`. */
|
|
.cbi-button-positive, .btn.success {
|
|
background: var(--fs-good); border-color: transparent; color: var(--fs-on-good);
|
|
}
|
|
.cbi-button-action, .cbi-button-action.important, .btn.primary, .btn.info {
|
|
background: var(--fs-accent); border-color: transparent; color: var(--fs-on-accent);
|
|
}
|
|
.cbi-button-negative, .cbi-button-negative.important, .cbi-button-remove,
|
|
.btn.danger, .btn.error {
|
|
background: var(--fs-danger); border-color: transparent; color: var(--fs-on-danger);
|
|
}
|
|
/* the lift is for the fills above plus the page-action Save & Apply: brightness deepens a solid
|
|
* fill and washes out an outline or a tint, so neutral Apply/Save keep their hairline.
|
|
* `.td .cbi-button-apply` is the one outline that does lift. */
|
|
.cbi-button-positive:hover, .btn.success:hover,
|
|
.cbi-button-action:hover, .btn.primary:hover, .btn.info:hover,
|
|
.cbi-button-negative:hover, .cbi-button-remove:hover, .btn.danger:hover, .btn.error:hover,
|
|
.cbi-page-actions .cbi-button-apply:hover, .td .cbi-button-apply:hover {
|
|
filter: var(--fs-hover-lift); border-color: transparent;
|
|
}
|
|
.cbi-button-reset, .cbi-button-link { background: transparent; border-color: var(--fs-border); color: var(--fs-dim); }
|
|
|
|
/* .btn owns size words in full now: the plain rule above re-sets padding in a later
|
|
* layer, so a size word carrying only font-size (base's old copy) got default padding */
|
|
.btn.large { font-size: var(--fs-type-lg); min-height: var(--fs-ctl-h-lg); padding: var(--fs-space-2) var(--fs-space-4); }
|
|
.btn.small { font-size: var(--fs-type-xs); min-height: var(--fs-ctl-h-sm); padding: var(--fs-space-1) var(--fs-space-2-5); border-radius: var(--fs-radius-sm); }
|
|
|
|
.cbi-section .table[id] .td .btn,
|
|
.cbi-section .table[id] .td .cbi-button { padding: var(--fs-space-1) var(--fs-space-2-5); font-size: var(--fs-type); }
|
|
/* size only: ui.changes puts .alert-message on the apply/rollback modal itself, so a paint here
|
|
* (0,2,0, after the fills) turned 'Apply unchecked' into the same panel2 grey as 'Cancel' */
|
|
.alert-message .btn, .alert-message .cbi-button {
|
|
border-radius: var(--fs-radius); padding: var(--fs-space-2) var(--fs-space-3);
|
|
}
|
|
.alert-message .btn:not(.cbi-button-positive, .cbi-button-action, .cbi-button-negative, .cbi-button-remove,
|
|
.primary, .info, .success, .danger, .error):hover { border-color: var(--fs-accent); color: var(--fs-accent); }
|
|
|
|
/* Save/Apply footer: base renders a tall half-empty plate with bottom-only radius, made a compact rounded bar */
|
|
.cbi-page-actions {
|
|
background: transparent;
|
|
border: 0;
|
|
border-radius: 0;
|
|
box-shadow: none;
|
|
padding: var(--fs-space-2) 0;
|
|
margin: 0 0 var(--fs-card-gap);
|
|
text-align: end;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
gap: var(--fs-space-2);
|
|
/* WRAP the bar rather than let items shrink into it: a no-wrap row put the whole squeeze on
|
|
* the Save & Apply split control's caption (measured up to 119px cut at 320px/Large) instead
|
|
* of sharing it — docs/css.md "Buttons: the page-action bar wraps, not shrinks" has the
|
|
* before/after numbers. */
|
|
flex-wrap: wrap;
|
|
}
|
|
.cbi-page-actions .cbi-button,
|
|
.cbi-page-actions .btn {
|
|
min-height: var(--fs-ctl-h);
|
|
padding: 0 var(--fs-space-5);
|
|
border-radius: var(--fs-radius);
|
|
font-weight: var(--fs-weight);
|
|
vertical-align: middle;
|
|
}
|
|
/* Reset takes Save's same ladder step (-soft/-fill) off the DANGER role, since it discards
|
|
* unsaved changes; label is --fs-text for the same over-tint reason as Save's below. */
|
|
.cbi-page-actions .cbi-button-reset {
|
|
background: var(--fs-danger-soft);
|
|
border: 1px solid var(--fs-danger-line);
|
|
color: var(--fs-text);
|
|
}
|
|
.cbi-page-actions .cbi-button-reset:hover {
|
|
background: var(--fs-danger-fill);
|
|
border-color: var(--fs-danger-line-hi);
|
|
}
|
|
|
|
/* no `.spinning` padding ladder here, and it must not come back — base/95-luci.css puts the
|
|
* glyph IN THE FLOW instead, reserving its own space (the ladder lost twice: issues #15, #22) */
|
|
|
|
input[type="file"]::file-selector-button {
|
|
margin-inline-end: var(--fs-space-3); padding: var(--fs-space-2) var(--fs-space-3-5);
|
|
font-family: var(--fs-font-sans); font-size: var(--fs-type); font-weight: var(--fs-weight);
|
|
color: var(--fs-text); background: var(--fs-panel2);
|
|
border: var(--fs-hairline); border-radius: var(--fs-radius-sm); cursor: pointer;
|
|
}
|
|
input[type="file"]::file-selector-button:hover { border-color: var(--fs-accent); color: var(--fs-accent); }
|
|
|
|
/* row-action buttons (Edit/Delete/Start-Stop): neutral outline, variants colour the ones that
|
|
* carry meaning. Neutral :hover comes FIRST — after it, it would grey the coloured variants
|
|
* back out on hover at equal specificity. 32px clears WCAG 2.5.8's 24px target/spacing rule;
|
|
* 28px did not (adjacent 24px circles overlapped). */
|
|
.cbi-section-actions .cbi-button, .cbi-section-actions .btn,
|
|
.cbi-section-table .cbi-button {
|
|
min-height: var(--fs-ctl-h-sm); padding: 0 var(--fs-space-3); font-size: var(--fs-type);
|
|
/* flex-basis: auto, not a definite basis: with one, the automatic minimum resolves to 0 in
|
|
* every row and flex-grow divides by count instead of by need — docs/css.md "Buttons:
|
|
* `flex-basis: auto`, not the definite basis base gave every row action" has the
|
|
* regression this fixed and the measured widths before/after. */
|
|
flex-basis: auto;
|
|
}
|
|
/* a ComboButton is a widget: its open list is a child of the box, and its label ellipsizes in its own <li> */
|
|
:is(.cbi-section-actions .cbi-button, .cbi-section-actions .btn, .cbi-section-table .cbi-button):not(.cbi-dropdown) {
|
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
}
|
|
.td .cbi-button, .cbi-section-actions .cbi-button, .cbi-section-table .cbi-button {
|
|
background: transparent;
|
|
border: var(--fs-hairline); color: var(--fs-dim);
|
|
}
|
|
.td .cbi-button:hover { border-color: var(--fs-dim); color: var(--fs-text); }
|
|
|
|
.td .cbi-button-action, .td .cbi-button-edit, .td .cbi-button-apply,
|
|
.cbi-section-actions .cbi-button-edit, .cbi-section-actions .cbi-button-action {
|
|
color: var(--fs-accent); border-color: var(--fs-accent-line); background: transparent;
|
|
}
|
|
/* hover ink is --fs-text, not the role colour: text of colour C on a tint of C eats its own
|
|
* contrast (Save: accent on accent-soft = 4.25:1, AA fail) — role reads from fill + border */
|
|
.td .cbi-button-action:hover, .td .cbi-button-edit:hover, .td .cbi-button-apply:hover,
|
|
.cbi-section-actions .cbi-button-action:hover {
|
|
background: var(--fs-accent-soft); color: var(--fs-text);
|
|
border-color: var(--fs-accent-line-hi);
|
|
}
|
|
/* an enabled/positive toggle in a table cell (System -> Startup) rendered blue text on a green fill = unreadable; green outline instead */
|
|
.td .cbi-button-positive, .cbi-section-actions .cbi-button-positive {
|
|
color: var(--fs-good); border-color: var(--fs-good-line); background: transparent;
|
|
}
|
|
/* without this border-colour the positive toggle read less responsive than its hover neighbours (which brighten to -line-hi) */
|
|
.td .cbi-button-positive:hover, .cbi-section-actions .cbi-button-positive:hover {
|
|
background: var(--fs-good-soft); color: var(--fs-text);
|
|
border-color: var(--fs-good-line-hi);
|
|
}
|
|
.td .cbi-button-negative, .td .cbi-button-remove,
|
|
.cbi-section-actions .cbi-button-remove, .cbi-section-actions .cbi-button-negative {
|
|
color: var(--fs-danger); border-color: var(--fs-danger-line); background: transparent;
|
|
}
|
|
.td .cbi-button-negative:hover, .td .cbi-button-remove:hover,
|
|
.cbi-section-actions .cbi-button-negative:hover {
|
|
background: var(--fs-danger-soft); color: var(--fs-text);
|
|
border-color: var(--fs-danger-line-hi);
|
|
}
|
|
|
|
/* Save & Apply is THE primary action, Save demoted so only one reads primary */
|
|
.cbi-page-actions .cbi-button-apply,
|
|
.cbi-page-actions .cbi-dropdown .cbi-button-apply {
|
|
background: var(--fs-accent);
|
|
border: 1px solid transparent;
|
|
color: var(--fs-on-accent);
|
|
text-shadow: none;
|
|
}
|
|
/* a TINT at rest, not a bare outline, or Save reads disabled beside the solid Save & Apply;
|
|
* -soft/-fill off the role ladder. Label --fs-text, not --fs-accent: accent on accent-soft
|
|
* measures 4.25:1, an AA failure (docs/design-system.md). */
|
|
.cbi-page-actions .cbi-button-save,
|
|
.cbi-page-actions .cbi-button-apply + .cbi-button-save,
|
|
.cbi-page-actions .cbi-button-negative + .cbi-button-save {
|
|
background: var(--fs-accent-soft);
|
|
border: 1px solid var(--fs-accent-line);
|
|
color: var(--fs-text);
|
|
text-shadow: none;
|
|
}
|
|
.cbi-page-actions .cbi-button-save:hover {
|
|
background: var(--fs-accent-fill);
|
|
border-color: var(--fs-accent-line-hi);
|
|
}
|
|
|
|
/* buttons that are part of a compound field widget */
|
|
.cbi-dynlist > .add-item > button,
|
|
.cbi-dynlist > .add-item > .cbi-button-add {
|
|
/* min-width was a bare 38px, the number --fs-ctl-h already states — a restated value is the drift this ladder exists to prevent */
|
|
flex: 0 0 auto; width: auto; min-width: var(--fs-ctl-h);
|
|
min-height: var(--fs-ctl-h-sm); padding: 0 var(--fs-space-3); margin: 0;
|
|
border: 0; border-inline-start: var(--fs-hairline);
|
|
border-radius: 0;
|
|
background: transparent; color: var(--fs-dim);
|
|
}
|
|
.cbi-dynlist > .add-item > button:hover,
|
|
.cbi-dynlist > .add-item > .cbi-button-add:hover { color: var(--fs-accent); }
|
|
.control-group:has(> .cbi-input-password) > button.cbi-button-neutral {
|
|
border: 0; border-radius: 0; margin: 0;
|
|
background: transparent; color: var(--fs-dim);
|
|
padding: 0 var(--fs-space-3); min-height: var(--fs-ctl-h);
|
|
border-inline-start: var(--fs-hairline);
|
|
}
|
|
.control-group:has(> .cbi-input-password) > button.cbi-button-neutral:hover { color: var(--fs-accent); }
|
|
/* SQUARE, ON THE LADDER: the only buttons once set in bare pixels (40x34, 34 being a height in
|
|
* no scale) and opted out of the Density axis; square because the glyph is an arrow, not a label */
|
|
.pager .btn.prev, .pager .btn.next {
|
|
flex: 0 0 auto; width: var(--fs-ctl-h); min-width: var(--fs-ctl-h); height: var(--fs-ctl-h); padding: 0;
|
|
border: var(--fs-hairline);
|
|
}
|
|
.pager .btn.prev:hover, .pager .btn.next:hover { border-color: var(--fs-accent); color: var(--fs-accent); }
|
|
}
|