数値入力
stimeo--number-input
スピンボタン。step 刻みの増減・範囲クランプ・端でのボタン無効化を担う。
stimeo--number-input コントローラは、APG の Spinbutton パターンを実装します。ステップ処理を自前で持つため(ブラウザのネイティブ増減に委ねない)、ネイティブの <input type="number"> でもカスタムの role="spinbutton" でも挙動が同一です。矢印で step、PageUp/PageDown で pageStep、Home/End で有限の min/max へ移動し、入力値は change 時にクランプ+ステップ正規化されます。増減ボタンは範囲端で disabled になり(直前に入力欄へフォーカスを戻す)、確定ごとに stimeo--number-input:change を発火します。
キーボード操作
| キー | 動作 |
|---|---|
| ↑ / ↓ | 1 ステップ増やす / 減らす。 |
| PageUp / PageDown | ページステップ(既定は step × 10)で増減。 |
| Home / End | 最小 / 最大へジャンプ。 |
<%# Markup for the number-input (APG Spinbutton) demo.
Increment/decrement buttons and the arrow keys step by `step`, clamped to min/max.
The input is the only tab stop (buttons are tabindex="-1"); a button is disabled at
its boundary. %>
<div class="number-input-demo" data-controller="stimeo--number-input"
data-stimeo--number-input-min-value="0"
data-stimeo--number-input-max-value="10"
data-stimeo--number-input-step-value="1">
<button type="button" class="number-input-demo__btn"
aria-label="<%= t('components.number_input.demo.decrease') %>" tabindex="-1"
data-stimeo--number-input-target="decrement"
data-action="click->stimeo--number-input#decrement">
<svg class="demo-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</button>
<input type="number" class="number-input-demo__input" min="0" max="10" step="1" value="1"
aria-label="<%= t('components.number_input.demo.quantity') %>"
data-stimeo--number-input-target="input"
data-action="change->stimeo--number-input#onInput
keydown->stimeo--number-input#onKeydown" />
<button type="button" class="number-input-demo__btn"
aria-label="<%= t('components.number_input.demo.increase') %>" tabindex="-1"
data-stimeo--number-input-target="increment"
data-action="click->stimeo--number-input#increment">
<svg class="demo-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</button>
</div>
/*
* Presentation-only styles for the number-input demo.
* Disabling at the boundary is expressed with native :disabled (the library sets disabled).
*/
.number-input-demo {
display: inline-flex;
align-items: stretch;
border: 1px solid var(--border-interactive);
border-radius: 0.375rem;
overflow: hidden;
}
.number-input-demo__btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2.25rem;
color: var(--fg);
background: var(--bg);
border: 0;
cursor: pointer;
transition: background 0.15s ease, color 0.15s ease;
}
.number-input-demo__btn:hover:not(:disabled) {
background: var(--color-primary-soft);
color: var(--accent);
}
.number-input-demo__btn:disabled {
color: var(--slate-300);
cursor: not-allowed;
}
.number-input-demo__input {
width: 3.5rem;
padding: 0.5rem 0.25rem;
font-size: 1rem;
text-align: center;
color: var(--fg);
background: var(--bg);
border: 0;
border-left: 1px solid var(--border);
border-right: 1px solid var(--border);
/* Hide the native spin buttons (this demo uses its own buttons). */
-moz-appearance: textfield;
appearance: textfield;
}
.number-input-demo__input::-webkit-outer-spin-button,
.number-input-demo__input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.number-input-demo__input:focus-visible {
outline: 2px solid var(--accent);
outline-offset: -2px;
}
.number-input-demo__btn .demo-icon {
width: 1.1rem;
height: 1.1rem;
}
このデモに固有の消費側 JS はありません(挙動はコントローラが担います)。
これらのスタイルは共通のデザイントークン(ライト/ダーク両対応)を使います。 共通スタイルも一緒にコピーし、ルート要素の data-theme を切り替えればダークになります。
このコンポーネントを動かすために HTML へ記述する data-* 属性です。ルート要素に下の data-controller を付け、その内側に各 target / value / action を配置します。
ルート要素に付与
data-controller="stimeo--number-input"
ターゲット
| 名前 | 説明 | 属性 |
|---|---|---|
input
必須
|
数値入力欄(ネイティブ input または role=spinbutton)。唯一のタブストップで値を保持する。 |
data-stimeo--number-input-target="input" |
increment
|
増加ボタン。step 分だけ増やし、上限で disabled になる。 | data-stimeo--number-input-target="increment" |
decrement
|
減少ボタン。step 分だけ減らし、下限で disabled になる。 | data-stimeo--number-input-target="decrement" |
値(Values)
| 名前 | 説明 | 属性 |
|---|---|---|
min
|
下限値(既定は -Infinity)。スナップの基準兼 Home の移動先。 | data-stimeo--number-input-min-value |
max
|
上限値(既定は +Infinity)。End の移動先。 | data-stimeo--number-input-max-value |
step
|
矢印・ボタン1回あたりの増減幅(既定1)。スナップ刻みも兼ねる。 | data-stimeo--number-input-step-value |
pageStep
|
PageUp/PageDown の増減幅。0(既定)なら step × 10 を使う。 | data-stimeo--number-input-page-step-value |
アクション
| 名前 | 説明 | アクション |
|---|---|---|
decrement
|
値を1ステップ減らし、フォーカスを input に保つ。 | stimeo--number-input#decrement |
increment
|
値を1ステップ増やし、フォーカスを input に保つ。 | stimeo--number-input#increment |
onInput
|
change 時に入力値をクランプし step 刻みにスナップする。 | stimeo--number-input#onInput |
onKeydown
|
APG スピンボタンのキー操作(矢印・Page・Home/End)を処理する。 | stimeo--number-input#onKeydown |
イベント
| 名前 | 説明 | イベント |
|---|---|---|
change
|
確定した変更ごとに発火。detail に新しい値を載せる。 | stimeo--number-input:change |
状態フック
ライブラリが操作するのはこれらの ARIA / data 属性、カスタムプロパティだけです。見た目は利用側 CSS がこれらに反応して作ります([aria-selected] / [aria-expanded] / var(--stimeo--…) などのセレクタでフックします)。
| フック | 対象 | 意味 |
|---|---|---|
value |
入力欄 | クランプ・ステップ正規化後の現在値。 |
disabled |
増加 / 減少ボタン | 範囲外になる方向のボタンに付与。 |