Replace the bulky hero installers with a compact platform switcher, wrapping command, and copy action

Hop-State: A_06FN6S8S3T184C0AS6MXQ08
Hop-Proposal: R_06FN6S5PSBAXTT4CDRPQS0R
Hop-Task: T_06FN6N560GHE00H1ACBKR8G
Hop-Attempt: AT_06FN6N560G6CPSCDTN8C48R
This commit is contained in:
Hop
2026-07-11 15:56:02 -07:00
parent fee4f6dd31
commit 0cb027737e
3 changed files with 202 additions and 74 deletions
@@ -305,6 +305,72 @@
load();
}
async function copyToClipboard(value) {
if (navigator.clipboard?.writeText) {
try {
await navigator.clipboard.writeText(value);
return true;
} catch {
// Fall back for browsers that block clipboard access outside a secure context.
}
}
const input = document.createElement('textarea');
input.value = value;
input.setAttribute('readonly', '');
input.style.position = 'fixed';
input.style.opacity = '0';
document.body.append(input);
input.select();
input.setSelectionRange(0, value.length);
const copied = document.execCommand('copy');
input.remove();
return copied;
}
function bindInstallationSwitchers() {
for (const switcher of document.querySelectorAll('.hop-agent-install-shell')) {
if (switcher.dataset.hopInstallBound === 'true') continue;
switcher.dataset.hopInstallBound = 'true';
const buttons = [...switcher.querySelectorAll('[data-hop-install-command]')];
const output = switcher.querySelector('[data-hop-install-command-output]');
const copyButton = switcher.querySelector('[data-hop-copy]');
const status = copyButton ? document.getElementById(copyButton.getAttribute('aria-describedby')) : null;
for (const button of buttons) {
button.addEventListener('click', () => {
for (const option of buttons) option.setAttribute('aria-pressed', String(option === button));
if (output) output.textContent = button.dataset.hopInstallCommand;
if (copyButton) copyButton.setAttribute('aria-label', `Copy ${button.dataset.hopInstallPlatform} installation command`);
if (status) status.textContent = '';
});
}
}
}
function bindInstallationCopyButtons() {
for (const button of document.querySelectorAll('[data-hop-copy]')) {
if (button.dataset.hopCopyBound === 'true') continue;
button.dataset.hopCopyBound = 'true';
button.addEventListener('click', async () => {
const command = button.closest('.hop-agent-install-command')?.querySelector('code')?.textContent?.trim();
const status = document.getElementById(button.getAttribute('aria-describedby'));
if (!command) return;
button.disabled = true;
button.textContent = 'Copying…';
const copied = await copyToClipboard(command);
button.disabled = false;
button.textContent = copied ? 'Copied' : 'Retry';
if (status) status.textContent = copied ? 'Command copied to clipboard.' : 'Could not copy automatically. Select the command and copy it.';
window.setTimeout(() => {
button.textContent = 'Copy';
if (status) status.textContent = '';
}, 2400);
});
}
}
function replaceBrandImages() {
const upstreamBrandAsset = /\/img\/(?:avatar_default\.png|logo\.png|logo\.svg)(?:\?.*)?$/;
for (const image of document.querySelectorAll('img[src]')) {
@@ -322,6 +388,8 @@
addPromptsNavigation();
addWorkflowSummary();
renderPromptPage();
bindInstallationSwitchers();
bindInstallationCopyButtons();
const title = replacePhrases(document.title);
if (title !== document.title) document.title = title;
document.documentElement.dataset.hopNative = 'true';