時刻選択
stimeo--time-picker
時 / 分 / AM / PM のセグメント(spinbutton)で 24 時間表記の値を合成する時刻入力。
stimeo--time-picker コントローラは各セグメント(時 / 分 / 任意で秒 / 任意で AM / PM)を APG Spinbutton として扱い、HH:MM[:SS] の値を隠し input に合成します(12 時間制で編集しても、値は常に 24 時間表記)。矢印キーでフォーカス中のセグメントを増減し、端ではラップします。ラップを有効にすると、あふれは分→時(秒→分)へ繰り上がります。左右でセグメント間を移動、Home/End で端へジャンプ、数字キーで直接入力でき、2 桁入力後に次のセグメントへ進みます。各セグメントは独立したタブストップです。ライブラリは挙動のみを提供します。
キーボード操作
| キー | 動作 |
|---|---|
| ↑ / ↓ | フォーカス中のセグメントを増減(このデモは step=5 のため分は 5 分刻み・端でラップ)。 |
| ← / → | 前 / 次のセグメントへ移動。 |
| Home / End | フォーカス中のセグメントを最小 / 最大へジャンプ。 |
| 0〜9 | 値を直接入力。2 桁入力後に次のセグメントへ進む。 |
<%# Markup for the time-picker (time selection) demo.
stimeo--time-picker treats each segment (hour / minute / AM·PM) as an APG Spinbutton,
handling arrow-key increment/decrement, edge wrap and carry (minute→hour), left/right
segment movement, and direct numeric entry, and reflects the composed 24-hour value
(HH:MM) into a hidden input. Each segment is an independent tab stop. %>
<div
class="time-picker"
data-controller="stimeo--time-picker"
data-stimeo--time-picker-hour-cycle-value="12"
data-stimeo--time-picker-step-value="5"
role="group"
aria-label="<%= t("components.time_picker.demo.group_label") %>">
<span class="time-picker__segment" role="spinbutton"
aria-label="<%= t("components.time_picker.demo.hours") %>"
tabindex="0" aria-valuenow="9" aria-valuemin="1" aria-valuemax="12" aria-valuetext="09"
data-segment="hour" data-stimeo--time-picker-target="segment"
data-action="keydown->stimeo--time-picker#onKeydown">09</span>
<span class="time-picker__colon" aria-hidden="true">:</span>
<span class="time-picker__segment" role="spinbutton"
aria-label="<%= t("components.time_picker.demo.minutes") %>"
tabindex="0" aria-valuenow="30" aria-valuemin="0" aria-valuemax="59" aria-valuetext="30"
data-segment="minute" data-stimeo--time-picker-target="segment"
data-action="keydown->stimeo--time-picker#onKeydown">30</span>
<span class="time-picker__segment time-picker__segment--meridiem" role="spinbutton"
aria-label="<%= t("components.time_picker.demo.meridiem") %>"
tabindex="0" aria-valuenow="0" aria-valuemin="0" aria-valuemax="1" aria-valuetext="AM"
data-segment="meridiem" data-stimeo--time-picker-target="segment"
data-action="keydown->stimeo--time-picker#onKeydown">AM</span>
<input type="hidden" name="time" data-stimeo--time-picker-target="field" />
</div>
/*
* Presentation-only styles for the time-picker demo.
* Each segment is an independent spinbutton (tab stop). Formatting and composition are
* the library's.
*/
.time-picker {
display: inline-flex;
align-items: center;
gap: 0.125rem;
padding: 0.5rem 0.75rem;
border: 1px solid var(--border);
border-radius: 0.5rem;
background: var(--surface, var(--surface-card));
font-variant-numeric: tabular-nums;
font-size: 1.25rem;
}
.time-picker__segment {
min-width: 1.75rem;
padding: 0.125rem 0.25rem;
text-align: center;
border-radius: 0.25rem;
cursor: ns-resize;
user-select: none;
}
.time-picker__segment--meridiem {
margin-left: 0.375rem;
cursor: pointer;
}
/* Invert the focused segment on :focus (not just :focus-visible) so a mouse click —
not only keyboard focus — clearly shows which segment the arrow keys / typing act on. */
.time-picker__segment:focus {
outline: none;
background: var(--accent);
color: var(--white);
}
.time-picker__colon {
color: var(--text-muted, var(--color-text-muted));
}
// Demo that subscribes to the time-picker change event to inspect the composed 24-hour
// value (HH:MM). Shows that even when operated in 12-hour mode (AM/PM), the hidden input
// holds the 24-hour value.
document.querySelectorAll('[data-controller~="stimeo--time-picker"]').forEach((root) => {
root.addEventListener('stimeo--time-picker:change', (e) => {
// In real use, e.detail.value ("HH:MM") feeds form submission, etc.
console.log('time value (24h):', e.detail.value);
});
});
これらのスタイルは共通のデザイントークン(ライト/ダーク両対応)を使います。 共通スタイルも一緒にコピーし、ルート要素の data-theme を切り替えればダークになります。
このコンポーネントを動かすために HTML へ記述する data-* 属性です。ルート要素に下の data-controller を付け、その内側に各 target / value / action を配置します。
ルート要素に付与
data-controller="stimeo--time-picker"
ターゲット
| 名前 | 説明 | 属性 |
|---|---|---|
segment
必須
|
時刻セグメント(時・分・秒・午前午後)。APG スピンボタンで各自タブストップ。 | data-stimeo--time-picker-target="segment" |
field
必須
|
合成した24時間表記 HH:MM[:SS] を保持する隠しフィールド。 | data-stimeo--time-picker-target="field" |
値(Values)
| 名前 | 説明 | 属性 |
|---|---|---|
hourCycle
|
12時間制か24時間制か(既定24)。12 で午前午後セグメントを使う。 | data-stimeo--time-picker-hour-cycle-value |
step
|
分の刻み幅(既定1)。他セグメントは1刻み。 | data-stimeo--time-picker-step-value |
seconds
|
true で秒セグメントを値に含める(既定 false)。 | data-stimeo--time-picker-seconds-value |
wrap
|
true(既定)で境界越えがラップし、上位単位へ繰り上がる。 | data-stimeo--time-picker-wrap-value |
アクション
| 名前 | 説明 | アクション |
|---|---|---|
onKeydown
|
上下のステップ、左右のセグメント移動、Home/End、数字直接入力を処理する。 | stimeo--time-picker#onKeydown |
イベント
| 名前 | 説明 | イベント |
|---|---|---|
change
|
合成値が実際に変わると発火。detail に値を載せる。 | stimeo--time-picker:change |
状態フック
ライブラリが操作するのはこれらの ARIA / data 属性、カスタムプロパティだけです。見た目は利用側 CSS がこれらに反応して作ります([aria-selected] / [aria-expanded] / var(--stimeo--…) などのセレクタでフックします)。
| フック | 対象 | 意味 |
|---|---|---|
aria-valuenow |
セグメント | そのセグメントの現在値。 |
aria-valuetext |
セグメント | ゼロ埋めの表示文字列(例 09)、または AM / PM。 |
value |
隠し input | 合成された 24 時間表記の HH:MM[:SS] 値。 |