mcpField
B
beam-glow-states

beam-glow-states

github.com/mengtoデザイン・UI7.1k1.3k 回インストール3 日前に更新
リポジトリ

beam-glow-states について

beam-glow-statesは、border-beamのReactコンポーネントで読み込み、選択、アクティブ状態を示すためのスキルです。エフェクトの選択、意味を保つ静的表示、アクセシビリティ、描画確認を扱います。

主な機能

  1. 015種類のビームエフェクトから選択
  2. 02色、テーマ、強さ、時間の設定
  3. 03アニメーションなしでも状態を明示
  4. 04有効化とフェードアウトの制御
  5. 05アクセシビリティとレスポンシブ表示の確認

活用シーン

  1. 01カードや入力欄の読み込み表示
  2. 02選択中のパネルや操作部の強調
  3. 03視差効果低減時の状態表示の検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mengto/skills --skill beam-glow-states

インストール後、Claude Code で/beam-glow-statesを入力して読み込まれたか確認します。

同梱ファイルagents/openai.yamlREFERENCES.md

詳細

ビームグローの状態

ビームは状態を際立たせる装飾として使います。アニメーションがない場合でも、テキスト、形状、コントラスト、適切なセマンティック属性で状態が理解できるようにしてください。

以下の API は border-beam 1.3.0 で検証済みです。インストール済みバージョンを変更した場合は、公式 README とエクスポートされる型を再確認してください。

インストールとインポート

リポジトリのパッケージマネージャーを使って、同じパッケージをインストールします。

npm install border-beam
pnpm add border-beam
yarn add border-beam
bun add border-beam

このパッケージには React と React DOM 18 以降が必要です。ESM、CommonJS、TypeScript の型定義が含まれています。コンポーネントのスコープに限定されたスタイルを挿入するため、別の CSS ファイルをインポートしないでください。

名前付きインポートを推奨します。

import { BorderBeam } from "border-beam";
import type {
  BorderBeamProps,
  BorderBeamSize,
  BorderBeamTheme,
  BorderBeamColorVariant,
} from "border-beam";

デフォルトのコンポーネントエクスポートもサポートされています。

import BorderBeam from "border-beam";

Next.js App Router プロジェクトでは、React の state、エフェクト、オブザーバー、アニメーションフレームを使用するため、クライアントコンポーネントからレンダリングしてください。

"use client";

import { BorderBeam } from "border-beam";

エフェクトを選ぶ

size動き最適な用途
smコンパクトな枠線が移動アイコンボタン、ピル、コンパクトなコントロール
md枠線全体が移動選択中のカード、現在のパネル、主要なアクティブ領域
line下辺が移動検索、プロンプト、入力、進捗、コマンドの領域
pulse-inner内側に収まる呼吸するグローローディングカード、処理中のパネル、持続する選択状態
pulse-outside外側に広がる呼吸するハロー広がる余地のある、目立たせたいアクティブタスクやヒーローコントロールを 1 つだけ

状態ごとに、次のデフォルトを使います。

  • ローディング中または処理中:pulse-inner、strength={0.55}~0.75、duration={2.3}~3。
  • 選択中または現在の項目:md または pulse-inner、strength={0.3}~0.55、duration={3.2}~5。
  • フォーカスまたは短時間のアクティブフィードバック:sm または line、strength={0.35}~0.6。
  • 優先度の高い進行中タスク:pulse-outside、strength={0.45}~0.7。1 つのビューにつき 1 つだけにしてください。

ニュートラルなプロダクト UI には colorVariant="mono"、落ち着いた技術的な状態には ocean、緊急性を温かみのある色で示す場合は sunset、まれな非常に目立たせたい場面には colorful から始めてください。

マウントしたラッパーを 1 つ使う

BorderBeam はマウントしたままにして、active を切り替えてください。状態が false になったときに削除すると、組み込みのフェードアウトがスキップされます。

<BorderBeam
  size="pulse-inner"
  colorVariant="ocean"
  theme="dark"
  strength={0.65}
  active={isWorking}
>
  <section className="task-card" aria-busy={isWorking}>
    <p>{isWorking ? "Generating layout options…" : "Layout options ready"}</p>
  </section>
</BorderBeam>

active は 0.6s でフェードインし、0.5s でフェードアウトします。視覚的なトランジションの完了に処理を合わせる必要がある場合にのみ、onActivate と onDeactivate を使ってください。

ローディング状態を設定する

ビームを追加する前に、ローディング状態が正確に伝わるようにしてください。

<BorderBeam
  size="pulse-inner"
  colorVariant="ocean"
  strength={0.65}
  active={pending && !reduceMotion}
  onDeactivate={() => {
    // Optional: advance only after the 0.5s beam exit completes.
  }}
>
  <section className="beam-surface" aria-busy={pending}>
    <span className="status-dot" aria-hidden="true" />
    <span>{pending ? "Building preview…" : "Preview ready"}</span>
  </section>
