Skip to content

Repository files navigation

@fumikaz/split-flap

React と TypeScript 向けの、アクセシブルな反転フラップ表示コンポーネントです。文字や値をフラップ式の回転アニメーションで表示します。

特徴

  • ESM / CommonJS / 型定義を配布
  • Unicode コードポイント対応で、日本語と絵文字を安全に扱う
  • sequenceshuffledirect の3つのアニメーションモード
  • prefers-reduced-motion とスクリーンリーダーに対応
  • CSS カスタムプロパティで外観を調整可能
  • 値マップの背景色、空の値、複数文字を1パネルに収める表示に対応
  • SSR 環境から安全に import 可能

インストール

npm install @fumikaz/split-flap

スタイルシートをアプリケーションのエントリーポイントで一度読み込みます。

import "@fumikaz/split-flap/styles.css";

基本例

import { SplitFlap } from "@fumikaz/split-flap";
import "@fumikaz/split-flap/styles.css";

export default function App() {
  return (
    <SplitFlap value="HELLO 10:24" length={11} interval={100} stagger={0} />
  );
}

多言語テキスト

漢字のように巨大な文字集合では、目的文字までの順送りを避ける shuffle が便利です。characters に目的の文字を含めなくても、最後に直接表示されます。

<SplitFlap value="こんにちは" length={5} animationMode="shuffle" />

色付きの値マップと背景

値マップでは、value に選択するキーを渡します。オブジェクトの定義順に選択先まで1件ずつ反転し、各値の bgColor は文字と同じfrom/to面へ追従します。

import type { SplitFlapValueMap } from "@fumikaz/split-flap";

const displayValues = {
  "0001": { value: "待機中", bgColor: "#f0ffff" },
  "0002": { value: "処理中", bgColor: "#fff4d6" },
  "0003": { value: "完了", bgColor: "#ffe5e5" },
} satisfies SplitFlapValueMap;

<SplitFlap
  values={displayValues}
  value="0003"
  valueTransitionInterval={350}
  charactersPerPanel={4}
  backgroundOptions={{
    widthMode: "fixed",
    alignment: "left",
    fixedWidth: 180,
    horizontalPadding: 18,
    verticalPadding: 6,
    borderRadius: 8,
  }}
/>;

bgColor が省略または空文字の場合は、背景バッジを描画しません。数値の寸法はpxとして扱います。

固定幅

widthMode: "fixed" では、文字列バッジの基準幅を fixedWidth に固定し、左右の horizontalPadding を加えた幅をバッジに使います。黒いフラップの幅は --split-flap-width で独立して決まり、バッジが広すぎる場合はパネル内に収まる幅へ制限されます。長い文字列は1行のままクリップされます。

可変幅

widthMode: "content" では、文字列の実幅に左右の horizontalPadding を加えた幅になります。黒いフラップの幅は --split-flap-width で独立して決まり、各バッジの横位置は alignment で指定します。verticalPadding は両モードで文字列バッジの高さへ一度だけ適用されます。

横位置

alignment は文字列と背景バッジを一体で配置します。"left""center""right" を指定でき、既定値は "center" です。左寄せ・右寄せでは、文字列にも背景の左右paddingを適用します。

<SplitFlap
  values={displayValues}
  value="0003"
  charactersPerPanel={4}
  backgroundOptions={{
    widthMode: "content",
    horizontalPadding: 18,
    verticalPadding: 6,
    borderRadius: 8,
  }}
/>

背景色はフラップ面を塗らず、文字列だけを囲む角丸長方形として静止面に描画します。反転するのは黒いフラップパネルと文字であり、色付きバッジ自体は回転しません。バッジは上半分・下半分の親要素でクリッピングされるため、中央の分割線に別の角丸は付きません。

文字列の実幅がバッジの内容領域を超える場合は、文字だけを自動で縮小してバッジ内へ収めます。静止面と反転面では同じ縮小率を使います。

空の値

value: "" を候補に含めると、文字を表示しない1枚のフラップを描画します。候補配列で空の値が連続する場合も、各候補は統合されず、それぞれでフラップアニメーションが実行されます。

<SplitFlap
  values={[
    { key: "ready", value: "READY" },
    { key: "blank-one", value: "" },
    { key: "blank-two", value: "" },
  ]}
  selectedValueKey="blank-two"
/>

旧候補配列との互換性

既存の readonly SplitFlapValue[]selectedValueKey も引き続き使用できます。配列候補に bgColor を付けた場合も、同じ背景面の処理が使われます。

<SplitFlap
  values={[
    { key: "0001", value: "待機中", bgColor: "#f0ffff" },
    { key: "0002", value: "処理中", bgColor: "#fff4d6" },
  ]}
  selectedValueKey="0002"
/>

Props

