React と TypeScript 向けの、アクセシブルな反転フラップ表示コンポーネントです。文字や値をフラップ式の回転アニメーションで表示します。
- ESM / CommonJS / 型定義を配布
- Unicode コードポイント対応で、日本語と絵文字を安全に扱う
sequence、shuffle、directの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"
/>| 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 |
wrapLongText が true のときのみ有効。この文字数を超えたら、先頭からこの文字数で改行して2行表示(1行目=この文字数、残りを2行目)。以下なら文字を縮小して1行に収める。0(または未設定)で無効 |
onAnimationStart |
() => void |
- | 値変更によるアニメーション開始時 |
onAnimationComplete |
() => void |
- | 最新のアニメーション完了時 |
SplitFlapBackgroundOptions の既定値は次のとおりです。
{
widthMode: "fixed",
alignment: "center",
fixedWidth: 160,
horizontalPadding: 16,
verticalPadding: 6,
borderRadius: 8,
}sequence: 文字集合を現在文字から目的文字まで順に反転します。shuffle: ランダム文字をshuffleCount回表示してから目的文字にします。同じ文字の連続を避けます。direct: 1回の反転で目的文字へ切り替えます。
direction="shortest" は sequence の際に、文字集合内で前後どちらが短いか選びます。
charactersPerPanel を指定すると、連続するUnicode文字を1枚のパネルへまとめて表示できます。length は文字数ではなくパネル数になります。
<SplitFlap value="TOKYO" length={2} charactersPerPanel={3} />プリセットとして LATIN_CHARACTERS、NUMBER_CHARACTERS、JAPANESE_KANA_CHARACTERS を export しています。独自の配列も渡せます。
const symbols = [" ", "遅", "延", "着", "発", "-", "0", "1", "2", "3"];
<SplitFlap value="遅延" length={4} characters={symbols} />;コンポーネントの親要素または 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;
}コンポーネントを使うファイルをクライアントコンポーネントにしてください。
"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-runmain への push と pull request では、CI が lint、型チェック、テスト、ビルド、パッケージ内容を検証します。
ローカルから公開する場合は、npm にログインして未公開のバージョンへ更新してから実行します。
npm version patch
npm publishGitHub Release を published にすると、Publish to npm workflow が npm registry へ公開します。リリースタグは v<version> 形式にし、リポジトリの Actions secrets に npm の公開権限を持つ NPM_TOKEN を設定してください。