</BorderBeam>
  • 表示される状態ラベルまたは進捗値を示してください。動く枠線だけをローディングの手がかりにしないでください。
  • およそ 150ms 以下で終わる処理には、ビームを表示しないでください。
  • 表示したら、ちらつきを防ぐため、ローディング表示を約 400ms~600ms 維持してください。
  • 処理中と完了後の状態でレイアウトを維持してください。
  • キャンセル、再試行、エラーのコントロールを操作可能なままにしてください。エフェクトのレイヤーには、すでに pointer-events: none が設定されています。

処理が 1 つの入力欄またはプロンプトバーに属する場合は line を使います。カード全体が処理中の場合は pulse-inner を使います。

選択中または現在の状態を設定する

コンポーネントの状態とセマンティックな状態を組み合わせて使ってください。

<BorderBeam
  size="md"
  colorVariant="mono"
  staticColors
  duration={4.2}
  strength={0.42}
  active={selected && !reduceMotion}
  className="beam-card"
>
  <button
    type="button"
    className="beam-surface"
    aria-pressed={selected}
    onClick={onSelect}
  >
    {label}
  </button>
</BorderBeam>
  • タブ、リストボックスのオプション、グリッドセルなどの選択ウィジェットには aria-selected を使います。
  • 現在のページ、ステップ、日付、場所には aria-current を使います。
  • aria-pressed はトグルボタンにのみ使います。
  • 静的な選択背景またはアウトラインを維持してください。ビームは注意を引くためのものであり、それ自体に意味を持たせないでください。
  • 持続して表示する選択状態のビームは、動きを遅くしてください。速いデフォルトの移動は、ローディング中または短時間のアクティブ状態に限ります。

項目数が多い場合は、新しく選択された項目だけを 800ms~1200ms アニメーションさせ、その後は静的な選択スタイルを維持してください。選択されたすべての項目でビームを無期限に動かし続けないでください。

フォーカスとアクティブ状態の管理

すべての標準 HTMLDivElement 属性とキャプチャハンドラーが転送されるため、ラッパーでフォーカスを追跡します。

const [focused, setFocused] = useState(false);

<BorderBeam
  size="sm"
  colorVariant="mono"
  strength={0.45}
  active={focused && !reduceMotion}
  className="beam-inline"
  onFocusCapture={() => setFocused(true)}
  onBlurCapture={(event) => {
    const next = event.relatedTarget as Node | null;
    if (!next || !event.currentTarget.contains(next)) setFocused(false);
  }}
>
  <button className="beam-surface">Run</button>
</BorderBeam>

通常の :focus-visible アウトラインは維持してください。ポインターのホバーだけで強いビームを開始せず、押下状態では即座にスケール、塗りつぶし、またはコントラストのフィードバックが表示されるようにします。

状態が重なる場合は、明示的に優先順位を決めます。

const beamState =
  pending ? "loading" :
  selected ? "selected" :
  focused ? "focus" :
  "idle";

const beamProps = {
  loading: {
    size: "pulse-inner",
    colorVariant: "ocean",
    duration: 2.6,
    strength: 0.65,
  },
  selected: {
    size: "md",
    colorVariant: "mono",
    duration: 4.2,
    strength: 0.42,
    staticColors: true,
  },
  focus: {
    size: "sm",
    colorVariant: "mono",
    duration: 2.4,
    strength: 0.45,
    staticColors: true,
  },
} as const;

const activeProps = beamState === "idle" ? null : beamProps[beamState];

<BorderBeam
  {...(activeProps ?? { size: "md" as const })}
  active={activeProps !== null && !reduceMotion}
>
  <div className="beam-surface" data-state={beamState}>
    {children}
  </div>
</BorderBeam>

プロダクトの状態モデルで別の指定がない限り、ローディングを選択より上、選択をフォーカスより上、フォーカスをホバーより上にします。

モーション低減設定への対応

prefers-reduced-motion: reduce の場合、パルスプリセットのアニメーションは停止します。回転プリセットとラインプリセットも、利用側で無効にしてください。プロジェクトのメディアクエリーフックか、小さなクライアントフックを使用します。

function useReducedMotion() {
  const [reduced, setReduced] = useState(false);

  useEffect(() => {
    const media = window.matchMedia("(prefers-reduced-motion: reduce)");
    const update = () => setReduced(media.matches);
    update();
    media.addEventListener("change", update);
    return () => media.removeEventListener("change", update);
  }, []);

  return reduced;
}

子サーフェスに静的なフォールバックを用意します。

.beam-surface {
  border: 1px solid rgb(255 255 255 / 0.12);
}

[data-state="selected"] {
  border-color: rgb(140 155 255 / 0.7);
  box-shadow: 0 0 0 3px rgb(100 120 255 / 0.12);
}

:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  [data-state="loading"] {
    border-color: rgb(100 150 255 / 0.68);
  }
}

API リファレンス

