Action relevant to current selection/context.
<div class="ctx-row">
<span class="ctx-row__name">Q3-report.pdf</span>
<button type="button" class="ctx-action ctx-action--onHover" style="--bg:#241430;border-radius:8px">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4 20l1-4L15 6l3 3L8 19l-4 1z"/><path d="M14 6l3 3"/></svg> Rename
</button>
</div>
<style>
.ctx-row {
display: flex; align-items: center; justify-content: space-between;
padding: 12px 14px; border: 1px solid rgba(36,20,48,.15);
font: 500 14px/1 system-ui, sans-serif; color: #241430;
}
.ctx-action {
display: inline-flex; align-items: center; gap: 6px;
font: 600 13px/1 system-ui, sans-serif;
padding: 7px 12px;
border: 1px solid var(--bg);
background: transparent;
color: var(--bg);
cursor: pointer;
}
.ctx-action--onHover { opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
.ctx-action--onHover { transition: opacity .12s ease; }
}
.ctx-row:hover .ctx-action--onHover,
.ctx-action--onHover:focus-visible { opacity: 1; }
.ctx-action:hover:not(:disabled) { background: rgba(36,20,48,.08); }
.ctx-action:focus-visible { outline:2px solid #241430;outline-offset:2px; }
.ctx-action:disabled { opacity: .35; cursor: not-allowed; }
</style><div class="group flex items-center justify-between px-3.5 py-3 text-sm font-medium text-[#241430]" style="border:1px solid rgba(36,20,48,.15)">
<span>Q3-report.pdf</span>
<button type="button" class="inline-flex items-center gap-1.5 px-3 py-1.75 text-xs font-semibold bg-transparent cursor-pointer disabled:opacity-35 disabled:cursor-not-allowed group-hover:opacity-100 ctx-action-tw ctx-action-tw--onHover" style="border:1px solid #241430;color:#241430;border-radius:8px">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4 20l1-4L15 6l3 3L8 19l-4 1z"/><path d="M14 6l3 3"/></svg> Rename
</button>
</div>
<style>
.ctx-action-tw--onHover { opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
.ctx-action-tw--onHover { transition: opacity .12s ease; }
}
.group:hover .ctx-action-tw--onHover, .ctx-action-tw--onHover:focus-visible { opacity: 1; }
.ctx-action-tw--onHover:focus-visible { outline:2px solid #241430;outline-offset:2px; }
</style>export function ContextualActionButton({
label = "Rename",
visibility = "onHover",
bg = "#241430",
radius = 8,
disabled = false,
}) {
const alwaysVisible = visibility === "alwaysVisible";
return (
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "12px 14px", border: "1px solid rgba(36,20,48,.15)", font: "500 14px/1 system-ui, sans-serif", color: "#241430" }}>
<span>Q3-report.pdf</span>
<button
type="button"
disabled={disabled}
className={alwaysVisible ? "" : "reveal-on-hover"}
style={{
display: "inline-flex",
alignItems: "center",
gap: 6,
padding: "7px 12px",
borderRadius: radius,
border: `1px solid ${bg}`,
background: "transparent",
color: bg,
font: "600 13px/1 system-ui, sans-serif",
cursor: disabled ? "not-allowed" : "pointer",
opacity: alwaysVisible ? 1 : undefined,
}}
>
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<path d="M4 20l1-4L15 6l3 3L8 19l-4 1z" /><path d="M14 6l3 3" />
</svg>
{label}
</button>
</div>
);
}