週間カレンダーWeekViewExperimental
週単位の時間グリッドに予定を配置し、重なった予定を横並びで表示します。
プレビュー
月22
火23
水24
木25
金26
8:00
9:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
撮影
進行中6/24 15:00-18:00 / スタジオ 2
キャンペーン用キービジュアルと商品カットを撮影します。
- 担当
- 担当: 撮影チーム
- 表示範囲
- 平日表示
状態とバリエーション
平日表示
dayCount=5 と weekStartsOn=1 で月曜始まりの平日表示にします。
月22
火23
水24
木25
金26
8:00
9:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
撮影
進行中6/24 15:00-18:00 / スタジオ 2
キャンペーン用キービジュアルと商品カットを撮影します。
- 担当
- 担当: 撮影チーム
- 表示範囲
- 平日表示
7日表示
週末も含める場合は dayCount=7 を使います。
月22
火23
水24
木25
金26
土27
日28
8:00
9:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
撮影
進行中6/24 15:00-18:00 / スタジオ 2
キャンペーン用キービジュアルと商品カットを撮影します。
- 担当
- 担当: 撮影チーム
- 表示範囲
- 7日表示
重なり予定
同時間帯の予定は列内で横並びになります。
月22
火23
水24
木25
金26
8:00
9:00
10:00
11:00
12:00
編集会議
議題確定6/22 09:00-10:30 / 編集室 A
週次企画の優先順位と公開枠を確認します。
- 担当
- 担当: 青井
- 表示範囲
- 午前の重なり
プロパティ
表は横にスクロールできます
| プロパティ | 型 | 初期値 | 説明 |
|---|---|---|---|
| weekOf | string | Date | - | 表示する週に含まれる日付です。 |
| events | WeekEvent[] | - | 開始、終了、ラベル、toneを持つ予定です。重なりは横並びになります。 |
| dayCount | number | 7 | 表示する日数です。5で平日表示になります。 |
| weekStartsOn | 0 | 1 | 0 | 週の開始曜日です。 |
| startHour / endHour | number | 8 / 21 | 表示する時間帯です。 |
| weekdayLabels / daySuffix | string[] / string | - | 曜日ヘッダーと読み上げ用の曜日接尾辞です。 |
| formatEventAriaLabel | function | - | 予定ボタンの読み上げ名を上書きします。関数propのため Client Component からのみ渡すこと(Server Component から渡すと next build が落ちる)。event+context から合成するため serializable な代替は無く、RSC からは "use client" ラッパーで包む。(#338) |
| onSelectEvent | (event: WeekEvent) => void | - | 予定を選択した時に呼ばれます。 |
使い方
import * as React from "react";
import { Badge, WeekView, type WeekEvent } from "@gunjo/ui";
const events: WeekEvent[] = [
{ id: "e1", start: "2026-06-22T09:00", end: "2026-06-22T10:30", label: "編集会議", tone: "info" },
{ id: "e2", start: "2026-06-22T10:00", end: "2026-06-22T11:00", label: "1on1", tone: "primary" },
{ id: "e3", start: "2026-06-23T13:00", end: "2026-06-23T15:00", label: "素材レビュー", tone: "warning" },
{ id: "e4", start: "2026-06-24T15:00", end: "2026-06-24T18:00", label: "撮影", tone: "success" },
{ id: "e5", start: "2026-06-26T10:00", end: "2026-06-26T11:30", label: "公開判定", tone: "destructive" },
];
const details = {
e1: { time: "6/22 09:00-10:30", location: "編集室 A", owner: "担当: 青井", status: "議題確定", summary: "週次企画の優先順位と公開枠を確認します。" },
e2: { time: "6/22 10:00-11:00", location: "オンライン", owner: "担当: 田中", status: "準備済み", summary: "進行中タスクとレビュー待ちの相談枠です。" },
e3: { time: "6/23 13:00-15:00", location: "レビュー卓", owner: "担当: 佐藤", status: "確認中", summary: "公開前素材の差し替え候補と権利表記を確認します。" },
e4: { time: "6/24 15:00-18:00", location: "スタジオ 2", owner: "担当: 撮影チーム", status: "進行中", summary: "キャンペーン用キービジュアルと商品カットを撮影します。" },
e5: { time: "6/26 10:00-11:30", location: "会議室 C", owner: "担当: 公開判定会", status: "要承認", summary: "公開可否、影響範囲、未解決タスクを最終確認します。" },
};
export function WeeklySchedule() {
const [selectedEventId, setSelectedEventId] = React.useState("e4");
const selectedEvent = events.find((event) => event.id === selectedEventId)!;
const detail = details[selectedEventId as keyof typeof details];
return (
<div className="flex w-full max-w-5xl flex-col gap-3 rounded-lg border bg-card p-4">
<WeekView weekOf="2026-06-24" today="2026-06-24" events={events} weekStartsOn={1} dayCount={5} startHour={8} endHour={19} label="週表示カレンダー" onSelectEvent={(event) => setSelectedEventId(event.id)} />
<section className="grid min-w-0 gap-3 rounded-md border bg-background p-3" aria-live="polite" aria-label="選択中予定の詳細">
<div className="min-w-0 space-y-1.5">
<div className="flex flex-wrap items-center gap-2">
<h3 className="text-sm font-semibold text-foreground">{selectedEvent.label}</h3>
<Badge variant="secondary">{detail.status}</Badge>
</div>
<p className="text-xs text-muted-foreground">{detail.time} / {detail.location}</p>
<p className="text-sm text-foreground">{detail.summary}</p>
</div>
<dl className="grid min-w-0 gap-2 rounded-md bg-muted/40 p-3 text-xs">
<div><dt className="text-muted-foreground">担当</dt><dd className="font-medium text-foreground">{detail.owner}</dd></div>
<div><dt className="text-muted-foreground">表示範囲</dt><dd className="font-medium text-foreground">平日表示</dd></div>
</dl>
</section>
</div>
);
}