Prop型デフォルト契約
childrenReactNode必須生成された 1 つの div でラップするコンテンツ
size"sm" | "md" | "line" | "pulse-outside" | "pulse-inner""md"エフェクトの種類と形状のプリセット
colorVariant"colorful" | "mono" | "ocean" | "sunset""colorful"ビームのカラーパレット
theme"dark" | "light" | "auto""dark"背景に合わせて不透明度と色の処理を調整
strengthnumber1ビームレイヤーの不透明度。0~1 に制限され、子要素の不透明度は変更しません
durationnumber回転は 1.96、ラインは 3.1、パルスは 2.3アニメーション周期(秒)
activebooleantrueフェードインまたはフェードアウトを開始し、継続中のモーションを制御
borderRadiusnumber自動検出ラッパーの半径(ピクセル)
brightnessnumberプリセットごとに異なり、通常は 1.3グローの明るさの倍率
saturationnumberテーマごとに異なり、暗色では通常 1.2グローの彩度の倍率
hueRangenumber30色相シフトの範囲(度)。line では最大 13
staticColorsbooleanfalse色相シフトを無効化します。移動やパルスのモーションは無効化しません
classNamestring—生成されたラッパーに設定するクラス
styleCSSProperties—生成されたラッパーに設定するインラインスタイル
onActivate() => void—0.6s のフェードイン完了時に呼び出されます
onDeactivate() => void—0.5s のフェードアウト完了時に呼び出されます

mono は、staticColors が false でも常に静的な色を使用します。転送された ref はラッパーを参照します。その他の標準 HTMLDivElement 属性とイベントも転送されます。

パッケージでは sizePresets、sizeThemePresets、非推奨の themeColors もエクスポートしています。これらは実装の参考として扱い、エクスポートされたプリセットオブジェクトを変更するのではなく、コンポーネントの props を使用してください。

ラッパーの扱い

  • BorderBeam は div をレンダリングします。li、td、label など、セマンティクス上必要な親要素の内側に配置し、それらの要素を置き換えないでください。
  • ラッパーはデフォルトでブロックレベルです。コンパクトなコントロールには display: inline-block または inline-flex を使用し、カードには width: 100% を使用します。
  • 先頭の子要素をラッパーの境界に合わせます。伸張されたラッパーの内側に小さな子要素を置くと、空白の周囲にビームが表示されます。
  • 境界半径は、先頭の子要素の計算済みの左上の半径から取得されます。角ごとに半径が異なる場合、実行時に半径が変わる場合、またはスタイルが遅れて適用され検出の信頼性が低い場合は、borderRadius を明示的に設定してください。
  • sm、md、line、pulse-inner はオーバーフローをクリップします。メニューやツールチップをラッパーの外にはみ出させる必要がある場合、これらのラッパーの内側に配置しないでください。
  • pulse-outside は overflow: visible を使用します。内側のグローが透けて見えないよう、子要素は不透明にし、周囲のレイアウトではハローがはみ出せるようにします。
  • pulse-outside の子要素には、独自の控えめな 1px の境界線またはインセットリングを設定してください。このプリセットは意図的に、別個の待機時の細い境界線を描画しません。
.beam-inline {
  display: inline-block;
}

.beam-card {
  display: block;
  width: 100%;
}

.beam-surface {
  width: 100%;
  border-radius: inherit;
  background: rgb(18 18 20);
}

控えめにする

  • ビューポートごとに、目立つアニメーションビームは1つにします。同時に複数のビームを使うと、階層が曖昧になり、描画処理が増えます。
  • 明るさや彩度を変える前に、strength を調整します。
  • 選択状態を示すビームは、読み込み中のビームより動きを遅く、控えめにします。
  • ビーム全体を、別のアニメーション付きグラデーションボーダー、大きく脈動するシャドウ、動く背景と組み合わせないでください。
  • pulse-outside は実際の余白に広がるようにします。意図せず切り取らないでください。
  • pulse のインスタンスは、フレームレートが制限されたアニメーションループを共有し、画面外では一時停止することを前提にしてください。rotate と line は CSS アニメーションを使用し、コンポーネントが画面外にある場合も一時停止します。

確認

次の項目をテストします。

  • 初期の非アクティブ状態、フェードイン、アクティブ状態の維持、フェードアウト、状態の急速な切り替え。
  • 読み込みの成功、エラー、再試行、キャンセルが、突然アンマウントされずに行われること。
  • aria-busy、aria-selected、aria-current、aria-pressed が適切なセマンティクスで使われていること。
  • ビームを無効にした状態、および動きを減らす設定を有効にした状態でのキーボードフォーカス。
  • 実際の表示面でのダーク、ライト、auto テーマ。
  • 幅が 320、768、1440 の場合の sm、md、line、pulse-inner、pulse-outside。
  • ボーダー半径の整合性、親要素のオーバーフロー、外側のパルスを覆う不透明な子要素、コンパクトなラッパーのサイズ。
  • 長いラベル、200% のズーム、多数のリスト項目、画面外での一時停止、ルートのクリーンアップ、コンソールエラー。

リンクのみのソース一覧として REFERENCES.md を維持してください。

コメント