数値入力&ステッパーシステム
目的
数値入力&ステッパーシステムは、離散的な数値を選択、調整、または入力するためのコントロールを設計、構造化、実装するための標準化されたフレームワークを提供します。カート内の商品数量、SaaSのシート割り当て、価格帯のユニット、予算範囲、寸法指定など、正確な数値入力には、迅速な微調整と直接テキスト編集のバランス、明確な最小/最大境界状態、タッチフレンドリーなタップターゲット、そしてフルキーボード/スクリーンリーダーアクセシビリティが求められます。
標準のHTML <input type="number">コントロールはブラウザ間で不統一に表示され、タッチターゲットガイドライン(WCAG 2.2 SC 2.5.8)に違反する小さくカスタマイズ不可能なネイティブスピナー矢印を備え、誤ったスクロール調整を引き起こすことがよくあります。このスキルは、カスタム数値ステッパーと単位付きフィールドのための明示的なUIパターン、空間レイアウトルール、インタラクション状態、アクセシビリティ基準を定義します。
ユースケース
- Eコマースカート数量セレクター: ショッパーがPDP、カートドロワー、チェックアウト集計テーブル内で商品数量を簡単に増減、入力できるようにします。
- SaaSプランシート&ライセンスコントロール: 価格ページやサブスクリプション管理設定で、ユーザーシート、サーバーインスタンス、ストレージギガバイト数をプロビジョニングします。
- フォーム内制約付き単位入力: パーセンテージ値(0–100%)、年齢制限、アイテム寸法(縦/横/高さ)、通貨金額などの制約されたメトリクスを取得します。
- 財務&計算機コントロール: インタラクティブな計算機内で融資期間、預金額、投資増分を選択します。
- ダッシュボード&フィルターコントロール: データ密度の高いデスクトップ環境で、数値しきい値、ページネーション行数制限、メトリクス範囲フィルターを調整します。
使用すべきでない場合
- 連続範囲選択: 正確な値よりも相対的な位置が重要で、広範で非特定的な数値範囲の探索には、代わりに
accessible-range-slider-implementationまたはデュアルサムスライダーを使用します。 - 大きな任意の数値: クレジットカード番号、電話番号、郵便番号、社会保障番号など、増分/減分操作が意味をなさない入力には、代わりに
form-design-systemとともに標準の<input type="text" inputmode="numeric">を使用します。 - 日付&時刻選択: カレンダーの日付、月、時刻を選択するには、
calendar-and-date-systemを使用します。 - 大きな離散オプションセット: 25、50、100、500 などの事前設定されたバルク数量から選択する場合は、
segmented-control-systemまたはcustom-select-and-combobox-systemを使用します。
入力
- 値の境界: 最小値(
min)、最大値(max)、増分ステップ(step)の制約。 - コンテキスト&密度: 利用可能なレイアウトスペース(コンパクトなインラインテーブル行 vs. 目立つPDP購入ブロック)。
- 入力形式&単位: 関連する物理的または金銭的な単位(例:
$、%、個、kg、席)。 - インタラクションモード: 直接手動テキスト入力を許可するか、ステッパーボタンのみに調整を制限するか。
- ブランド&サーフェストークン: サーフェス背景、アクティブ境界線、無効状態、フォーカスリング、アイコングリフのパレットトークン。
出力
- ステッパーコンポーネント仕様: 減分ボタン、数値表示/入力フィールド、増分ボタン、単位ラベルを定義するビジュアルアナトミー。
- 境界&状態マトリックス: デフォルト、ホバー、フォーカス、無効(最小/最大時)、ローディング、エラー状態のビジュアル処理。
- レスポンシブ空間レイアウト仕様: タッチターゲット寸法(モバイルで最低44x44px、コンパクトデスクトップで24x24px)、スペーシング、ブレークポイントごとのフォントメトリクス。
- アクセシビリティ&キーボードマッピング: ARIA属性(
role="spinbutton"、aria-valuenow、aria-valuemin、aria-valuemax)、ライブリージョン設定、キーボードショートカットハンドラー仕様。
ワークフロー
1. ステッパーバリアントの選択
コンテキストとインタラクションの意図に基づいて、適切な構造バリアントを選択します:
- 標準水平ステッパー(3パーツセグメント): 左側に減分ボタン(
-)、中央にテキスト入力、右側に増分ボタン(+)。EコマースのPDP、カートアイテム、SaaSシートカウンターに最適です。 - コンパクトインラインステッパー(積み重ね矢印): テキスト入力と、後続側に垂直に積み重ねられたマイクロボタン。高密度のデスクトップデータテーブル、ツールバー、SaaS設定サイドバーパネルに最適です。
- 単位付き入力: 固定の接頭辞/接尾辞単位ラベル(例:
$、USD、px、%)とオプションのステッパーボタンを備えたテキストフィールド。財務入力やシステム設定フォームに最適です。 - スタンドアロンボタンカウンター: 完全にクリック可能なピル型で、タップするとインラインモーダル/ポップオーバーが開くか、フォーカス時にアクティブなステッパーに変形します。
2. ビジュアルアナトミーとタッチターゲットルールの確立
明確な幾何学的パラメータを使用してコンポーネントを構造化します:
- タッチターゲット寸法: モバイル/タッチインターフェースでは、すべてのインタラクティブな増分/減分ボタンが最低 44x44px のヒットターゲットを確保します(WCAG 2.5.5 / 2.5.8)。デスクトップ専用のコンパクトUIでは、少なくとも 24x24px と適切なヒットパディングを維持します。
- 入力フィールドサイズ設定: 期待される最大桁数に基づいてCSS
ch単位を使用して動的に幅を設定します(例: 2桁の数量にはwidth: calc(3ch + 2rem))。 - タイポグラフィ&配置: 数値を入力フィールド内で中央揃えにします。タブラーニューメリック(
font-variant-numeric: tabular-nums;)を使用して、値の急速な遷移時のレイアウトシフトを防ぎます。 - 視覚的グループ化: ボタンと入力を共有の境界線コンテナまたは連続したセグメントピル内に囲み、統一された機能を示します。
3. 境界動作と無効状態の定義
最小値と最大値の制限を明確に伝え、ユーザーのフラストレーションを回避します:
- 最小境界時(
value <= min):- 減分ボタンを無効にします(
disabled属性とaria-disabled="true")。 - 低コントラストの無効スタイルを適用します(例:
opacity: 0.4; cursor: not-allowed;)。 - Eコマースカートのコンテキストで
min === 1の場合、値が1のときに減分ボタンを「ゴミ箱/削除」アイコンにオプションで変換し、明細行の削除を許可します。
- 減分ボタンを無効にします(
- 最大境界時(
value >= max):- 増分ボタンを無効にします(
disabled属性とaria-disabled="true")。 - インラインヘルパーテキスト(例: 「1注文あたり最大10個」)または、ユーザーがさらに増分しようとした場合に微妙なツールチップを提供します。
- 増分ボタンを無効にします(
- 直接入力検証:
- 入力の
blur時に、範囲外の入力値を自動的に最も近い有効な制限値にクランプします(例: 最大値10のフィールドに99と入力すると10にクランプ)。 - ステップ増分が整数でない場合(例:
step="0.5")、blur時に入力値を最も近い有効なステップ増分に丸めます。
- 入力の
4. キーボードナビゲーションとタッチフィードバックの実装
入力デバイス全体でシームレスな制御を保証します:
- キーバインディング:
ArrowUp/ArrowRight: 値をstepだけ増分。ArrowDown/ArrowLeft: 値をstepだけ減分。PageUp: 値をstep * 10(またはより大きなステップデルタ)だけ増分。PageDown: 値をstep * 10だけ減分。Home: 値をminに設定(定義されている場合)。End: 値をmaxに設定(定義されている場合)。
- 長押し自動リピート: ユーザーが増分/減分ボタンを(ポインターまたはキーボードで)押し続けると、500msの初期遅延後に値の自動リピートを開始し、100msごとにサイクルします。
- タッチ/モバイルキーボード:
<input>要素にinputmode="numeric"またはinputmode="decimal"とpattern="[0-9]*"を設定して、モバイルデバイスで標準のネイティブブラウザスピナーを強制せずに数値キーパッドをトリガーします。
5. アクセシビリティとスクリーンリーダーセマンティクスの設定
WCAG 2.1 / 2.2 AA 準拠のエクスペリエンスを提供します:
- セマンティックHTMLオプション:
- オプションA(ステッパーボタン付きネイティブ入力): 明示的な
<label>に関連付けられた<input type="text" inputmode="numeric">を使用。増分/減分ボタンには<button type="button" aria-label="数量を減らす">とaria-controls="input-id"を付けます。 - オプションB(ARIA Spinbuttonロール): コンテナまたは入力に
role="spinbutton"、aria-valuenow="3"、aria-valuemin="1"、aria-valuemax="10"、aria-valuetext="3 seats"、aria-label="シート数を選択"を適用します。
- オプションA(ステッパーボタン付きネイティブ入力): 明示的な
- フォーカスリング管理: アクティブなボタンとテキスト入力の周りに、可視性が高くコントラストの高いフォーカスリング(
outline: 2px solid var(--focus-ring); outline-offset: 2px;)を維持します。フォーカスリングは親コンテナの境界線によって隠されたりクリップされたりしてはなりません。 - ライブリージョン通知:
aria-live="polite"を使用するか、aria-valuenowを動的に更新して、支援技術がボタン押下時に値の変更を即座に通知できるようにします。
決定ルール
コンポーネントパターンマトリックス
| ユースケース | 推奨バリアント | ボタン配置 | 最小/最大戦略 |
|---|---|---|---|
| EコマースPDP | 標準水平 | 両側(- 左、+ 右) | 最小 = 1(または1でゴミ箱)、最大 = 在庫制限 |
| カート明細行 | コンパクト水平 / ゴミ箱ハイブリッド | 両側(-/ゴミ箱 左、+ 右) | 最小 = 0(アイテムを削除)、最大 = 利用可能在庫 |
| SaaS請求シート | 単位接尾辞付き水平 | 両側(- 左、+ 右) | 最小 = 最小プラン層、最大 = アカウント上限 |
| デスクトップデータテーブル | 積み重ねインラインステッパー | 後続積み重ね(▲ 上、▼ 下) | 最小/最大はBlur時にクランプ |
| 金融金額 | 単位付き入力($) | オプションの両側、または手動のみ | 最小 = 0、最大 = 制限(検証メッセージ付き) |
直接入力 vs. ボタンのみルール
- 直接入力を許可(デフォルト): 数量が5を超える場合、またはユーザーが大きな数値を直接入力する可能性がある場合(例: 50個の注文、$500の予算設定)。
- ボタンのみに制限(
readonly入力): 値の範囲が非常に小さい場合(例: 1から5)のみで、自由形式のテキスト入力が小さなタッチデバイスで不必要な検証オーバーヘッドを引き起こす場合。
制約
- アクセシビリティ(WCAG 2.1 / 2.2 AA):
- ボタンにはアクションを説明する明示的な
aria-label属性を提供する必要があります(例: 「アイテム数量を減らす」)。 - 増分ボタンと減分ボタンは、タッチビューポートで最低 44x44px のタッチターゲットを維持する必要があります(SC 2.5.8)。
- アクティブなフォーカスインジケーターは、WCAG 2.4.11(フォーカスが隠されていない)およびSC 2.4.13(フォーカス外観)を満たす必要があります。
- ボタンにはアクションを説明する明示的な
- 数値フォーマット:
- blur時に空白や
NaN値を入力に残さない。minまたは前回の有効な値にフォールバックします。 - 数値は
font-variant-numeric: tabular-nums;を使用してレンダリングし、増分時のレイアウトリフローを防ぎます。
- blur時に空白や
- モバイルソフトキーボード:
- iOS/Androidで標準の数値キーパッドを開くために、常に
inputmode="numeric"(またはdecimal)を設定します。CSSでネイティブスピナーを無効にすることで(::-webkit-inner-spin-button)、ネイティブの<input type="number">のデフォルトの矢印スタイルを回避します。
- iOS/Androidで標準の数値キーパッドを開くために、常に
一般的な失敗パターン
- 小さく非標準のタッチターゲット: モバイルで18x18pxのシェブロンボタンを使用し、誤タップやユーザーのフラストレーションを引き起こす。
- ネイティブブラウザ
<input type="number">への依存: ブラウザデフォルトのスピナーが不統一にレンダリングされ、カスタムテキストパディングと重なったり、意図しないスクロール調整を引き起こしたりするのを許容する。 - 境界無効化の手がかりの欠落:
value === minのときに減分ボタンを視覚的にアクティブなままにし、ユーザーがフィードバックなしにクリックしてしまう。 - クランプされていない自由形式入力: ユーザーが無効な値(例:
-5、999999)を入力しても、blur時にクランプやエラーフィードバックを行わない。 - キーボードサポートの欠落:
Tabフォーカス可能性とArrowUp/ArrowDownイベント処理を欠いたカスタム<div>ボタンを設計する。
検証基準
- 減分ボタンと増分ボタンがタッチビューポートで最低44x44pxのタッチターゲットを満たしている。
- タブラーニューメリック(
tabular-nums)タイポグラフィを使用して、更新時のレイアウトジッターを防止している。 - 最小値と最大値の制限で、それぞれのボタンが無効状態(
aria-disabled="true")に遷移する。 - モバイル入力が
inputmode="numeric"またはinputmode="decimal"を使用している。 - コンポーネントが
ArrowUp、ArrowDown、PageUp、PageDown、Home、Endキーを正しく処理する。 - プログラムによるラベル(
aria-labelまたは<label>)とARIAロール(role="spinbutton"または明示的なaria-controlsボタン)が設定されている。 - 範囲外の入力値が
blur時に自動クランプされるか、検証エラーメッセージをトリガーする。 - ハイコントラストのフォーカスインジケーターが可視であり、隠されていない。