fix(uxp-panel): icon controls as <div role=button> so UXP renders them
ROOT CAUSE: UXP renders native <button> chrome that ignores CSS `background` and does not draw <svg>-only button content. The original panel "worked" only because its buttons had TEXT (native buttons render their text label); the redesign stripped text out, leaving empty grey pills. Non-<button> elements (the <span> status chips, the <label> search field + magnifier) render custom backgrounds and SVG children correctly in this exact UXP -- proof divs are the right vehicle. FIX: convert the 12 rail/dock/menu icon controls from <button> to <div role="button" tabindex="0">. Divs have no native `disabled`, so main.js installs a `disabled` accessor that reflects to a [disabled] attribute; CSS keys disabled styling off [disabled]. Reverted the non-working ::before cover back to direct backgrounds (divs honor them). Text buttons (Connect, slide-panel actions, glyph close) stay <button>. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
08a0fb1b60
commit
3430ef823e
3 changed files with 62 additions and 72 deletions
|
|
@ -35,9 +35,9 @@
|
|||
<span class="signal-dot"></span>
|
||||
<span id="connected-host" class="connected-host"></span>
|
||||
<span id="panel-version" class="panel-version" title="Plugin version"></span>
|
||||
<button id="menu-btn" class="iconbtn iconbtn--sm" data-tip="More" data-tip-pos="down-left" aria-label="More">
|
||||
<div id="menu-btn" role="button" tabindex="0" class="iconbtn iconbtn--sm" data-tip="More" data-tip-pos="down-left" aria-label="More">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24"><path fill="currentColor" d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<div id="status-menu" class="menu hidden" role="menu">
|
||||
<button id="disconnect-btn" class="menu-item" role="menuitem">Disconnect</button>
|
||||
</div>
|
||||
|
|
@ -47,22 +47,22 @@
|
|||
|
||||
<!-- Vertical icon rail: views on top, global actions below -->
|
||||
<nav class="rail">
|
||||
<button id="tab-library" class="rail-btn active" data-tip="Library" data-tip-pos="right">
|
||||
<div id="tab-library" role="button" tabindex="0" class="rail-btn active" data-tip="Library" data-tip-pos="right">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24"><rect x="3" y="3" width="7.5" height="7.5" rx="1.5" fill="currentColor"/><rect x="13.5" y="3" width="7.5" height="7.5" rx="1.5" fill="currentColor"/><rect x="3" y="13.5" width="7.5" height="7.5" rx="1.5" fill="currentColor"/><rect x="13.5" y="13.5" width="7.5" height="7.5" rx="1.5" fill="currentColor"/></svg>
|
||||
</button>
|
||||
<button id="tab-growing" class="rail-btn" data-tip="Growing" data-tip-pos="right">
|
||||
</div>
|
||||
<div id="tab-growing" role="button" tabindex="0" class="rail-btn" data-tip="Growing" data-tip-pos="right">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24"><path fill="currentColor" d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z"/></svg>
|
||||
<span id="growing-count" class="rail-count" style="display:none">0</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<span class="rail-spacer"></span>
|
||||
|
||||
<button id="export-timeline-btn" class="rail-btn rail-btn--accent" data-tip="Export Timeline" data-tip-pos="right">
|
||||
<div id="export-timeline-btn" role="button" tabindex="0" class="rail-btn rail-btn--accent" data-tip="Export Timeline" data-tip-pos="right">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24"><path fill="currentColor" d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"/></svg>
|
||||
</button>
|
||||
<button id="refresh-btn" class="rail-btn" data-tip="Refresh" data-tip-pos="right">
|
||||
</div>
|
||||
<div id="refresh-btn" role="button" tabindex="0" class="rail-btn" data-tip="Refresh" data-tip-pos="right">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24"><path fill="currentColor" d="M17.65 6.35A7.96 7.96 0 0 0 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08A5.99 5.99 0 0 1 12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Main column -->
|
||||
|
|
@ -112,30 +112,30 @@
|
|||
<!-- Contextual action dock: text buttons replaced by icon buttons
|
||||
with hover labels. Per-asset actions left, batch actions right. -->
|
||||
<footer class="dock">
|
||||
<button id="import-proxy-btn" class="iconbtn iconbtn--primary" data-tip="Import Proxy" data-tip-pos="up" disabled>
|
||||
<div id="import-proxy-btn" role="button" tabindex="0" class="iconbtn iconbtn--primary" data-tip="Import Proxy" data-tip-pos="up" disabled>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentColor" d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></svg>
|
||||
</button>
|
||||
<button id="import-hires-btn" class="iconbtn" data-tip="Import Hi-Res" data-tip-pos="up" disabled>
|
||||
</div>
|
||||
<div id="import-hires-btn" role="button" tabindex="0" class="iconbtn" data-tip="Import Hi-Res" data-tip-pos="up" disabled>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentColor" d="M11.99 18.54l-7.37-5.73L3 14.07l9 7 9-7-1.63-1.27-7.38 5.74zM12 16l7.36-5.73L21 9l-9-7-9 7 1.63 1.27L12 16z"/></svg>
|
||||
</button>
|
||||
<button id="mount-live-btn" class="iconbtn" data-tip="Mount Live" data-tip-pos="up" disabled>
|
||||
</div>
|
||||
<div id="mount-live-btn" role="button" tabindex="0" class="iconbtn" data-tip="Mount Live" data-tip-pos="up" disabled>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentColor" d="M14 12c0 1.11-.89 2-2 2s-2-.89-2-2 .89-2 2-2 2 .89 2 2zm-2-6c-3.31 0-6 2.69-6 6 0 2.22 1.21 4.15 3 5.19l1-1.74A3.98 3.98 0 0 1 8 12c0-2.21 1.79-4 4-4s4 1.79 4 4c0 1.48-.81 2.75-2 3.45l1 1.74c1.79-1.04 3-2.97 3-5.19 0-3.31-2.69-6-6-6zm0-4C7.58 2 4 5.58 4 10c0 2.96 1.61 5.53 4 6.92l1-1.73C7.21 14.07 6 12.18 6 10c0-3.31 2.69-6 6-6s6 2.69 6 6c0 2.18-1.21 4.07-3 5.19l1 1.73c2.39-1.39 4-3.96 4-6.92 0-4.42-3.58-8-8-8z"/></svg>
|
||||
</button>
|
||||
<button id="relink-btn" class="iconbtn" data-tip="Relink Hi-Res" data-tip-pos="up" disabled>
|
||||
</div>
|
||||
<div id="relink-btn" role="button" tabindex="0" class="iconbtn" data-tip="Relink Hi-Res" data-tip-pos="up" disabled>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentColor" d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<span class="dock-sep"></span>
|
||||
|
||||
<button id="import-all-btn" class="iconbtn" data-tip="Import All" data-tip-pos="up-left" disabled>
|
||||
<div id="import-all-btn" role="button" tabindex="0" class="iconbtn" data-tip="Import All" data-tip-pos="up-left" disabled>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentColor" d="M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81-1h12l.94 1H5.12z"/></svg>
|
||||
</button>
|
||||
<button id="export-conform-btn" class="iconbtn" data-tip="Export & Conform" data-tip-pos="up-left" disabled>
|
||||
</div>
|
||||
<div id="export-conform-btn" role="button" tabindex="0" class="iconbtn" data-tip="Export & Conform" data-tip-pos="up-left" disabled>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentColor" d="M3 17v2h6v-2H3zM3 5v2h10V5H3zm10 16v-2h8v-2h-8v-2h-2v6h2zM7 9v2H3v2h4v2h2V9H7zm14 4v-2H11v2h10zm-6-4h2V7h4V5h-4V3h-2v6z"/></svg>
|
||||
</button>
|
||||
<button id="fetch-relink-btn" class="iconbtn" data-tip="Fetch & Relink All" data-tip-pos="up-left" disabled>
|
||||
</div>
|
||||
<div id="fetch-relink-btn" role="button" tabindex="0" class="iconbtn" data-tip="Fetch & Relink All" data-tip-pos="up-left" disabled>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentColor" d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46A7.93 7.93 0 0 0 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74A7.93 7.93 0 0 0 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div><!-- /main -->
|
||||
|
|
|
|||
|
|
@ -6,6 +6,28 @@
|
|||
|
||||
const $ = id => document.getElementById(id);
|
||||
|
||||
// UXP renders native <button> chrome that ignores CSS `background` and does
|
||||
// not draw <svg>-only button content, so the rail/dock icon controls are
|
||||
// <div role="button"> (divs render custom backgrounds + SVG children fine).
|
||||
// Divs have no native `disabled`, so reflect the `.disabled` property the
|
||||
// rest of the code sets onto a [disabled] attribute the stylesheet keys off.
|
||||
const ICON_CONTROLS = [
|
||||
'menu-btn', 'tab-library', 'tab-growing', 'export-timeline-btn', 'refresh-btn',
|
||||
'import-proxy-btn', 'import-hires-btn', 'mount-live-btn', 'relink-btn',
|
||||
'import-all-btn', 'export-conform-btn', 'fetch-relink-btn'
|
||||
];
|
||||
function enableDivDisabled() {
|
||||
ICON_CONTROLS.forEach(id => {
|
||||
const el = document.getElementById(id);
|
||||
if (!el || Object.getOwnPropertyDescriptor(el, 'disabled')) return;
|
||||
Object.defineProperty(el, 'disabled', {
|
||||
configurable: true,
|
||||
get() { return this.hasAttribute('disabled'); },
|
||||
set(v) { if (v) this.setAttribute('disabled', ''); else this.removeAttribute('disabled'); }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function syncConnectBtn() {
|
||||
$('connect-btn').disabled = !$('server-url').value.trim() || !$('api-token').value.trim();
|
||||
}
|
||||
|
|
@ -465,6 +487,7 @@
|
|||
}
|
||||
|
||||
function init() {
|
||||
enableDivDisabled();
|
||||
wireConnectPane(); wireLibraryPane();
|
||||
wireExportPanel(); wireConformPanel(); wireRelinkPanel();
|
||||
showVersion();
|
||||
|
|
|
|||
|
|
@ -255,43 +255,28 @@ input[type="search"]::-webkit-search-cancel-button { display: none; }
|
|||
padding: 8px 0;
|
||||
gap: 2px;
|
||||
}
|
||||
/* Rail/dock controls are <div role="button"> (not <button>): UXP renders
|
||||
native button chrome that ignores `background` and won't draw SVG-only
|
||||
content. Divs honor backgrounds and render SVG children correctly. */
|
||||
.rail-btn {
|
||||
position: relative;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border: none;
|
||||
/* Leave background transparent — UXP native chrome cannot be overridden via
|
||||
`background` on icon-only buttons. Cover it with a ::before pseudo-element
|
||||
instead; authored content renders above native chrome. */
|
||||
background: transparent;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
border-radius: 8px;
|
||||
color: var(--text-3);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: color var(--t-fast) var(--ease);
|
||||
transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
|
||||
}
|
||||
/* Full-face cover painted above native chrome */
|
||||
.rail-btn::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: 8px;
|
||||
background: var(--bg-base);
|
||||
transition: background var(--t-fast) var(--ease);
|
||||
pointer-events: none;
|
||||
}
|
||||
.rail-btn:hover { color: var(--text-1); }
|
||||
.rail-btn:hover::before { background: var(--bg-hover); }
|
||||
.rail-btn.active { color: var(--accent-bright); }
|
||||
.rail-btn.active::before { background: var(--accent-subtle); }
|
||||
/* SVG and badge sit above the ::before cover */
|
||||
.rail-btn svg { position: relative; z-index: 1; width: 18px; height: 18px; }
|
||||
.rail-btn:hover { background: var(--bg-hover); color: var(--text-1); }
|
||||
.rail-btn.active { background: var(--accent-subtle); color: var(--accent-bright); }
|
||||
.rail-btn svg { width: 18px; height: 18px; }
|
||||
.rail-btn[disabled] { opacity: 0.32; cursor: default; pointer-events: none; }
|
||||
.rail-btn--accent { color: var(--accent-bright); }
|
||||
.rail-btn--accent:hover::before { background: var(--accent-subtle); }
|
||||
.rail-btn--accent:hover { background: var(--accent-subtle); }
|
||||
.rail-spacer { flex: 1; }
|
||||
|
||||
.rail-count {
|
||||
|
|
@ -493,40 +478,22 @@ input[type="search"]::-webkit-search-cancel-button { display: none; }
|
|||
width: 30px;
|
||||
height: 30px;
|
||||
flex-shrink: 0;
|
||||
border: none;
|
||||
/* Same ::before strategy as .rail-btn — authored pseudo-element covers
|
||||
UXP's native button chrome which ignores explicit background rules. */
|
||||
background: transparent;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
border-radius: 7px;
|
||||
color: var(--text-2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: color var(--t-fast) var(--ease);
|
||||
transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
|
||||
}
|
||||
.iconbtn::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: 7px;
|
||||
background: var(--bg-base);
|
||||
transition: background var(--t-fast) var(--ease);
|
||||
pointer-events: none;
|
||||
}
|
||||
.iconbtn:hover { color: var(--text-1); }
|
||||
.iconbtn:hover::before { background: var(--bg-hover); }
|
||||
/* SVG sits above the ::before cover */
|
||||
.iconbtn svg { position: relative; z-index: 1; width: 16px; height: 16px; }
|
||||
.iconbtn:disabled { opacity: 0.32; cursor: default; pointer-events: none; }
|
||||
.iconbtn:hover { background: var(--bg-hover); color: var(--text-1); }
|
||||
.iconbtn svg { width: 16px; height: 16px; }
|
||||
.iconbtn[disabled] { opacity: 0.32; cursor: default; pointer-events: none; }
|
||||
.iconbtn--sm { width: 24px; height: 24px; border-radius: 6px; color: var(--text-3); }
|
||||
.iconbtn--sm::before { border-radius: 6px; }
|
||||
.iconbtn--sm svg { width: 15px; height: 15px; }
|
||||
.iconbtn--primary::before { background: var(--accent); }
|
||||
.iconbtn--primary { color: #fff; }
|
||||
.iconbtn--primary:not(:disabled):hover::before { background: var(--accent-hover); }
|
||||
.iconbtn--primary { background: var(--accent); color: #fff; }
|
||||
.iconbtn--primary:not([disabled]):hover { background: var(--accent-hover); }
|
||||
|
||||
/* ── progress ───────────────────────────────────────────────────── */
|
||||
.progress-row { display: flex; flex-direction: column; gap: 4px; padding: 8px 10px 0; flex-shrink: 0; }
|
||||
|
|
|
|||
Loading…
Reference in a new issue