@godxjp/ui 19.2.0 → 19.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/dist/components/data-display/badge.d.ts +26 -2
  2. package/dist/components/data-display/badge.js +20 -5
  3. package/dist/components/data-display/index.d.ts +2 -0
  4. package/dist/components/data-display/index.js +2 -0
  5. package/dist/components/data-display/popover.d.ts +13 -1
  6. package/dist/components/data-display/popover.js +3 -1
  7. package/dist/components/data-display/table.d.ts +19 -2
  8. package/dist/components/data-display/table.js +4 -1
  9. package/dist/components/data-display/timeline-grid.d.ts +18 -0
  10. package/dist/components/data-display/timeline-grid.js +222 -0
  11. package/dist/components/data-entry/cascader.js +4 -6
  12. package/dist/components/data-entry/checkbox.js +1 -1
  13. package/dist/components/data-entry/search-select.js +5 -7
  14. package/dist/components/data-entry/select.js +32 -28
  15. package/dist/components/data-entry/tree-select.js +4 -6
  16. package/dist/components/general/inert-background.d.ts +5 -0
  17. package/dist/components/general/inert-background.js +48 -0
  18. package/dist/components/layout/auth-shell.d.ts +4 -2
  19. package/dist/components/layout/auth-shell.js +7 -1
  20. package/dist/components/layout/centered-shell.d.ts +2 -2
  21. package/dist/components/layout/flex.d.ts +1 -1
  22. package/dist/components/layout/flex.js +2 -1
  23. package/dist/components/layout/index.d.ts +3 -0
  24. package/dist/components/layout/index.js +2 -0
  25. package/dist/components/layout/mobile-shell.d.ts +21 -0
  26. package/dist/components/layout/mobile-shell.js +43 -0
  27. package/dist/components/layout/sidebar-link.d.ts +1 -1
  28. package/dist/components/navigation/context-menu.js +13 -9
  29. package/dist/components/navigation/dropdown-menu.js +17 -13
  30. package/dist/inertia/index.d.ts +1 -1
  31. package/dist/lib/variants.d.ts +3 -3
  32. package/dist/lib/variants.js +1 -0
  33. package/dist/props/components/data-display.prop.d.ts +72 -0
  34. package/dist/props/components/data-entry.prop.d.ts +1 -1
  35. package/dist/props/components/layout.prop.d.ts +93 -6
  36. package/dist/props/registry.d.ts +113 -2
  37. package/dist/props/registry.js +155 -1
  38. package/dist/props/vocabulary/data.prop.d.ts +6 -0
  39. package/dist/props/vocabulary/index.d.ts +3 -3
  40. package/dist/props/vocabulary/layout.prop.d.ts +17 -2
  41. package/dist/props/vocabulary/shared.prop.d.ts +7 -0
  42. package/dist/styles/badge-layout.css +15 -0
  43. package/dist/styles/control.css +18 -1
  44. package/dist/styles/data-display-layout.css +167 -0
  45. package/dist/styles/layout.css +7 -0
  46. package/dist/styles/shell-layout.css +148 -0
  47. package/dist/styles/table-layout.css +23 -4
  48. package/dist/tokens/components/badge.css +8 -0
  49. package/dist/tokens/components/control.css +1 -0
  50. package/dist/tokens/components/data-display.css +20 -0
  51. package/dist/tokens/components/shell.css +22 -0
  52. package/dist/tokens/components/table.css +2 -0
  53. package/docs/SPACING.md +19 -6
  54. package/docs/charts/compact-bar-trend.tsx +5 -6
  55. package/docs/data-display/avatar.tsx +7 -9
  56. package/docs/data-display/badge.tsx +37 -1
  57. package/docs/data-display/card/index.tsx +6 -4
  58. package/docs/data-display/carousel.tsx +8 -4
  59. package/docs/data-display/data-table/examples/approval-queue.tsx +1 -1
  60. package/docs/data-display/data-table/examples/grid-features.tsx +1 -1
  61. package/docs/data-display/data-table/index.tsx +1 -1
  62. package/docs/data-display/permission-matrix.tsx +15 -11
  63. package/docs/data-display/popover.tsx +2 -1
  64. package/docs/data-display/scroll-area.tsx +108 -76
  65. package/docs/data-display/table.tsx +2 -2
  66. package/docs/data-display/timeline-grid.tsx +119 -0
  67. package/docs/data-entry/branch-scope-picker.tsx +1 -1
  68. package/docs/data-entry/calendar.tsx +1 -1
  69. package/docs/data-entry/checkbox.tsx +1 -1
  70. package/docs/data-entry/country-picker-recipe.tsx +11 -6
  71. package/docs/data-entry/form-field/index.tsx +33 -29
  72. package/docs/data-entry/form-root.tsx +1 -1
  73. package/docs/data-entry/input-otp.tsx +1 -1
  74. package/docs/data-entry/password-input.tsx +1 -5
  75. package/docs/data-entry/select.tsx +7 -7
  76. package/docs/data-entry/textarea.tsx +3 -3
  77. package/docs/data-entry/toggle-count.tsx +1 -1
  78. package/docs/feedback/alert.tsx +1 -1
  79. package/docs/feedback/banner.tsx +1 -1
  80. package/docs/feedback/sheet.tsx +112 -102
  81. package/docs/feedback/skeleton.tsx +2 -2
  82. package/docs/foundation/colors.tsx +8 -6
  83. package/docs/foundation/email-tokens.tsx +83 -66
  84. package/docs/foundation/radius-shadow.tsx +13 -11
  85. package/docs/general/activity.tsx +1 -1
  86. package/docs/layout/app-shell.tsx +2 -2
  87. package/docs/layout/aspect-ratio.tsx +30 -14
  88. package/docs/layout/auth-account-summary.tsx +1 -1
  89. package/docs/layout/auth-recovery/examples/mobile-390.tsx +1 -1
  90. package/docs/layout/auth-recovery/examples/password-recovery.tsx +0 -2
  91. package/docs/layout/auth-shell-context.tsx +1 -1
  92. package/docs/layout/auth-shell-device.tsx +2 -2
  93. package/docs/layout/auth-shell-registration.tsx +1 -1
  94. package/docs/layout/auth-shell.tsx +1 -1
  95. package/docs/layout/flex.tsx +6 -2
  96. package/docs/layout/master-detail.tsx +2 -2
  97. package/docs/layout/mobile-shell.tsx +101 -0
  98. package/docs/layout/page-container.tsx +15 -7
  99. package/docs/layout/responsive-grid.tsx +12 -4
  100. package/docs/layout/separator.tsx +2 -2
  101. package/docs/layout/service-role-panel.tsx +1 -1
  102. package/docs/layout/sidebar.tsx +175 -152
  103. package/docs/layout/split-pane.tsx +45 -28
  104. package/docs/layout/topbar.tsx +19 -23
  105. package/docs/navigation/app-setting-picker.tsx +5 -4
  106. package/docs/navigation/breadcrumb.tsx +12 -5
  107. package/docs/navigation/context-menu.tsx +10 -4
  108. package/docs/navigation/filter-bar.tsx +2 -2
  109. package/docs/navigation/navigation-menu.tsx +89 -96
  110. package/docs/navigation/pagination.tsx +2 -2
  111. package/docs/navigation/steps.tsx +13 -11
  112. package/docs/navigation/tabs.tsx +27 -21
  113. package/docs/navigation/toolbar.tsx +15 -15
  114. package/docs/providers/format-date.tsx +2 -2
  115. package/docs/showcase/acme-portal.tsx +41 -28
  116. package/docs/showcase/acme-website.tsx +67 -61
  117. package/docs/showcase/case1-warehouse-dashboard.tsx +46 -31
  118. package/docs/showcase/case2-employee-me.tsx +33 -36
  119. package/docs/showcase/case3-approval-workflow.tsx +34 -32
  120. package/docs/showcase/case4-login.tsx +95 -101
  121. package/docs/showcase/case5-shift-calendar.tsx +182 -281
  122. package/docs/showcase/case6-agency-handy.tsx +514 -470
  123. package/docs/showcase/futurelastic-web.tsx +32 -29
  124. package/docs/showcase/org-switcher.tsx +20 -13
  125. package/docs/showcase/permission-matrix.tsx +20 -17
  126. package/docs/showcase/public-landing.tsx +1 -1
  127. package/docs/showcase/settings-account-sections.tsx +2 -2
  128. package/docs/showcase/settings-security-mfa.tsx +3 -3
  129. package/docs/showcase/table-approval-queue.tsx +1 -1
  130. package/docs/showcase/table-bulk-actions.tsx +49 -52
  131. package/docs/showcase/table-conditional-format.tsx +9 -9
  132. package/docs/showcase/table-crud-list.tsx +4 -4
  133. package/docs/showcase/table-density.tsx +49 -42
  134. package/docs/showcase/table-expandable-rows.tsx +112 -100
  135. package/docs/showcase/table-filter-chips.tsx +78 -71
  136. package/docs/showcase/table-footer-totals.tsx +30 -23
  137. package/docs/showcase/table-grouped-subtotals.tsx +31 -25
  138. package/docs/showcase/table-master-detail.tsx +27 -24
  139. package/docs/showcase/table-pagination.tsx +34 -27
  140. package/docs/showcase/table-states.tsx +42 -34
  141. package/docs/showcase/table-sticky-columns.tsx +11 -7
  142. package/docs/showcase/table-tree-rows.tsx +22 -15
  143. package/docs/showcase/table-view-tabs.tsx +12 -14
  144. package/package.json +7 -7