Prop 既定値 説明
value string - 単体モードの表示文字列、または値マップモードの選択キー
values SplitFlapValueMap - キーごとの { value, bgColor? }。空文字を含められ、定義順に通過する候補
backgroundOptions Partial<SplitFlapBackgroundOptions> 下記 背景の幅、横位置、余白、角丸
selectedValueKey string - 旧候補配列モードで到達する候補のキー
valueTransitionInterval number interval 候補モードで次の候補へ進む間隔(ms)
length number value の文字数 パネル数。空文字のときは1
charactersPerPanel number 1 1パネルに収めるUnicode文字数。値マップでは省略時に最長値全体を1パネルへ収める
characters string | readonly string[] LATIN_CHARACTERS 順送り・シャッフルに使う文字集合
interval number 360 上面・下面を含む1回の反転時間(ms)
stagger number 0 各フラップの開始間隔(ms)
padCharacter string " " 短い値を埋める文字。複数文字の場合は最初のコードポイントを使用
animationMode "sequence" | "shuffle" | "direct" "sequence" アニメーション方式
direction "forward" | "shortest" "forward" sequence の進行方向
shuffleCount number 6 shuffle 時のランダム表示回数
className string - 盤面のクラス名
characterClassName string - 全フラップに付与するクラス名
ariaLabel string value 盤面の代替テキスト
wrapLongText boolean false パネル幅に収まらない文字列を2行に折り返す
alwaysWrapText boolean false 文字数に関わらず常に2行に折り返す
wrapThreshold number 0 wrapLongTexttrue のときのみ有効。この文字数を超えたら、先頭からこの文字数で改行して2行表示(1行目=この文字数、残りを2行目)。以下なら文字を縮小して1行に収める。0(または未設定)で無効
onAnimationStart () => void - 値変更によるアニメーション開始時
onAnimationComplete () => void - 最新のアニメーション完了時

SplitFlapBackgroundOptions の既定値は次のとおりです。

{
  widthMode: "fixed",
  alignment: "center",
  fixedWidth: 160,
  horizontalPadding: 16,
  verticalPadding: 6,
  borderRadius: 8,
}

Animation modes

  • sequence: 文字集合を現在文字から目的文字まで順に反転します。
  • shuffle: ランダム文字を shuffleCount 回表示してから目的文字にします。同じ文字の連続を避けます。
  • direct: 1回の反転で目的文字へ切り替えます。

direction="shortest"sequence の際に、文字集合内で前後どちらが短いか選びます。

複数文字パネル

charactersPerPanel を指定すると、連続するUnicode文字を1枚のパネルへまとめて表示できます。length は文字数ではなくパネル数になります。

<SplitFlap value="TOKYO" length={2} charactersPerPanel={3} />

独自の文字集合

プリセットとして LATIN_CHARACTERSNUMBER_CHARACTERSJAPANESE_KANA_CHARACTERS を export しています。独自の配列も渡せます。

const symbols = [" ", "遅", "延", "着", "発", "-", "0", "1", "2", "3"];

<SplitFlap value="遅延" length={4} characters={symbols} />;

CSS カスタマイズ

コンポーネントの親要素または className に以下の変数を設定できます。

.my-board {
  --split-flap-width: 2.5rem;
  --split-flap-height: 3.5rem;
  --split-flap-gap: 0.2rem;
  --split-flap-font-size: 2.2rem;
  --split-flap-font-family: "Courier New", monospace;
  --split-flap-font-weight: 700;
  --split-flap-color: #f4ecc1;
  --split-flap-background: #171717;
  --split-flap-border-color: #343434;
  --split-flap-border-radius: 0.2rem;
  --split-flap-shadow: 0 0.18rem 0.32rem rgb(0 0 0 / 32%);
  --split-flap-frame-color: #111416;
  --split-flap-frame-edge-color: #32373a;
  --split-flap-frame-size: 1px;
  --split-flap-perspective: 900px;
  --split-flap-hinge-color: #080808;
  /* --split-flap-hinge-height: 0.5px; */
  --split-flap-text-offset: 0em;
  --split-flap-bg-fixed-width: 160px;
  --split-flap-bg-horizontal-padding: 16px;
  --split-flap-bg-vertical-padding: 6px;
  --split-flap-bg-border-radius: 8px;
}

Next.js

コンポーネントを使うファイルをクライアントコンポーネントにしてください。

"use client";

import { SplitFlap } from "@fumikaz/split-flap";
import "@fumikaz/split-flap/styles.css";

export function StatusDisplay() {
  return <SplitFlap value="READY" length={5} animationMode="shuffle" />;
}

アクセシビリティとブラウザ対応

外側の盤面だけに role="img" と文字列全体の aria-label を設定し、各フラップは aria-hidden にします。ライブリージョンは使用しません。prefers-reduced-motion: reduce が有効な利用者には、アニメーションせず最終文字を表示します。

CSS の 3D transform と ES2020 をサポートするモダンブラウザを対象とします。

開発

npm run dev       # デモを起動
npm run lint
npm run typecheck
npm run test
npm run test:run
npm run build     # dist にライブラリを出力
npm run preview
npm pack --dry-run

npm への公開

main への push と pull request では、CI が lint、型チェック、テスト、ビルド、パッケージ内容を検証します。

ローカルから公開する場合は、npm にログインして未公開のバージョンへ更新してから実行します。

npm version patch
npm publish

GitHub Release を published にすると、Publish to npm workflow が npm registry へ公開します。リリースタグは v<version> 形式にし、リポジトリの Actions secrets に npm の公開権限を持つ NPM_TOKEN を設定してください。

ライセンス

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages