ui
copy to clipboard feedback / copy button animation / copied tooltip
コピーボタンを押した瞬間にボタンの背景が成功色で光って引き、ボタンの真上から「コピーしました」が少し浮いて消える演出。クリップボードは目に見えないので、押した場所で返さないと「本当にコピーされたのか」をユーザーが確かめに行く。肝は押すたびに頭から再生し直すことと、失敗も同じ場所で返すこと。
02 — Prompt template
03 — Params
flash(背景の光が引く時間 s) — 範囲 0〜1.2 / 初期 0.47
成功色を一瞬で乗せ、この時間で ease-out に透明へ戻す。0.4〜0.5sが「押した手応え」として読める(観察元は0.47s)。0で光らせない。0.8sを超えるとボタンが選択状態になったように見える。rise(ラベルの浮き上がり px) — 範囲 0〜24 / 初期 5
「コピーしました」がボタンの上で浮く距離。4〜8pxで「ボタンから出てきた」と読める。16pxを超えると飛んでいく別の通知に見え、ボタンとの結び付きが切れる。0だとその場でフェードするだけ。hold(ラベルが消え始めるまで s) — 範囲 0.2〜2.5 / 初期 0.7
ラベルを読ませる時間。この後0.8sかけて消える。「コピーしました」程度の短さなら0.6〜1s。0.4s未満は読み切れず、2sを超えると次のコピーの邪魔になる。feedback(返し方) — 選択: float-label / icon-swap / both(初期: float-label)
float-labelはボタンの上に文字を浮かべる(観察元)。icon-swapはクリップボードのアイコンをチェックに入れ替えて hold+0.8s 後に戻す(GitHubのコードブロック型)。アイコンだけのボタンが密集する場所はicon-swap、意味を言葉で伝えたい場所はfloat-labelかboth。
04 — Vocab
Clipboard API(navigator.clipboard.writeText) — 文字列をクリップボードへ書き込む非同期API。Promiseを返し、https などの安全なコンテキストとユーザー操作の中でしか成功しない。拒否されると例外になるので、結果を見てから成功表示を出す。
インプレースフィードバック(in-place feedback) — 操作の結果を、操作した要素の上や中で返すこと。画面端のトースト(toast)より視線移動が無く、どのボタンの結果かが一目で結び付く。
アニメーションの再トリガー(restart) — 同じクラスを付けっぱなしにしても CSS アニメーションは2度目を再生しない。クラスを外して次のフレームで付け直す、または key を変えて要素を作り直すと頭から再生される。
片側キーフレーム(from だけ指定) — @keyframes に 0% だけ書くと、その値から要素の通常のスタイルへ補間される。「一瞬光って元に戻る」を1行で書ける(観察元の背景フラッシュはこの書き方)。
aria-live="polite" — 中身が変わったときに、読み上げ中の内容を遮らずに読み上げさせる属性。見た目だけのラベルでは、スクリーンリーダーにコピーの成否が伝わらない。
05 — NG → OK examples
NG
言い方: 「「コピーボタンを押したら、コピーできたって分かるようにして」」
なぜNG: 画面の端にトーストを出す実装が返ってきやすく、押した場所から視線が外れて「どれをコピーしたのか」が結び付かない。表示が状態の切り替えだけで作られると、2回目以降のクリックでは何も再生されず壊れて見える。writeText の失敗を拾っていない実装も多く、http 環境ではコピーされていないのに「コピーしました」と出る。
OK
言い方: 「「copy to clipboard feedbackを。writeTextをawaitしてsuccess/error。押すたびに状態を空にしてから入れ直して頭から再生。背景は成功色を0%にだけ置き0.47s ease-outで引く。ボタンの真上に『コピーしました』、1.5sで5px浮かせ0.7s後から0.8sで消して要素を外す。失敗は赤で光らせて文字列を選択状態に。aria-live=polite、reduced-motionでは静止表示」」
なぜOK: 返す場所(ボタンの真上)・光と浮き上がりの数値・消すタイミングに加えて、「押すたびに頭から」と「失敗の逃げ道」が指定されている。この2つが無いと、連打で無反応になる実装と、失敗しても成功と言う実装が普通に返ってくる。
