Files
olivv-cs-ComfyUI-FunPack/app/composer/elements/input.css
T
digital-garbage 739a720adc app, core: Settings matches v4 -- retractable rail, fixed frame, real About
Three things the unified Settings window was still missing next to v4's
own, all found by looking at it next to v4 rather than in isolation:

- The sidebar is a 52px icon rail now, expanding to a full list on
  hover/focus and overlaying the content instead of a splitPane's
  permanently-docked two-pane shape -- v4's own sidebar, not an
  approximation of it. Fixing this surfaced two real CSS bugs along the
  way: filterList's own min-width:220px silently defeated the collapse
  (clipping the search box to "Sear" instead of showing an icon), and
  .cx-filter-list's unset overflow-x (computed to auto once overflow-y
  was set) put a horizontal scrollbar under it. Centering the icon in
  the collapsed row needed the label's flex-basis AND the row's own gap
  to both go to zero -- an invisible label still claims its share of
  both otherwise, and the icon renders off-centre.
- The modal now has a real height (v4's own 660px) rather than sizing to
  whichever section is showing, so switching between a short section
  (About) and a long one (Node packs) doesn't visibly resize the whole
  window. That exposed a THIRD latent bug: .cx-modal-body never had
  flex:1 1 auto, invisible until a modal had a real height to fill --
  every prior modal shrink-wrapped its content, so head+body+foot always
  summed to exactly the card's height by accident. Fixed at the shared
  rule, not just for Settings.
- About now shows what v4's does: commit and dirty state, a codename
  when the checkout has one, and the machine's real hardware/software
  facts (chip, memory, GPU or MPS, disk, OS, ComfyUI/Python/Torch/
  attention-backend versions, hostname) -- a new core/sysinfo.py
  (ported from v4's own, individually guarded so a missing probe never
  takes the panel down) behind a new GET /funpack/api/system, injected
  into settings_window.js the same way every other network call here is.

Also: a nav row's tone (the coloured icon chip) is now validated against
its closed set the same way button.js already validates its own tone --
an unknown one used to render silently wrong instead of failing loudly.
2026-09-07 13:47:18 +03:00

152 lines
8.3 KiB
CSS

.cx-input, .cx-textarea, .cx-select {
width: 100%;
border: var(--bw) solid var(--line); border-radius: var(--ctl-r);
background: var(--elev-2); color: var(--text);
font-family: var(--font-ui);
transition: border-color var(--dur-1) var(--ease-standard);
}
.cx-input-md { height: var(--ctl-h-lg); padding: 0 var(--ctl-pad-x-md); font-size: var(--fs-4); }
.cx-input-sm { height: var(--ctl-h-md); padding: 0 var(--ctl-pad-x-sm); font-size: var(--fs-5); }
.cx-input:hover:not(:disabled), .cx-textarea:hover:not(:disabled) { border-color: var(--line-hover); }
.cx-input:disabled, .cx-textarea:disabled, .cx-select:disabled { opacity: var(--disabled-opacity); }
.cx-input::placeholder, .cx-textarea::placeholder { color: var(--faint); }
.cx-number { font-variant-numeric: tabular-nums; }
.cx-number-wrap { display: inline-flex; align-items: center; gap: var(--sp-2); width: 100%; }
.cx-unit { font-size: var(--fs-6); color: var(--muted); }
.cx-stepper { display: inline-flex; align-items: stretch; gap: var(--sp-1); }
.cx-stepper .cx-number { text-align: center; }
.cx-step-btn {
width: var(--ctl-h-lg); height: var(--ctl-h-lg); flex: none;
border: var(--bw) solid var(--line); border-radius: var(--ctl-r);
background: var(--elev-2); color: var(--muted);
font-size: var(--fs-4); line-height: 1; cursor: pointer;
}
.cx-step-btn:hover { border-color: var(--line-hover); color: var(--text); }
.cx-textarea {
padding: var(--sp-3) var(--ctl-pad-x-md);
font-size: var(--fs-4); line-height: var(--lh-snug);
resize: vertical; min-height: var(--ctl-h-xl);
}
.cx-autogrow { resize: none; overflow: hidden; }
.cx-search { appearance: none; }
.cx-search::-webkit-search-cancel-button { filter: grayscale(1) opacity(.6); }
.cx-filter { display: flex; flex-direction: column; gap: var(--sp-3); min-width: 220px; }
.cx-filter-list {
display: flex; flex-direction: column; gap: 1px;
max-height: 240px; overflow-y: auto; overflow-x: hidden;
border: var(--bw) solid var(--line); border-radius: var(--r-3);
background: var(--elev-1); padding: var(--sp-1);
}
.cx-filter-row {
display: flex; align-items: center; gap: var(--sp-3);
padding: var(--sp-3) var(--sp-4); border: 0; border-radius: var(--r-2);
background: transparent; color: var(--text);
font-size: var(--fs-5); text-align: left; cursor: pointer; width: 100%;
}
.cx-filter-row:hover { background: var(--hover); }
.cx-filter-row.cx-on { background: var(--accent-soft); color: var(--accent-hi); }
.cx-filter-row.cx-on .cx-filter-label { font-weight: var(--fw-semibold); }
/* A column so a wrapping hint sits directly under its own label, both flush
to the same left edge, instead of floating as a baseline-aligned sibling
of the icon and the label. Centred on the icon: with the hint gone (a
nav row now, not a compact picker's two-line entry) top-aligning the two
just looks like a mistake. */
.cx-filter-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; justify-content: center; }
.cx-filter-label { display: block; }
.cx-filter-hint { display: block; font-size: var(--fs-7); color: var(--muted); line-height: var(--lh-snug); }
.cx-filter-empty { padding: var(--sp-5); font-size: var(--fs-6); color: var(--faint); text-align: center; }
/* A chip, not a bare glyph floating in the row -- the thing a nav list reads
as unfinished without. `tone` is a closed set of pre-approved looks
(accent/danger/warn/good/neutral), the same rule as everywhere else in the
kit; there is no path from item data to a raw colour. */
.cx-filter-icon {
display: inline-flex; align-items: center; justify-content: center;
width: 22px; height: 22px; flex: 0 0 auto; border-radius: var(--r-2);
background: var(--elev-3); color: var(--text); font-size: var(--fs-6); line-height: 1;
/* Optical, against the label's cap-height, not the row's own top edge. */
margin-block-start: 1px;
}
.cx-filter-icon-accent { background: var(--grad-accent); color: var(--on-accent); }
.cx-filter-icon-danger { background: linear-gradient(180deg, var(--danger), color-mix(in srgb, var(--danger) 65%, black)); color: #fff; }
.cx-filter-icon-warn { background: linear-gradient(180deg, var(--warn), color-mix(in srgb, var(--warn) 65%, black)); color: #fff; }
.cx-filter-icon-good { background: linear-gradient(180deg, var(--good), color-mix(in srgb, var(--good) 65%, black)); color: #fff; }
.cx-filter-icon-neutral { background: linear-gradient(180deg, var(--muted), color-mix(in srgb, var(--muted) 65%, black)); color: #fff; }
.cx-filter-row.cx-on .cx-filter-icon { box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent-hi) 50%, transparent); }
/* The Settings sidebar: a 52px icon rail by default, expanding to a full list
on hover or keyboard focus and OVERLAYING the content rather than pushing
it -- v4's own sidebar, and the reason nothing here uses splitPane's
resizable two-pane shape: this one is not meant to stay open. */
.cx-settings-body { position: relative; min-block-size: 0; block-size: 100%; }
.cx-settings-rail {
position: absolute; inset-block: 0; inset-inline-start: 0; z-index: 2;
/* .cx-filter's own min-width:220px is a floor for its NORMAL (small,
always-220px-ish) role; here it would keep this element from ever
actually reaching 52px regardless of inline-size below, since min-width
always wins over a smaller width -- the search box then rendered at its
un-shrunk content width and this clipped it to "Sear", not an icon. */
min-inline-size: 52px; inline-size: 52px; overflow: hidden;
background: var(--elev-2); border-inline-end: var(--bw) solid var(--line);
transition: inline-size var(--dur-2) var(--ease-standard),
box-shadow var(--dur-2) var(--ease-standard);
}
.cx-settings-rail:hover, .cx-settings-rail:focus-within {
inline-size: 218px;
box-shadow: 18px 0 40px -18px color-mix(in srgb, var(--shadow-ink) 80%, transparent);
}
/* The label, and the search box's placeholder -- the icon chip stays put so
the collapsed rail still says something, the way a dock of icons does.
The label's WIDTH collapses too, not just its opacity: an invisible label
still claiming its flex share left the icon sitting off-centre with dead
space after it, rather than centred in the icon-only rail. */
.cx-settings-rail .cx-filter-text {
flex: 0 1 0; inline-size: 0; overflow: hidden;
transition: flex-basis var(--dur-2) var(--ease-standard);
}
.cx-settings-rail .cx-filter-row {
justify-content: center;
/* The row's own gap still opens a space before a zero-width label -- two
flex items with nothing between them still get one gap's worth of
nothing, which shifted the centred GROUP (icon + gap) off the icon. */
gap: 0;
}
.cx-settings-rail .cx-filter-label {
opacity: 0; transition: opacity var(--dur-1) var(--ease-standard); white-space: nowrap;
}
.cx-settings-rail .cx-search::placeholder {
opacity: 0; transition: opacity var(--dur-1) var(--ease-standard);
}
.cx-settings-rail:hover .cx-search::placeholder,
.cx-settings-rail:focus-within .cx-search::placeholder { opacity: 1; }
.cx-settings-rail:hover .cx-filter-label, .cx-settings-rail:focus-within .cx-filter-label { opacity: 1; }
.cx-settings-rail:hover .cx-filter-text, .cx-settings-rail:focus-within .cx-filter-text {
flex: 1 1 auto; inline-size: auto;
}
.cx-settings-rail:hover .cx-filter-row, .cx-settings-rail:focus-within .cx-filter-row {
justify-content: flex-start; gap: var(--sp-3);
}
.cx-settings-content {
/* The rail's own right edge, plus real breathing room from the scale --
flush against it read as a layout bug, not a deliberate two regions
meeting. sp-8, not the gutter (sp-5): the gutter is for regions that
border each other structurally: this is content clearing an overlay. */
margin-inline-start: calc(52px + var(--sp-8)); block-size: 100%; overflow-y: auto; min-inline-size: 0;
}
/* Used as a whole pane (the Settings sidebar) rather than a compact dropdown
list -- the 240px cap and boxed border/background are right for the small
version and wrong for this one, so a host opts in with this class instead
of the base rules changing under every other consumer. */
.cx-filter-full { min-block-size: 0; block-size: 100%; }
.cx-filter-full .cx-filter-list {
max-height: none; flex: 1 1 auto; min-block-size: 0;
border: 0; background: transparent; padding: 0;
}
.cx-filter-full .cx-filter-row { padding: var(--sp-3) var(--sp-3); }