Gradient Glow Button
A call-to-action button with a gradient fill and a soft coloured glow on hover.
6 個のフレームワーク初級
Copies text to the clipboard and confirms with a check and a "Copied" label for two seconds.
<button class="copy-btn" type="button" data-copy="npm install adysre">
<svg class="copy-btn__icon" data-icon="copy" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<rect x="9" y="9" width="12" height="12" rx="2" />
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
</svg>
<svg class="copy-btn__icon" data-icon="check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" hidden>
<path d="m20 6-11 11-5-5" />
</svg>
<!-- aria-live makes the swap an announcement, not just a picture change. -->
<span class="copy-btn__label" aria-live="polite">Copy</span>
</button>
<script>
document.querySelectorAll('.copy-btn').forEach(function (button) {
var copyIcon = button.querySelector('[data-icon="copy"]');
var checkIcon = button.querySelector('[data-icon="check"]');
var label = button.querySelector('.copy-btn__label');
var timer;
function fallbackCopy(text) {
// navigator.clipboard needs a secure context (https or localhost). On
// http:// it is simply undefined, so keep the old path alive.
var area = document.createElement('textarea');
area.value = text;
area.setAttribute('readonly', '');
area.style.position = 'absolute';
area.style.left = '-9999px';
document.body.appendChild(area);
area.select();
document.execCommand('copy');
document.body.removeChild(area);
}
button.addEventListener('click', async function () {
var text = button.dataset.copy;
try {
await navigator.clipboard.writeText(text);
} catch (error) {
fallbackCopy(text);
}
copyIcon.hidden = true;
checkIcon.hidden = false;
label.textContent = 'Copied';
button.dataset.copied = 'true';
window.clearTimeout(timer);
timer = window.setTimeout(function () {
copyIcon.hidden = false;
checkIcon.hidden = true;
label.textContent = 'Copy';
delete button.dataset.copied;
}, 2000);
});
});
</script>| Prop | 型 | デフォルト | 説明 |
|---|---|---|---|
text必須 | string | - | ボタンが押されたときにクリップボードへ書き込まれる文字列。 |
children | ReactNode | 'Copy' | コンポーネントの内部にレンダリングされるコンテンツ。 |
disabled | boolean | false | 操作を無効にし、コントロールを淡色表示にします。 |
`navigator.clipboard` needs a secure context and can be blocked by permissions policy, so the `catch` falls back to the deprecated textarea-and-`execCommand` trick - a copy button that silently does nothing is worse than an ugly one. `min-w-28` fixes the width so the box does not jump when "Copy" becomes "Copied", and `aria-live="polite"` makes the swap an announcement rather than a picture change nobody hears.