/** * The install command, with a copy button that is always visible. * * A plain code fence renders a copy control only on hover, so it is invisible * to anyone who has not already guessed it is there, and absent from the * accessibility tree entirely. This is the one line on a catalog page that * every reader is here to take, so the affordance is spelled out. * * The button is icon-only, and both icons are Mintlify's own: the same * clipboard and check paths, at the same 16px, that the sitewide code-block * copy button draws. Two copy affordances sit on a catalog page, and they * should read as one control used twice. Sizing, hover plate, focus ring and * the brand-coloured check live in `custom.css` next to the rules that style * that sitewide button, so the pair cannot drift apart. * * The "Copied" announcement is a sibling `role="status"`, not a swapped * `aria-label`: it is the pattern Mintlify already uses on the code-block * button, so a screen reader hears the same word from both controls, and it * does not rename a control while it holds focus. * * navigator.clipboard is unavailable on insecure origins, which is exactly the * local `mint dev` preview these pages are written against. The textarea path * below is the fallback, not decoration. */ export const InstallCommand = ({ command }) => { const [copied, setCopied] = React.useState(false); const copy = async () => { try { if (navigator.clipboard && window.isSecureContext) { await navigator.clipboard.writeText(command); } else { // The scratch textarea has to take focus to be selected, and removing // it drops focus on — so a reader who copied with the keyboard // would Tab from the top of the page again. Hand focus back. const previous = document.activeElement; const scratch = document.createElement("textarea"); scratch.value = command; scratch.setAttribute("readonly", ""); scratch.style.position = "fixed"; scratch.style.opacity = "0"; document.body.appendChild(scratch); scratch.select(); document.execCommand("copy"); document.body.removeChild(scratch); previous?.focus?.(); } setCopied(true); setTimeout(() => setCopied(false), 2000); } catch { // Leave the command on screen and selectable. Reporting a failure the // reader cannot act on is worse than letting them select it by hand. } }; return (
{command} {copied ? "Copied" : ""}
); };