@fumikaz/split-flap
v0.4.0
Published
Accessible split-flap display components for React and TypeScript
Maintainers
Readme
@fumikaz/split-flap
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"
/>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 | wrapLongText が true のときのみ有効。この文字数を超えたら、先頭からこの文字数で改行して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_CHARACTERS、NUMBER_CHARACTERS、JAPANESE_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-runnpm への公開
main への 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 を設定してください。
