mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-09-11 02:44:57 +08:00
258 lines
8.1 KiB
CSS
258 lines
8.1 KiB
CSS
@layer base {
|
||
/* Forms: input types, the .cbi-value row layout, and the focus/disabled/
|
||
* readonly/invalid states shared by every CBI widget. */
|
||
fieldset {
|
||
margin-bottom: var(--fs-space-2);
|
||
padding-top: var(--fs-space-2);
|
||
}
|
||
|
||
/* size: theme/30-tables.css (`legend`) — absorbed */
|
||
fieldset legend {
|
||
display: block;
|
||
line-height: 1;
|
||
color: var(--fs-text);
|
||
padding-top: var(--fs-space-5);
|
||
}
|
||
|
||
/* Control typography stays in BASE: moved to the theme layer, a bare-element rule out-ranks
|
||
* every classed base refinement regardless of specificity, and the firewall's zone badges grew
|
||
* from 10.8 to 13px. In base, classed rules beat it on specificity, which is the contract they
|
||
* were written against. `select` is not a member — its face, size and leading live in
|
||
* 60-inputs.css. */
|
||
label,
|
||
input,
|
||
button {
|
||
font-family: var(--fs-font-sans);
|
||
font-size: var(--fs-type);
|
||
font-weight: var(--fs-weight-normal);
|
||
line-height: normal;
|
||
}
|
||
|
||
.cbi-value {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
margin-bottom: var(--fs-space-4);
|
||
align-items: baseline;
|
||
}
|
||
|
||
.cbi-value-field {
|
||
/* logical, not margin-left: this is the gap AFTER the label column, and LuCI ships four RTL
|
||
* languages (ar/fa/he/ur). Identical to margin-left while nothing in openwrt/luci stamps
|
||
* dir=rtl, so it costs nothing and is already correct if one ever does. */
|
||
margin-inline-start: var(--fs-space-5);
|
||
flex: 1;
|
||
/* a flex item will not shrink below min-content by default, so a nested table or one long
|
||
* unbreakable value pushes the whole row out of the card */
|
||
min-width: 0;
|
||
}
|
||
|
||
/* size + ink: theme/60-inputs.css (`.cbi-value-title`) — absorbed. Left: the label
|
||
* column's geometry, which theme does not touch. */
|
||
.cbi-value label.cbi-value-title {
|
||
/* the nudge that lands the label's first baseline on the field's, tuned for the unitless
|
||
* leading in 20-typography.css */
|
||
padding-top: var(--fs-space-1);
|
||
/* 180px is a column WIDTH, not a rhythm — what fits LuCI's longest option labels beside a
|
||
* field — so it is deliberately not on the 4px step scale */
|
||
flex: 0 0 180px;
|
||
/* `end`, not `right`: the label is aligned TOWARDS its field, which is a logical intent.
|
||
* Not the same as base/95-luci.css's `.left/.right/.center`, which are LuCI's forcing
|
||
* utilities — a class named `right` means right in any direction. Never sweep those onto
|
||
* start/end. */
|
||
text-align: end;
|
||
}
|
||
|
||
.cbi-value > .cbi-section,
|
||
.cbi-value > .cbi-tblsection {
|
||
width: 100%;
|
||
}
|
||
|
||
label > input[type="checkbox"],
|
||
label > input[type="radio"] {
|
||
vertical-align: text-top;
|
||
margin: 0;
|
||
}
|
||
|
||
label[for] {
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* The shared field box (the 210px x control-height default, #localtime's widening, and the
|
||
* per-widget escapes: file, button types, checkbox/radio, .cbi-select, readonly, the
|
||
* cell-filling widths) lives in theme/60-inputs.css — absorbed whole. The escapes had to move
|
||
* with the box: each beat it here in-layer, and left behind they would lose to a theme rule by
|
||
* layer whatever their specificity. */
|
||
|
||
.cbi-dynlist {
|
||
height: auto;
|
||
/* min-height: theme/60-inputs.css — absorbed */
|
||
display: inline-flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* item paint: theme/60-inputs.css — absorbed. Left: the drag-and-drop machinery
|
||
* UIDynamicList needs. */
|
||
.cbi-dynlist > .item {
|
||
margin-bottom: var(--fs-space-1);
|
||
padding: var(--fs-space-1) 2em var(--fs-space-1) var(--fs-space-2);
|
||
position: relative;
|
||
pointer-events: auto; /* needed for drag-and-drop in UIDynamicList */
|
||
overflow: hidden;
|
||
word-break: break-all;
|
||
cursor: move; /* drag-and-drop */
|
||
user-select: text; /* text selection in drag-and-drop */
|
||
}
|
||
|
||
/* display/padding/border + radius + × ink: theme/60-inputs.css (the bare `.item::after`
|
||
* plate + its dynlist refinement) — absorbed. Left: what pins the plate to the chip. */
|
||
.cbi-dynlist > .item::after {
|
||
content: "×";
|
||
position: absolute;
|
||
align-items: center;
|
||
top: -1px;
|
||
inset-inline-end: -1px;
|
||
bottom: -1px;
|
||
font-weight: var(--fs-weight-bold);
|
||
pointer-events: auto;
|
||
}
|
||
|
||
/* indication line for drag-and-drop in UIDynamicList*/
|
||
.cbi-dynlist > .item.drag-over {
|
||
border-top: 1px solid var(--fs-text);
|
||
}
|
||
|
||
/* Make item being dragged in UIDynamicList partially transparent*/
|
||
.cbi-dynlist > .item.dragging {
|
||
opacity: .5;
|
||
}
|
||
|
||
/* prevent pointer changing when over the span element in UIDynamicList */
|
||
.cbi-dynlist > .item > span {
|
||
pointer-events: none;
|
||
}
|
||
|
||
.cbi-dynlist > .add-item {
|
||
display: flex;
|
||
}
|
||
|
||
/* indication line for drag-and-drop in UIDynamicList*/
|
||
.cbi-dynlist > .add-item > .cbi-input-text.drag-over {
|
||
border-top: 1px solid var(--fs-text);
|
||
}
|
||
|
||
/* indication line for drag-and-drop in UIDynamicList*/
|
||
.cbi-dynlist > .add-item > .cbi-button-add.drag-over {
|
||
border-top: 1px solid var(--fs-text);
|
||
}
|
||
|
||
.cbi-dynlist > .add-item > input,
|
||
.cbi-dynlist > .add-item > button {
|
||
/* flex: theme/60-inputs.css — absorbed */
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* the same one-line control height, so a toggle lines up with the field above it */
|
||
.cbi-value-field > .cbi-checkbox,
|
||
.cbi-value-field > div > .cbi-radio {
|
||
height: var(--fs-control-h);
|
||
display: inline-flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.cbi-radio {
|
||
cursor: pointer;
|
||
gap: var(--fs-space-1);
|
||
}
|
||
|
||
/* .cbi-select lives in theme/60-inputs.css — absorbed whole. Do not re-add an option rule here
|
||
* either: layer beats specificity, so theme's bare `option` outranks even
|
||
* `.cbi-select select option:checked`. */
|
||
|
||
/* Checkbox/radio drawing: theme/60-inputs.css — absorbed whole (it undoes the generic input
|
||
* box, which lives there now). */
|
||
|
||
::placeholder {
|
||
color: var(--fs-dim);
|
||
}
|
||
|
||
/* Transitions and the focus/hover ring are the theme's one ring token (--fs-focus-ring /
|
||
* --fs-focus-ring-invalid). A generic glow here rings every clicked button and every hovered
|
||
* widget in a second, unnamed focus style. */
|
||
|
||
input[disabled],
|
||
button[disabled],
|
||
select[disabled],
|
||
textarea[disabled],
|
||
.cbi-dropdown[disabled]:not(.btn):not(.cbi-button),
|
||
input[type="checkbox"][disabled]::before,
|
||
input[type="checkbox"][disabled]::after,
|
||
input[type="radio"][disabled]::before,
|
||
input[type="radio"][disabled]::after {
|
||
opacity: var(--fs-disabled-opacity);
|
||
pointer-events: none;
|
||
cursor: default;
|
||
}
|
||
|
||
/* readonly border fade: theme/60-inputs.css — absorbed with the generic box */
|
||
|
||
.cbi-optionals,
|
||
.cbi-section-create {
|
||
padding: 0 0 var(--fs-space-3) var(--fs-space-3);
|
||
}
|
||
|
||
/* `gap`, not a negative-margin pair: that trick predates flex gap and leaks, the outer -3px
|
||
* pulling the row into whatever sits beside it */
|
||
.cbi-section-create {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: var(--fs-space-2);
|
||
}
|
||
|
||
.cbi-section-create > * {
|
||
flex: 1 1 auto;
|
||
}
|
||
|
||
/* the input's cell-filling width: theme/60-inputs.css — absorbed with the generic box */
|
||
|
||
/* .cbi-page-actions paint: theme/55-buttons.css — absorbed. The legacy `.actions` plate has no
|
||
* theme override, so it stays: some luci-app-* still emits it. */
|
||
.actions {
|
||
background: var(--fs-panel2);
|
||
margin-bottom: var(--fs-space-4);
|
||
/* a plate, so it takes the card's own gutter on every side */
|
||
padding: var(--fs-card-pad);
|
||
border-top: var(--fs-hairline);
|
||
border-radius: 0 0 var(--fs-radius-lg) var(--fs-radius-lg);
|
||
text-align: end;
|
||
}
|
||
|
||
/* Physical, mirrored by hand — see `.close` in base/90-widgets.css for why `float` takes no
|
||
* logical keyword. Unmirrored it contradicts its own container: `.actions` above sets
|
||
* `text-align: end`, which follows the writing direction, so in RTL the plate aligns its
|
||
* content one way and the secondary action the other. Measured in a live document at 1400px:
|
||
* 582px from the reading edge in LTR, 10px in RTL. */
|
||
.actions .secondary-action,
|
||
.cbi-page-actions .secondary-action{
|
||
float: right;
|
||
}
|
||
:root[dir="rtl"] .actions .secondary-action,
|
||
:root[dir="rtl"] .cbi-page-actions .secondary-action { float: left; }
|
||
|
||
.actions .secondary-action a,
|
||
.cbi-page-actions .secondary-action a {
|
||
line-height: var(--fs-control-h);
|
||
}
|
||
|
||
.actions .secondary-action a:hover,
|
||
.cbi-page-actions .secondary-action a:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.cbi-page-actions > form {
|
||
display: inline;
|
||
margin: 0;
|
||
}
|
||
}
|