@@ -497,7 +497,7 @@ export default function Demo() {
497
497
  </CardContent>
498
498
 
499
499
  {/* Footer totals — composed from CardFooter + Badge, not a hand-rolled bar. */}
500
- <CardFooter className="flex-wrap justify-between gap-3">
500
+ <CardFooter className="flex-wrap justify-between">
501
501
  <Flex direction="row" gap="md" align="center" wrap>
502
502
  <Text size="xs" tone="muted">
503
503
  選択中{" "}
@@ -508,19 +508,19 @@ export default function Demo() {
508
508
  </Text>
509
509
  <Badge tone="success" variant="outline">
510
510
  出勤{" "}
511
- <Text as="span" tabular className="ms-1">
511
+ <Text as="span" tabular>
512
512
  {tally.present}
513
513
  </Text>
514
514
  </Badge>
515
515
  <Badge tone="warning" variant="outline">
516
516
  遅刻{" "}
517
- <Text as="span" tabular className="ms-1">
517
+ <Text as="span" tabular>
518
518
  {tally.late}
519
519
  </Text>
520
520
  </Badge>
521
521
  <Badge tone="muted" variant="outline">
522
522
  承認待ち{" "}
523
- <Text as="span" tabular className="ms-1">
523
+ <Text as="span" tabular>
524
524
  {tally.pendingApproval}
525
525
  </Text>
526
526
  </Badge>
@@ -25,12 +25,13 @@ import { Clock } from "lucide-react";
25
25
 
26
26
  import {
27
27
  Badge,
28
- type BadgeProps,
29
28
  Card,
29
+ CardAction,
30
30
  CardContent,
31
31
  CardHeader,
32
32
  CardTitle,
33
33
  DataTable,
34
+ type BadgeProps,
34
35
  type ColumnDef,
35
36
  } from "@godxjp/ui/data-display";
36
37
  import { Button, Text } from "@godxjp/ui/general";
@@ -233,44 +234,48 @@ export default function Demo() {
233
234
  <Flex direction="col" gap="lg">
234
235
  {/* Control + live readout */}
235
236
  <Card>
236
- <CardHeader className="flex flex-row items-center justify-between gap-4">
237
+ <CardHeader>
237
238
  <CardTitle level={2}>行密度</CardTitle>
238
- <Flex direction="row" align="center" gap="md">
239
- <Text as="span" size="xs" tone="muted" className="inline-flex items-center gap-1.5">
240
- <Clock className="size-3.5" aria-hidden="true" />
241
- 行高
242
- <Text as="strong" weight="medium" tabular>
243
- {meta.px}px
244
- </Text>
245
- <span aria-hidden="true">·</span>
246
- {meta.note}
247
- </Text>
248
- <ToggleGroup
249
- type="single"
250
- value={density}
251
- onValueChange={(v) => {
252
- if (v) setDensity(v as DensityKey);
253
- }}
254
- variant="outline"
255
- size="sm"
256
- aria-label="行密度を切り替え"
257
- >
258
- {DENSITY_ORDER.map((key) => (
259
- <ToggleGroupItem
260
- key={key}
261
- value={key}
262
- aria-label={`${DENSITY_META[key].label} ${DENSITY_META[key].px}px`}
263
- >
264
- <Flex direction="row" align="center" gap="xs">
265
- <span>{DENSITY_META[key].label}</span>
266
- <Text size="2xs" tone="muted" tabular>
267
- {DENSITY_META[key].px}
268
- </Text>
269
- </Flex>
270
- </ToggleGroupItem>
271
- ))}
272
- </ToggleGroup>
273
- </Flex>
239
+ <CardAction>
240
+ <Flex direction="row" align="center" gap="md">
241
+ <Flex align="center" gap="xs">
242
+ <Text as="span" size="xs" tone="muted">
243
+ <Clock className="size-3.5" aria-hidden="true" />
244
+ 行高
245
+ <Text as="strong" weight="medium" tabular>
246
+ {meta.px}px
247
+ </Text>
248
+ <span aria-hidden="true">·</span>
249
+ {meta.note}
250
+ </Text>
251
+ </Flex>
252
+ <ToggleGroup
253
+ type="single"
254
+ value={density}
255
+ onValueChange={(v) => {
256
+ if (v) setDensity(v as DensityKey);
257
+ }}
258
+ variant="outline"
259
+ size="sm"
260
+ aria-label="行密度を切り替え"
261
+ >
262
+ {DENSITY_ORDER.map((key) => (
263
+ <ToggleGroupItem
264
+ key={key}
265
+ value={key}
266
+ aria-label={`${DENSITY_META[key].label} ${DENSITY_META[key].px}px`}
267
+ >
268
+ <Flex direction="row" align="center" gap="xs">
269
+ <span>{DENSITY_META[key].label}</span>
270
+ <Text size="2xs" tone="muted" tabular>
271
+ {DENSITY_META[key].px}
272
+ </Text>
273
+ </Flex>
274
+ </ToggleGroupItem>
275
+ ))}
276
+ </ToggleGroup>
277
+ </Flex>
278
+ </CardAction>
274
279
  </CardHeader>
275
280
  <CardContent flush>
276
281
  {/* The SAME DataTable. Only the density class changes — same columns,
@@ -314,11 +319,13 @@ export default function Demo() {
314
319
  const m = DENSITY_META[key];
315
320
  return (
316
321
  <Card key={key}>
317
- <CardHeader className="flex flex-row items-center justify-between">
322
+ <CardHeader>
318
323
  <CardTitle level={2}>{m.label}</CardTitle>
319
- <Text size="xs" tone="muted" tabular>
320
- 行高 {m.px}px · {m.note}
321
- </Text>
324
+ <CardAction>
325
+ <Text size="xs" tone="muted" tabular>
326
+ 行高 {m.px}px · {m.note}
327
+ </Text>
328
+ </CardAction>
322
329
  </CardHeader>
323
330
  <CardContent flush>
324
331
  <DataTable
@@ -23,8 +23,8 @@ import { ChevronRight, Clock, Coffee, MapPin } from "lucide-react";
23
23
 
24
24
  import {
25
25
  Badge,
26
- type BadgeProps,
27
26
  Card,
27
+ CardAction,
28
28
  CardContent,
29
29
  CardHeader,
30
30
  CardTitle,
@@ -35,6 +35,7 @@ import {
35
35
  TableHead,
36
36
  TableHeader,
37
37
  TableRow,
38
+ type BadgeProps,
38
39
  } from "@godxjp/ui/data-display";
39
40
  import { Button, Text } from "@godxjp/ui/general";
40
41
  import { Flex, PageContainer } from "@godxjp/ui/layout";
@@ -249,8 +250,7 @@ const EMPLOYEES: Employee[] = [
249
250
 
250
251
  // ── Shared cell padding to match compact DataTable density ─────────────────────
251
252
 
252
- const CELL = "px-3 py-2 align-middle";
253
- const HEAD = "px-3";
253
+ const CELL = "align-middle";
254
254
 
255
255
  function StatusBadge({ status }: { status: ShiftStatus }) {
256
256
  return (
@@ -264,97 +264,105 @@ function StatusBadge({ status }: { status: ShiftStatus }) {
264
264
 
265
265
  function DetailPanel({ employee }: { employee: Employee }) {
266
266
  return (
267
- <div className="border-s-primary bg-muted/30 border-s-[3px] px-4 py-3">
268
- <Flex direction="col" gap="md">
269
- <Flex direction="row" wrap align="center" gap="md">
270
- <Text size="sm" weight="medium">
271
- {employee.name} · {employee.dept}
272
- </Text>
273
- <Text size="xs" tone="muted" className="inline-flex items-center gap-1">
274
- <MapPin className="size-3.5" aria-hidden="true" />
275
- {employee.site}
276
- </Text>
277
- </Flex>
267
+ <Card className="border-s-primary bg-muted/30 border-s-[3px]">
268
+ <CardContent solo>
269
+ <Flex direction="col" gap="md">
270
+ <Flex direction="row" wrap align="center" gap="md">
271
+ <Text size="sm" weight="medium">
272
+ {employee.name} · {employee.dept}
273
+ </Text>
274
+ <Flex align="center" gap="xs">
275
+ <Text size="xs" tone="muted">
276
+ <MapPin className="size-3.5" aria-hidden="true" />
277
+ {employee.site}
278
+ </Text>
279
+ </Flex>
280
+ </Flex>
278
281
 
279
- {/* KPI mini-row inside the panel — real StatCard primitives */}
280
- <Flex direction="row" wrap gap="sm">
281
- <StatCard label="出勤日数" value={employee.workDays} layout="inline" />
282
- <StatCard
283
- label="遅刻回数"
284
- value={employee.lateCount}
285
- layout="inline"
286
- inverse
287
- delta={employee.lateCount === 0 ? "問題なし" : "要確認"}
288
- />
289
- <StatCard
290
- label="残業 累計"
291
- value={<Text tabular>{employee.overtime}</Text>}
292
- layout="inline"
293
- />
294
- </Flex>
282
+ {/* KPI mini-row inside the panel — real StatCard primitives */}
283
+ <Flex direction="row" wrap gap="sm">
284
+ <StatCard label="出勤日数" value={employee.workDays} layout="inline" />
285
+ <StatCard
286
+ label="遅刻回数"
287
+ value={employee.lateCount}
288
+ layout="inline"
289
+ inverse
290
+ delta={employee.lateCount === 0 ? "問題なし" : "要確認"}
291
+ />
292
+ <StatCard
293
+ label="残業 累計"
294
+ value={<Text tabular>{employee.overtime}</Text>}
295
+ layout="inline"
296
+ />
297
+ </Flex>
295
298
 
296
- {/* Per-day breakdown — quiet nested list, real Card chrome */}
297
- <Card>
298
- <CardHeader className="flex flex-row items-center justify-between">
299
- <CardTitle level={2} className="text-[var(--font-size-xs)]">
300
- 今週の打刻
301
- </CardTitle>
302
- <Text size="xs" tone="muted" className="inline-flex items-center gap-1">
303
- <Clock className="size-3.5" aria-hidden="true" />
304
- 直近 3
305
- </Text>
306
- </CardHeader>
307
- <CardContent flush>
308
- <Table>
309
- <TableHeader className="bg-secondary">
310
- <TableRow>
311
- <TableHead className={HEAD}>日付</TableHead>
312
- <TableHead className={HEAD}>状態</TableHead>
313
- <TableHead className={HEAD}>出勤</TableHead>
314
- <TableHead className={HEAD}>退勤</TableHead>
315
- <TableHead className={HEAD}>休憩</TableHead>
316
- <TableHead className={`${HEAD} text-end`}>実働</TableHead>
317
- <TableHead className={HEAD}>備考</TableHead>
318
- </TableRow>
319
- </TableHeader>
320
- <TableBody>
321
- {employee.days.map((d) => (
322
- <TableRow key={d.date}>
323
- <TableCell className={`${CELL} text-xs whitespace-nowrap tabular-nums`}>
324
- {d.date}({d.weekday})
325
- </TableCell>
326
- <TableCell className={CELL}>
327
- <StatusBadge status={d.status} />
328
- </TableCell>
329
- <TableCell className={`${CELL} tabular-nums`}>{d.clockIn}</TableCell>
330
- <TableCell className={`${CELL} tabular-nums`}>{d.clockOut}</TableCell>
331
- <TableCell
332
- className={`${CELL} text-muted-foreground inline-flex items-center gap-1 tabular-nums`}
333
- >
334
- <Coffee className="size-3.5" aria-hidden="true" />
335
- {d.break}
336
- </TableCell>
337
- <TableCell className={`${CELL} text-end font-medium tabular-nums`}>
338
- {d.work}
339
- </TableCell>
340
- <TableCell className={`${CELL} text-muted-foreground text-xs`}>
341
- {d.note ?? "—"}
342
- </TableCell>
299
+ {/* Per-day breakdown — quiet nested list, real Card chrome */}
300
+ <Card>
301
+ <CardHeader>
302
+ <CardTitle level={2} className="text-[var(--font-size-xs)]">
303
+ 今週の打刻
304
+ </CardTitle>
305
+ <CardAction>
306
+ <Flex align="center" gap="xs">
307
+ <Text size="xs" tone="muted">
308
+ <Clock className="size-3.5" aria-hidden="true" />
309
+ 直近 3 日
310
+ </Text>
311
+ </Flex>
312
+ </CardAction>
313
+ </CardHeader>
314
+ <CardContent flush>
315
+ <Table>
316
+ <TableHeader className="bg-secondary">
317
+ <TableRow>
318
+ <TableHead>日付</TableHead>
319
+ <TableHead>状態</TableHead>
320
+ <TableHead>出勤</TableHead>
321
+ <TableHead>退勤</TableHead>
322
+ <TableHead>休憩</TableHead>
323
+ <TableHead className="text-end">実働</TableHead>
324
+ <TableHead>備考</TableHead>
343
325
  </TableRow>
344
- ))}
345
- </TableBody>
346
- </Table>
347
- </CardContent>
348
- </Card>
326
+ </TableHeader>
327
+ <TableBody>
328
+ {employee.days.map((d) => (
329
+ <TableRow key={d.date}>
330
+ <TableCell className={`${CELL} text-xs whitespace-nowrap tabular-nums`}>
331
+ {d.date}({d.weekday})
332
+ </TableCell>
333
+ <TableCell className={CELL}>
334
+ <StatusBadge status={d.status} />
335
+ </TableCell>
336
+ <TableCell className={`${CELL} tabular-nums`}>{d.clockIn}</TableCell>
337
+ <TableCell className={`${CELL} tabular-nums`}>{d.clockOut}</TableCell>
338
+ <TableCell className={`${CELL} text-muted-foreground tabular-nums`}>
339
+ <Flex align="center" gap="xs">
340
+ <Coffee className="size-3.5" aria-hidden="true" />
341
+ {d.break}
342
+ </Flex>
343
+ </TableCell>
344
+ <TableCell className={`${CELL} text-end font-medium tabular-nums`}>
345
+ {d.work}
346
+ </TableCell>
347
+ <TableCell className={`${CELL} text-muted-foreground text-xs`}>
348
+ {d.note ?? "—"}
349
+ </TableCell>
350
+ </TableRow>
351
+ ))}
352
+ </TableBody>
353
+ </Table>
354
+ </CardContent>
355
+ </Card>
349
356
 
350
- <Flex direction="row" gap="sm">
351
- <Button size="sm" variant="outline">
352
- 勤怠詳細を開く
353
- </Button>
354
- <Button size="sm">承認する</Button>
357
+ <Flex direction="row" gap="sm">
358
+ <Button size="sm" variant="outline">
359
+ 勤怠詳細を開く
360
+ </Button>
361
+ <Button size="sm">承認する</Button>
362
+ </Flex>
355
363
  </Flex>
356
- </Flex>
357
- </div>
364
+ </CardContent>
365
+ </Card>
358
366
  );
359
367
  }
360
368
 
@@ -374,12 +382,12 @@ function ExpandableList() {
374
382
  <Table>
375
383
  <TableHeader className="bg-secondary sticky top-0 z-10">
376
384
  <TableRow>
377
- <TableHead className={`${HEAD} w-10`} aria-label="展開" />
378
- <TableHead className={HEAD}>従業員</TableHead>
379
- <TableHead className={HEAD}>部署</TableHead>
380
- <TableHead className={`${HEAD} text-center`}>直近の状態</TableHead>
381
- <TableHead className={`${HEAD} text-end`}>出勤日数</TableHead>
382
- <TableHead className={`${HEAD} text-end`}>残業 累計</TableHead>
385
+ <TableHead className="w-10" aria-label="展開" />
386
+ <TableHead>従業員</TableHead>
387
+ <TableHead>部署</TableHead>
388
+ <TableHead className="text-center">直近の状態</TableHead>
389
+ <TableHead className="text-end">出勤日数</TableHead>
390
+ <TableHead className="text-end">残業 累計</TableHead>
383
391
  </TableRow>
384
392
  </TableHeader>
385
393
  <TableBody>
@@ -427,7 +435,9 @@ function ExpandableList() {
427
435
  </TableRow>
428
436
  {isOpen && (
429
437
  <TableRow className="hover:bg-transparent">
430
- <TableCell colSpan={COLSPAN} className="p-0" id={panelId}>
438
+ {/* `flush` — the detail panel owns its own inset, so it spans the full cell
439
+ width instead of being indented by the cell padding. */}
440
+ <TableCell flush colSpan={COLSPAN} id={panelId}>
431
441
  <DetailPanel employee={emp} />
432
442
  </TableCell>
433
443
  </TableRow>
@@ -449,11 +459,13 @@ export default function Demo() {
449
459
  >
450
460
  <Flex direction="col" gap="lg">
451
461
  <Card>
452
- <CardHeader className="flex flex-row items-center justify-between">
462
+ <CardHeader>
453
463
  <CardTitle level={2}>従業員の勤怠(今週)</CardTitle>
454
- <Text size="xs" tone="muted" tabular>
455
- 4 · 06/04 時点
456
- </Text>
464
+ <CardAction>
465
+ <Text size="xs" tone="muted" tabular>
466
+ 4 名 · 06/04 時点
467
+ </Text>
468
+ </CardAction>
457
469
  </CardHeader>
458
470
  <CardContent flush>
459
471
  <ExpandableList />
@@ -27,7 +27,14 @@ import * as React from "react";
27
27
  import { X, Filter } from "lucide-react";
28
28
 
29
29
  import { Button, Text } from "@godxjp/ui/general";
30
- import { Badge, DataTable, type ColumnDef } from "@godxjp/ui/data-display";
30
+ import {
31
+ Badge,
32
+ Card,
33
+ CardContent,
34
+ DataTable,
35
+ EmptyState,
36
+ type ColumnDef,
37
+ } from "@godxjp/ui/data-display";
31
38
  import { SearchInput, Select } from "@godxjp/ui/data-entry";
32
39
  import { Flex, PageContainer } from "@godxjp/ui/layout";
33
40
  import type { SortStateProp } from "@godxjp/ui/props";
@@ -256,7 +263,7 @@ function FilterChip({
256
263
  onRemove: () => void;
257
264
  }) {
258
265
  return (
259
- <Badge tone={tone ?? "neutral"} variant="outline" className="gap-1 pe-1">
266
+ <Badge tone={tone ?? "neutral"} variant="outline">
260
267
  {label}
261
268
  <Button
262
269
  variant="ghost"
@@ -354,69 +361,67 @@ export default function Demo() {
354
361
  </Flex>
355
362
 
356
363
  {/* Active-filter chip bar — visible at rest because filters are seeded */}
357
- <Flex
358
- direction="row"
359
- wrap
360
- align="center"
361
- gap="xs"
362
- className="border-border bg-secondary/30 min-h-9 rounded-md border px-2.5 py-1.5"
363
- >
364
- <Flex direction="row" align="center" gap="xs" className="text-muted-foreground pe-1">
365
- <Filter className="size-3.5" aria-hidden="true" />
366
- <Text size="xs">適用中</Text>
367
- </Flex>
364
+ <Card>
365
+ <CardContent solo>
366
+ <Flex direction="row" wrap align="center" gap="xs">
367
+ <Flex direction="row" align="center" gap="xs" className="text-muted-foreground">
368
+ <Filter className="size-3.5" aria-hidden="true" />
369
+ <Text size="xs">適用中</Text>
370
+ </Flex>
368
371
 
369
- {!hasFilters && (
370
- <Text size="xs" tone="muted">
371
- 条件なし · 全 {ROWS.length} 件
372
- </Text>
373
- )}
372
+ {!hasFilters && (
373
+ <Text size="xs" tone="muted">
374
+ 条件なし · 全 {ROWS.length} 件
375
+ </Text>
376
+ )}
374
377
 
375
- {query.trim() && (
376
- <FilterChip
377
- label={`検索: ${query.trim()}`}
378
- onRemove={() => {
379
- setQuery("");
380
- }}
381
- />
382
- )}
383
- {status && (
384
- <FilterChip
385
- tone={STATUS_META[status].tone}
386
- label={`状態: ${STATUS_META[status].label}`}
387
- onRemove={() => {
388
- setStatus(undefined);
389
- }}
390
- />
391
- )}
392
- {dept && (
393
- <FilterChip
394
- label={`部署: ${dept}`}
395
- onRemove={() => {
396
- setDept(undefined);
397
- }}
398
- />
399
- )}
400
- {ot !== "any" && (
401
- <FilterChip
402
- label={ot === "ot" ? "残業あり" : "残業 60分以上"}
403
- onRemove={() => {
404
- setOt("any");
405
- }}
406
- />
407
- )}
378
+ {query.trim() && (
379
+ <FilterChip
380
+ label={`検索: ${query.trim()}`}
381
+ onRemove={() => {
382
+ setQuery("");
383
+ }}
384
+ />
385
+ )}
386
+ {status && (
387
+ <FilterChip
388
+ tone={STATUS_META[status].tone}
389
+ label={`状態: ${STATUS_META[status].label}`}
390
+ onRemove={() => {
391
+ setStatus(undefined);
392
+ }}
393
+ />
394
+ )}
395
+ {dept && (
396
+ <FilterChip
397
+ label={`部署: ${dept}`}
398
+ onRemove={() => {
399
+ setDept(undefined);
400
+ }}
401
+ />
402
+ )}
403
+ {ot !== "any" && (
404
+ <FilterChip
405
+ label={ot === "ot" ? "残業あり" : "残業 60分以上"}
406
+ onRemove={() => {
407
+ setOt("any");
408
+ }}
409
+ />
410
+ )}
408
411
 
409
- {hasFilters && (
410
- <Button
411
- variant="ghost"
412
- size="sm"
413
- className="ms-auto h-6 px-2 text-xs"
414
- onClick={clearAll}
415
- >
416
- すべて解除
417
- </Button>
418
- )}
419
- </Flex>
412
+ {hasFilters && (
413
+ <Button
414
+ variant="ghost"
415
+ size="sm"
416
+ className="ms-auto h-6 text-xs"
417
+ onClick={clearAll}
418
+ >
419
+ すべて解除
420
+ </Button>
421
+ )}
422
+ </Flex>
423
+ </CardContent>
424
+ </Card>
420
425
 
421
426
  {/* The filtered table */}
422
427
  <DataTable
@@ -430,15 +435,17 @@ export default function Demo() {
430
435
  onSortChange={setSort}
431
436
  density="compact"
432
437
  empty={
433
- <Flex direction="col" align="center" gap="xs" className="py-8">
434
- <Text weight="medium">該当する勤怠記録がありません</Text>
435
- <Text size="xs" tone="muted">
436
- フィルター条件を解除すると全件を表示します
437
- </Text>
438
- <Button variant="outline" size="sm" className="mt-1" onClick={clearAll}>
439
- フィルターを解除
440
- </Button>
441
- </Flex>
438
+ <EmptyState
439
+ variant="section"
440
+ titleAs="p"
441
+ title="該当する勤怠記録がありません"
442
+ description="フィルター条件を解除すると全件を表示します"
443
+ action={
444
+ <Button variant="outline" size="sm" onClick={clearAll}>
445
+ フィルターを解除
446
+ </Button>
447
+ }
448
+ />
442
449
  }
443
450
  >
444
451
  <DataTable.Toolbar>