Files
AEmotionStudio-ComfyUI-Magn…/css/info-panel.css
T
Æmotion StudioandClaude Opus 5.5 4b06ee92bb Update the Inspector panel look, navigation and editing
Restyle the panel on ComfyUI palette tokens and drop the built-in themes.
Add a header with Back/Forward, Prev/Next, Focus, Lock and a searchable
Go to node picker, a subgraph/group breadcrumb, and simplified modes:
Follow glass or Float, plus Sticky, Follow selection and Lock to node
(replaces Hold).

Fix widget edits (step2 steps, INT/FLOAT, commit on Enter/blur, undo),
subgraph lookups, orphaned dropdown menus, global arrow-key capture,
the pop-out editor, and remove Google Fonts loading and dead code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 06:47:21 -08:00

814 lines
16 KiB
CSS

/**
* ComfyUI MagnifyGlass - Info Panel CSS
*
* Built on the same ComfyUI tokens as the sidebar (sidebar.css), so the panel follows
* every palette. The toolbar, the menus and the node highlight are appended to body,
* so they take the tokens themselves. Text and accent colours changed in the settings
* arrive on the root as --mg-panel-fg and --mg-panel-accent.
*/
.magnify-info-panel,
.floating-controls,
.node-selector-dropdown,
.custom-dropdown-menu,
#magnify-glass-node-highlight {
--mg-fg: var(--fg-color, #fff);
--mg-muted: color-mix(in srgb, var(--mg-fg) 72%, transparent);
--mg-surface: var(--comfy-menu-bg, #171718);
--mg-stroke: var(--interface-stroke, var(--border-color, #4e4e4e));
--mg-control: var(--secondary-background, var(--comfy-input-bg, #262729));
--mg-control-hover: var(--secondary-background-hover, var(--mg-stroke));
--mg-accent: var(--mg-panel-accent, var(--primary-background, #0b8ce9));
/* The accent as text: the light palette's accent is too pale on its own */
--mg-accent-fg: color-mix(in srgb, var(--mg-accent) 45%, var(--mg-fg));
--mg-ring: var(--mg-fg);
--mg-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
--mg-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.magnify-info-panel {
--mg-fg: var(--mg-panel-fg, var(--fg-color, #fff));
position: absolute;
z-index: 99999;
display: flex;
flex-direction: column;
overflow: hidden;
color: var(--mg-fg);
background: color-mix(in srgb, var(--mg-surface) var(--panel-opacity, 100%), transparent);
border: 1px solid var(--mg-stroke);
border-radius: 0.5rem;
box-shadow: var(--mg-shadow);
line-height: 1.35;
}
.magnify-info-panel.high-contrast-text {
--mg-muted: var(--mg-fg);
}
.magnify-info-panel.high-contrast-text :is(.info-value, input, textarea) {
font-weight: 600;
}
.magnify-info-panel *,
.magnify-info-panel *::before,
.magnify-info-panel *::after,
.floating-controls * {
box-sizing: border-box;
}
.magnify-info-panel :where(button, input, textarea),
.floating-controls :where(button) {
font: inherit;
color: inherit;
}
.magnify-info-panel svg,
.floating-controls svg,
.node-selector-dropdown svg {
flex: none;
width: 1em;
height: 1em;
pointer-events: none;
}
.magnify-info-panel [hidden] {
display: none !important;
}
.magnify-info-panel :focus-visible,
.floating-controls :focus-visible,
.node-selector-dropdown :focus-visible,
.custom-dropdown-menu :focus-visible {
outline: 2px solid var(--mg-ring);
outline-offset: 2px;
}
/* Icon buttons: the toolbar and the header */
.control-btn,
.copy-btn,
.widget-editor-stepper {
display: flex;
flex: none;
align-items: center;
justify-content: center;
width: 2em;
height: 2em;
padding: 0;
border: 0;
border-radius: 0.375rem;
background: transparent;
color: var(--mg-muted);
cursor: pointer;
transition: background-color 120ms var(--mg-ease), color 120ms var(--mg-ease);
}
.control-btn:hover,
.copy-btn:hover,
.widget-editor-stepper:hover {
background: var(--mg-control-hover);
color: var(--mg-fg);
}
.control-btn.active,
.copy-btn.copied {
background: color-mix(in srgb, var(--mg-accent) 18%, transparent);
color: var(--mg-accent-fg);
}
.copy-btn.copied {
opacity: 1;
}
.control-btn:disabled {
background: transparent;
color: var(--mg-muted);
opacity: 0.4;
cursor: not-allowed;
}
/* Toolbar */
.floating-controls {
position: fixed;
z-index: 100000;
gap: 0.125rem;
padding: 0.25rem;
color: var(--mg-fg);
background: var(--mg-surface);
border: 1px solid var(--mg-stroke);
border-radius: 0.5rem;
box-shadow: var(--mg-shadow);
font-size: 0.875rem;
}
.floating-controls.vertical-layout {
flex-direction: column;
}
.controls-divider {
flex: none;
align-self: stretch;
margin: 0.125rem;
background: var(--mg-stroke);
}
.vertical-layout .controls-divider {
height: 1px;
}
.horizontal-layout .controls-divider {
width: 1px;
}
/* Header: the node's identity, then the navigation row and the breadcrumb */
.panel-header {
display: flex;
align-items: center;
gap: 0.25em;
min-height: 2.75em;
padding: 0.25em 0.375em 0.25em 0.75em;
border-bottom: 1px solid var(--mg-stroke);
/* Dragging it floats the panel */
cursor: grab;
touch-action: none;
user-select: none;
}
.magnify-info-panel.is-dragging,
.magnify-info-panel.is-dragging .panel-header {
cursor: grabbing;
}
.magnify-info-panel.is-dragging,
.info-row.draggable .info-label {
user-select: none;
}
.panel-minimized .panel-header {
border-bottom: 0;
}
.header-identity {
display: flex;
flex: 1;
align-items: baseline;
gap: 0.375em;
min-width: 0;
}
.header-title,
.header-badge,
.goto-btn span,
.crumb,
.crumb-group {
min-width: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.header-title {
font-weight: 700;
}
.header-title.is-empty {
color: var(--mg-muted);
font-weight: 600;
}
.header-id {
flex: none;
color: var(--mg-muted);
font-size: 0.875em;
font-variant-numeric: tabular-nums;
}
.header-badge {
padding: 0.125em 0.5em;
border-radius: 1em;
background: var(--mg-control);
color: var(--mg-muted);
font-size: 0.8em;
font-weight: 500;
flex: 0 4 auto;
min-width: 3.5em;
max-width: 40%;
}
.panel-nav {
display: flex;
align-items: center;
gap: 0.125em;
padding: 0.25em 0.375em;
border-bottom: 1px solid var(--mg-stroke);
}
.goto-btn {
display: flex;
flex: 1;
align-items: center;
gap: 0.375em;
min-width: 0;
height: 2em;
margin-left: 0.25em;
padding: 0 0.5em;
border: 1px solid var(--mg-stroke);
border-radius: 0.375rem;
background: var(--mg-control);
color: var(--mg-muted);
cursor: pointer;
}
.goto-btn:hover,
.goto-btn[aria-expanded="true"] {
background: var(--mg-control-hover);
color: var(--mg-fg);
}
.panel-breadcrumb {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.25em 0.375em;
padding: 0.25em 0.75em;
border-bottom: 1px solid var(--mg-stroke);
color: var(--mg-muted);
font-size: 0.875em;
}
.crumb {
max-width: 10em;
}
.crumb[aria-current] {
color: var(--mg-fg);
}
.crumb-group {
max-width: 12em;
padding: 0 0.375em;
border: 1px solid var(--mg-stroke);
border-radius: 0.25rem;
}
.crumb-action {
margin-left: auto;
padding: 0.125em 0.5em;
border: 0;
border-radius: 0.375rem;
background: var(--mg-control);
cursor: pointer;
}
.crumb-action:hover {
background: var(--mg-control-hover);
}
/* Body: the panel's one scroller, capped by the Max Height setting */
.panel-content {
flex: 1 1 auto;
min-height: 0;
max-height: min(var(--panel-max-height, 600px), calc(100vh - 5rem));
overflow-x: hidden;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: var(--mg-stroke) transparent;
}
.panel-minimized :is(.panel-nav, .panel-breadcrumb, .panel-content, .panel-resize) {
display: none;
}
/* Corner handle: Width and Max Height */
.panel-resize {
position: absolute;
right: 0;
bottom: 0;
width: 0.875rem;
height: 0.875rem;
cursor: nwse-resize;
touch-action: none;
}
.panel-resize::after {
content: '';
position: absolute;
right: 3px;
bottom: 3px;
width: 6px;
height: 6px;
border-right: 2px solid var(--mg-muted);
border-bottom: 2px solid var(--mg-muted);
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5em;
padding: 2em 1em;
color: var(--mg-muted);
}
.empty-state-icon {
display: flex;
font-size: 2em;
}
.info-rows {
padding-bottom: 0.375em;
}
/* Rows: label and value side by side */
.info-row {
display: grid;
grid-template-columns: minmax(4.5em, 2fr) minmax(0, 3fr) auto;
align-items: baseline;
column-gap: 0.75em;
min-height: 2em;
padding: 0.25em 0.75em;
}
.info-label {
grid-area: 1 / 1;
min-width: 0;
/* Widget names break after their underscores */
overflow-wrap: break-word;
color: var(--mg-muted);
}
.info-value,
.inline-control-container,
.widget-editor-container {
grid-area: 1 / 2;
min-width: 0;
}
.info-value {
overflow-wrap: anywhere;
white-space: pre-wrap;
font-variant-numeric: tabular-nums;
}
.copy-btn {
grid-area: 1 / 3;
width: 1.75em;
height: 1.75em;
opacity: 0;
}
.info-row:hover .copy-btn,
.panel-header:hover .copy-btn,
.copy-btn:focus-visible {
opacity: 1;
}
@media (hover: none) {
.copy-btn {
opacity: 1;
}
}
/* Long values show a few lines until expanded */
.info-value.is-clamped {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4;
overflow: hidden;
}
.info-row.is-expanded .info-value.is-clamped {
display: block;
}
.value-expand {
grid-area: 2 / 2;
justify-self: start;
padding: 0;
border: 0;
background: transparent;
color: var(--mg-accent-fg);
font: inherit;
font-size: 0.85em;
cursor: pointer;
}
.value-expand:hover {
text-decoration: underline;
}
.info-row.editing :is(.copy-btn, .value-expand) {
display: none;
}
/* Off screen while the clipboard fallback copies from it */
.copy-fallback {
position: fixed;
top: 0;
left: -9999px;
opacity: 0;
}
.info-row.editable .info-value {
cursor: text;
}
.info-row.editable:hover,
.info-row.dragging {
background: var(--mg-control);
}
.info-row.draggable {
cursor: ew-resize;
}
.info-row.dragging .info-value {
color: var(--mg-accent-fg);
}
.info-row.editing .widget-editor-container {
grid-column: 2 / -1;
}
/* Text needs the room, so its editor goes under the label */
.info-row.editing:has(.widget-editor-text) {
grid-template-columns: minmax(0, 1fr);
row-gap: 0.25em;
}
.info-row.editing:has(.widget-editor-text) > * {
grid-area: auto;
}
.edit-hint {
margin: 0.25em 0.75em 0;
padding: 0.125em 0.5em;
border: 1px solid var(--mg-stroke);
border-radius: 0.25rem;
background: transparent;
color: var(--mg-muted);
font-size: 0.85em;
cursor: pointer;
}
.edit-hint:hover {
color: var(--mg-fg);
background: var(--mg-control-hover);
}
.linked-tag {
margin-left: 0.375em;
padding: 0 0.25em;
border: 1px solid var(--mg-stroke);
border-radius: 0.25rem;
color: var(--mg-muted);
font-size: 0.8em;
}
/* Widget editors */
.widget-editor {
display: flex;
align-items: center;
gap: 0.25em;
width: 100%;
}
.widget-editor-text {
flex-direction: column;
align-items: stretch;
}
.widget-editor-input,
.widget-editor-textarea {
width: 100%;
min-width: 0;
padding: 0.25em 0.5em;
border: 1px solid var(--mg-stroke);
border-radius: 0.375rem;
background: var(--mg-control);
}
.magnify-info-panel :is(.widget-editor-input, .widget-editor-textarea):focus-visible {
outline: none;
border-color: var(--mg-accent);
}
.widget-editor-number .widget-editor-input {
text-align: center;
font-variant-numeric: tabular-nums;
appearance: textfield;
}
.widget-editor-number .widget-editor-input::-webkit-outer-spin-button,
.widget-editor-number .widget-editor-input::-webkit-inner-spin-button {
margin: 0;
-webkit-appearance: none;
}
.widget-editor-stepper {
width: 1.75em;
height: 1.75em;
background: var(--mg-control);
}
.widget-editor-textarea {
min-height: 4.5em;
max-height: 15em;
resize: vertical;
}
.widget-editor-counter {
color: var(--mg-muted);
font-size: 0.875em;
font-variant-numeric: tabular-nums;
text-align: right;
}
.widget-editor-range {
flex: 1;
min-width: 0;
margin: 0;
accent-color: var(--mg-accent);
cursor: pointer;
}
.widget-editor-slider-value {
min-width: 3em;
font-variant-numeric: tabular-nums;
text-align: right;
}
/* Inline controls */
.inline-control-container {
display: flex;
align-items: center;
}
.inline-dropdown {
flex: 1;
min-width: 0;
}
/* Toggles, as the sidebar draws them */
.inline-toggle-switch {
position: relative;
display: block;
flex: none;
width: 2.25em;
height: 1.25em;
cursor: pointer;
}
.inline-toggle-input {
position: absolute;
width: 0;
height: 0;
opacity: 0;
}
.inline-toggle-slider {
position: absolute;
inset: 0;
border-radius: 1em;
background: var(--border-default, var(--mg-stroke));
transition: background-color 120ms var(--mg-ease);
}
.inline-toggle-slider::before {
content: '';
position: absolute;
top: 0.125em;
left: 0.125em;
width: 1em;
height: 1em;
border-radius: 50%;
background: var(--base-background, var(--mg-surface));
transition: transform 120ms var(--mg-ease);
}
:checked + .inline-toggle-slider {
background: var(--mg-accent);
}
:checked + .inline-toggle-slider::before {
transform: translateX(1em);
}
:focus-visible + .inline-toggle-slider {
outline: 2px solid var(--mg-ring);
outline-offset: 2px;
}
/* Dropdown triggers */
.inline-dropdown-trigger {
display: flex;
align-items: center;
gap: 0.375em;
min-height: 1.75em;
padding: 0 0.5em;
border-radius: 0.375rem;
background: var(--mg-control);
cursor: pointer;
}
.inline-dropdown-trigger:hover {
background: var(--mg-control-hover);
}
.custom-dropdown-value {
flex: 1;
min-width: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.custom-dropdown-arrow {
display: flex;
color: var(--mg-muted);
}
.inline-action-button {
min-height: 1.75em;
padding: 0 0.75em;
border: 0;
border-radius: 0.375rem;
background: var(--mg-accent);
color: var(--base-foreground, var(--mg-fg));
font-weight: 600;
cursor: pointer;
}
.inline-action-button:hover {
background: color-mix(in srgb, var(--mg-accent) 85%, var(--mg-fg));
}
/* Menus appended to body: the shared dropdown and the Go to node picker */
.custom-dropdown-menu,
.node-selector-dropdown {
position: fixed;
display: flex;
flex-direction: column;
box-sizing: border-box;
color: var(--mg-fg);
background: var(--mg-surface);
border: 1px solid var(--mg-stroke);
border-radius: 0.5rem;
box-shadow: var(--mg-shadow);
font-size: 0.8125rem;
line-height: 1.35;
}
.custom-dropdown-menu {
z-index: 100001;
overflow: hidden;
}
.custom-dropdown-filter,
.node-picker-filter {
margin: 0.25rem;
padding: 0.25rem 0.5rem;
font: inherit;
color: inherit;
background: var(--mg-control);
border: 1px solid var(--mg-stroke);
border-radius: 0.375rem;
}
.custom-dropdown-list,
.node-picker-list {
min-height: 0;
overflow-y: auto;
}
.custom-dropdown-item {
padding: 0.375rem 0.625rem;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
cursor: pointer;
}
.custom-dropdown-item.active,
.node-selector-dropdown .dropdown-item.active {
background: var(--mg-control-hover);
}
.custom-dropdown-item[aria-selected="true"],
.node-selector-dropdown .dropdown-item[aria-selected="true"] {
font-weight: 600;
box-shadow: inset 2px 0 var(--mg-accent);
}
.node-selector-dropdown {
z-index: 100000;
max-width: calc(100vw - 20px);
overflow: hidden;
}
.node-selector-dropdown .dropdown-item {
display: flex;
flex: none;
align-items: center;
gap: 0.5rem;
padding: 0.375rem 0.75rem;
cursor: pointer;
}
.dropdown-item-order {
min-width: 1.5rem;
color: var(--mg-accent-fg);
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.dropdown-item-title {
flex: 1;
min-width: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.dropdown-item-type,
.dropdown-item-id {
flex: none;
color: var(--mg-muted);
font-size: 0.85em;
}
.dropdown-item-type {
flex-shrink: 1;
max-width: 40%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.dropdown-item-id {
font-variant-numeric: tabular-nums;
}
.node-picker-empty {
padding: 0.5rem 0.75rem;
color: var(--mg-muted);
}
/* Highlight around the inspected node on the canvas */
#magnify-glass-node-highlight {
position: fixed;
z-index: 1000;
box-sizing: border-box;
border: 2px solid var(--mg-accent);
border-radius: 10px;
box-shadow: 0 0 10px color-mix(in srgb, var(--mg-accent) 30%, transparent);
pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
.magnify-info-panel *,
.floating-controls * {
transition: none !important;
}
}