Files
olivv-cs-ComfyUI-FunPack/app/composer/elements/button.css
T
digital-garbageandClaude Opus 5 9dcd94c156 app, core: a project of scenes, and the timeline that draws it
The app could run a pipeline and had nowhere to keep what it was making. A
project is an ordered list of scenes, one JSON file each, and it is the only
part of the app that has to survive a reload.

A scene owns its prompt text and the result it produced, and nothing else. v4's
Scene grew three dozen fields; each belongs to the feature that needs it. Per
scene length and fps are deliberately absent — a regenerate uses the project's
values, so a scene cropped on the timeline comes back whole.

The prompt box edits the current scene rather than holding its own copy, so
what is on screen and what a run uses cannot disagree.

app: the region toggles are named buttons in the timeline bar

v4's arrangement. The kit's fallback is one glyph on a rail at each edge of the
window, which is right for a kit that cannot know what its panels are called and
wrong here, where they have names and a bar to put them in.

A pressed toggle was styled only inside a button group, so a standalone one
carried aria-pressed and looked identical either way.

gallery.strip is selectable like its siblings: a filmstrip is the one shape
whose whole job is saying which of these you are on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 12:03:19 +03:00

80 lines
4.3 KiB
CSS

.cx-btn {
display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
border: var(--bw) solid var(--line); border-radius: var(--ctl-r);
background: var(--grad-raise); color: var(--text);
font-family: var(--font-ui); font-weight: var(--fw-medium);
white-space: nowrap; cursor: pointer;
transition: background var(--dur-1) var(--ease-standard),
border-color var(--dur-1) var(--ease-standard),
color var(--dur-1) var(--ease-standard);
}
.cx-btn-xl { height: var(--ctl-h-xl); padding: 0 var(--ctl-pad-x-xl); font-size: var(--fs-4); }
.cx-btn-lg { height: var(--ctl-h-lg); padding: 0 var(--ctl-pad-x-lg); font-size: var(--fs-5); }
.cx-btn-md { height: var(--ctl-h-md); padding: 0 var(--ctl-pad-x-md); font-size: var(--fs-5); }
.cx-btn-sm { height: var(--ctl-h-sm); padding: 0 var(--ctl-pad-x-sm); font-size: var(--fs-6); }
.cx-btn:hover:not(:disabled) { border-color: var(--line-hover); background: var(--hover); }
.cx-btn:active:not(:disabled) { border-color: var(--line-active); }
.cx-btn:disabled { opacity: var(--disabled-opacity); cursor: default; }
.cx-btn-primary {
background: var(--grad-accent); border-color: var(--accent);
color: var(--on-accent); font-weight: var(--fw-bold);
box-shadow: var(--glow-accent);
}
/* The SURFACE brightens, not the button.
`filter: brightness()` applies to the whole element, text included -- so the
label was lightened along with the fill under it and the one thing that had
to stay readable lost contrast in both themes. The label's colour is fixed
and only the fill moves, one step up the same accent ramp. */
.cx-btn-primary:hover:not(:disabled) {
background: var(--grad-accent-hover); border-color: var(--accent-hover-edge);
}
.cx-btn-primary:active:not(:disabled) { background: var(--accent-lo); }
.cx-btn-danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 30%, var(--line)); }
.cx-btn-danger:hover:not(:disabled) { background: color-mix(in srgb, var(--danger) 12%, transparent); border-color: var(--danger); }
.cx-btn-ghost { background: transparent; border-color: transparent; color: var(--muted); }
.cx-btn-ghost:hover:not(:disabled) { background: var(--hover); color: var(--text); }
.cx-btn-icon { line-height: 1; }
.cx-btn-label:empty { display: none; }
.cx-icon-btn {
display: inline-flex; align-items: center; justify-content: center;
border: var(--bw) solid transparent; border-radius: var(--r-2);
background: transparent; color: var(--muted); cursor: pointer; padding: 0;
transition: background var(--dur-1) var(--ease-standard), color var(--dur-1) var(--ease-standard);
}
.cx-icon-btn-md { width: var(--ctl-h-md); height: var(--ctl-h-md); font-size: var(--fs-4); }
.cx-icon-btn-sm { width: var(--ctl-h-icon); height: var(--ctl-h-icon); font-size: var(--fs-6); }
.cx-icon-btn-micro { width: var(--ctl-h-icon-sm); height: var(--ctl-h-icon-sm); font-size: var(--fs-7); }
.cx-icon-btn:hover:not(:disabled) { background: var(--hover); color: var(--text); }
.cx-icon-btn[aria-pressed="true"] { color: var(--accent); background: var(--accent-soft); }
.cx-icon-btn:disabled { opacity: var(--disabled-opacity); cursor: default; }
.cx-btn-group { display: inline-flex; }
.cx-btn-group .cx-btn { border-radius: 0; margin-left: calc(var(--bw) * -1); }
.cx-btn-group .cx-btn:first-child { border-radius: var(--ctl-r) 0 0 var(--ctl-r); margin-left: 0; }
.cx-btn-group .cx-btn:last-child { border-radius: 0 var(--ctl-r) var(--ctl-r) 0; }
.cx-btn-group .cx-btn:only-child { border-radius: var(--ctl-r); }
/* A pressed toggle, grouped or not. Scoping this to .cx-btn-group meant a
standalone toggle -- the region buttons in the timeline bar -- carried
aria-pressed and looked identical either way: a control that reports its state
to a screen reader and not to the eye. */
.cx-btn.cx-on {
background: var(--accent-soft); border-color: var(--accent); color: var(--accent-hi);
}
.cx-btn-group .cx-btn.cx-on {
position: relative; z-index: 1; /* its border wins over its neighbours' */
}
.cx-btn-spin {
width: 11px; height: 11px; border-radius: var(--r-pill);
border: 2px solid color-mix(in srgb, currentColor 30%, transparent);
border-top-color: currentColor;
animation: cx-spin 800ms linear infinite;
}
@keyframes cx-spin { to { transform: rotate(360deg); } }