いちにちの帯DayBandExperimental
1日を1本の帯にして、時間帯を面で、節目を印で、いまの時刻とつまみの位置を重ねて見せます。日の出も「いま」も呼び出し側が渡す数で、部品は1日について何も計算しません。
プレビュー
東京 9月12日14:30
日の出 05:22日の入 17:56いま
06121824
状態とバリエーション
TimeTransport の中に入れる
操作盤の scrubber スロットへ差し込んだ形。帯を掴めば時刻が動き、「いまへ戻る」で戻ります。この組み合わせのために作られた部品です。⚠️ ここでの単位は「分」なので、TimeTransport の liveTolerance も分で渡しています(既定の 1000 はエポックミリ秒の1秒ぶんです)。
14:30
2026-09-12 JST
日の出 05:22日の入 17:56いま
06121824
当番表
同じ形で当番表になります。時間帯にトーン名を渡すと、面のトークン(--*-subtle)へ解決します。節目の印は交代の時刻です。
3階病棟 9月12日14:30
交代 08:00交代 18:00
06121824
見せるだけ(sm)
onValueChange を渡さなければ操作を受け取らず、焦点も持ちません。value も外せば、つまみのない営業時間の帯になります。size="sm" は 24px です。
営業時間11:00 – 22:00
ラストオーダー 21:00
06121824
掴んで流す(relative)
触っただけでは動かず、掴んだ距離ぶんだけ動きます。細い帯で指が現在位置を隠さず、誤って触っても時刻が飛びません。0時をまたぐと帯の外の値も返るので、呼び出し側が日を入れ替えます。
14:30
日の出 05:22日の入 17:56いま
06121824
いちばん小さい形
時間帯だけ。印も時刻の数字も目盛りも外せます(marks を渡さず、hourLabels={[]}、tickEvery={0})。表の行の中など、狭いところに置くときの形です。
操作できない
帯全体が無効。読み取り専用の盤や、まだ日が決まっていないときに使います。
14:30
日の出 05:22日の入 17:56
06121824
プロパティ
表は横にスクロールできます
| プロパティ | 型 | 初期値 | 説明 |
|---|---|---|---|
| min / max | number / number | - | 1日の始まりと終わり。単位は呼び出し側のもので、既定は午前0時からの分です。実日付ならその日の0時のエポックミリ秒と +86400000 を渡します。phases・marks・value・now はすべてこの単位です。 |
| value | number | - | つまみが指す位置。渡さなければつまみは出ません(見せるだけの帯になります)。 |
| onValueChange | (next: number) => void | - | 掴んで動かしたときの次の位置。渡さなければ帯は操作を受け取らず、スライダーの役割も焦点も持ちません。 |
| phases | DayBandPhase[] | - | 1日の中の時間帯。{ start, end, label?, color? } で、面として敷かれます。color はトーン名(success など)か任意の CSS 色。トーンは面のトークン(--*-subtle)へ解決します。⚠️ 0時をまたぐ時間帯は2つに分けてください(22:00–24:00 と 00:00–06:00)。 |
| marks | DayBandMark[] | - | 節目の印。{ at, label?, color? }。ラベルは帯の上の行に出ます(下の行は時刻の数字なので、ぶつかりません)。色がつくのは線だけで、文字は着色しません。 |
| now | number | - | 「いま」の位置。印として描かれるので、動かしたあとも戻り先が見えます。⚠️ 時刻は effect の中で読んでください(部品は時計を持ちません)。 |
| scrub | "absolute" | "relative" | - | absolute は触った位置がそのまま時刻(ひと触りでどの時刻へも行けます)。relative は掴んだ距離ぶんだけ動く(指が現在位置を隠さず、触っただけでは動きません)。relative は0時をまたいで帯の外の値も返すので、呼び出し側が日を入れ替えます。 |
| step / coarseStep | number / number | - | 矢印キーの刻みと、Shift+矢印・PageUp / PageDown の刻み。既定は15分と1時間ぶんです。Home / End は帯の両端へ飛びます。 |
| tickEvery | number | - | 帯の中に立てる目盛りの間隔(時間)。0 で消えます。 |
| hourLabels / formatHour | number[] / (hour: number) => ReactNode | - | 帯の下に出す時刻の数字と、その書式。既定は単位なしの数字なので、そのまま多言語に出せます。[] で行ごと消えます。 |
| formatValue | (value: number) => string | - | 読み上げ(aria-valuetext)の書式。既定は1日の中の位置から出した HH:MM で、時間帯の名前が「10:40 · 昼」のように続きます。 |
| size | "sm" | "default" | - | 帯の高さ。default は触れる 44px、sm は 24px で、見せるだけの帯に使います。 |
| label / hint | ReactNode / ReactNode | - | 帯の上の行。左が label(地点・日付・担当)、右が hint(いまの時刻・注記・合計)。現在時刻を出したいときは hint に渡します。 |
| labels | DayBandLabels | - | 組み込みの文字列の差し替え(band=帯の読み上げ名/now=「いま」の印の名前)。既定は英語です。 |
| disabled | boolean | - | 帯を無効にし、タブ移動からも外します。 |
使い方
import { DayBand } from "@gunjo/ui";
// 既定の単位は「午前0時からの分」(min 0 / max 1440)。
// 実日付で使うなら min にその日の0時のエポックミリ秒、max に +86400000 を渡します。
export function SunBand() {
const [value, setValue] = React.useState(640);
return (
<DayBand
value={value}
onValueChange={setValue}
// ⚠️ 日の出・日の入は呼び出し側が渡します。部品は天文計算を持ちません。
phases={[
{ start: 0, end: 260, label: "夜", color: "hsl(var(--gunjo-deepest))" },
{ start: 260, end: 322, label: "薄明", color: "hsl(var(--gunjo-deep))" },
{ start: 322, end: 1076, label: "昼", color: "hsl(var(--gunjo-bright))" },
{ start: 1076, end: 1138, label: "薄明", color: "hsl(var(--gunjo-deep))" },
{ start: 1138, end: 1440, label: "夜", color: "hsl(var(--gunjo-deepest))" },
]}
marks={[
{ at: 322, label: "日の出 05:22", color: "warning" },
{ at: 1076, label: "日の入 17:56", color: "info" },
]}
// ⚠️ いまの時刻は描画中ではなく effect の中で読んでください。
now={nowMinutes}
label="東京 9月12日"
hint={formatClock(value)}
labels={{ band: "いちにちの中の時刻", now: "いま" }}
/>
);
}
// TimeTransport の掴んで動かす面として差し込む場合
<TimeTransport value={value} now={now} onValueChange={setValue}
scrubber={<DayBand value={value} now={now} onValueChange={setValue} phases={PHASES} />} />設計の判断
- 時間帯の色は「面のトークン」へ解決します。
successのようなトーン名は、強い色ではなく--success-subtleの側へ 落とします。時間帯は下地で、その上に印とつまみが乗るからです。空のような絵としての色が要るときは、任意の CSS 色をそのまま渡せます。 - つまみは2色で描いています。下地の時間帯は明色でも暗色でもありうるので、背景色の線に前景色の縁を重ねています。 片方の色に賭けると、夜の帯か昼の帯のどちらかで必ず消えます。
- 印のラベルは帯の上、時刻の数字は帯の下。出どころの実装は1つの行に詰めていたため、印から48px以内の時刻の数字を消して衝突を避けていました。 行を分ければ、消す必要がありません。
- 指で触ったときは、押した瞬間には動きません。押した指がそのまま縦スクロールに変わることがあるためで、動かしたときか、指を離したとき (=はっきりした「触った」)に確定します。マウスとペンは押した瞬間です。 帯の上から始めた縦スクロールも止めません(
touch-action: pan-y)。 - 色だけに意味を載せません。読み上げには「10:40 · 昼」のように時間帯の名前が乗り、節目は文字のラベルを 持ち、時間帯にはポインタで読める名前がつきます。矢印・Shift+矢印・PageUp / PageDown・ Home / End で、触らずに1日を歩けます。
- 0時をまたぐ時間帯は2つに分けます。1本の帯は1日です。
startがend以上の時間帯は描かず、開発時に 警告を出します(黙って反対側を塗るより、言うほうが正しいためです)。