@godxjp/ui 19.3.1 → 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.
- package/dist/components/data-display/badge.d.ts +9 -1
- package/dist/components/data-display/badge.js +3 -2
- package/dist/components/data-display/index.d.ts +2 -0
- package/dist/components/data-display/index.js +2 -0
- package/dist/components/data-display/popover.d.ts +13 -1
- package/dist/components/data-display/popover.js +3 -1
- package/dist/components/data-display/table.d.ts +19 -2
- package/dist/components/data-display/table.js +4 -1
- package/dist/components/data-display/timeline-grid.d.ts +18 -0
- package/dist/components/data-display/timeline-grid.js +222 -0
- package/dist/components/data-entry/cascader.js +4 -6
- package/dist/components/data-entry/checkbox.js +1 -1
- package/dist/components/data-entry/search-select.js +5 -7
- package/dist/components/data-entry/select.js +32 -28
- package/dist/components/data-entry/tree-select.js +4 -6
- package/dist/components/general/inert-background.d.ts +5 -0
- package/dist/components/general/inert-background.js +48 -0
- package/dist/components/layout/auth-shell.d.ts +4 -2
- package/dist/components/layout/auth-shell.js +7 -1
- package/dist/components/layout/centered-shell.d.ts +2 -2
- package/dist/components/layout/flex.d.ts +1 -1
- package/dist/components/layout/flex.js +2 -1
- package/dist/components/layout/index.d.ts +3 -0
- package/dist/components/layout/index.js +2 -0
- package/dist/components/layout/mobile-shell.d.ts +21 -0
- package/dist/components/layout/mobile-shell.js +43 -0
- package/dist/components/layout/sidebar-link.d.ts +1 -1
- package/dist/components/navigation/context-menu.js +13 -9
- package/dist/components/navigation/dropdown-menu.js +17 -13
- package/dist/inertia/index.d.ts +1 -1
- package/dist/lib/variants.d.ts +3 -3
- package/dist/lib/variants.js +1 -0
- package/dist/props/components/data-display.prop.d.ts +65 -0
- package/dist/props/components/data-entry.prop.d.ts +1 -1
- package/dist/props/components/layout.prop.d.ts +93 -6
- package/dist/props/registry.d.ts +109 -2
- package/dist/props/registry.js +143 -0
- package/dist/props/vocabulary/data.prop.d.ts +6 -0
- package/dist/props/vocabulary/index.d.ts +3 -3
- package/dist/props/vocabulary/layout.prop.d.ts +17 -2
- package/dist/props/vocabulary/shared.prop.d.ts +7 -0
- package/dist/styles/control.css +18 -1
- package/dist/styles/data-display-layout.css +167 -0
- package/dist/styles/layout.css +7 -0
- package/dist/styles/shell-layout.css +148 -0
- package/dist/styles/table-layout.css +23 -4
- package/dist/tokens/components/control.css +1 -0
- package/dist/tokens/components/data-display.css +20 -0
- package/dist/tokens/components/shell.css +22 -0
- package/dist/tokens/components/table.css +2 -0
- package/docs/SPACING.md +19 -6
- package/docs/charts/compact-bar-trend.tsx +5 -6
- package/docs/data-display/avatar.tsx +7 -9
- package/docs/data-display/badge.tsx +1 -1
- package/docs/data-display/card/index.tsx +6 -4
- package/docs/data-display/data-table/examples/approval-queue.tsx +1 -1
- package/docs/data-display/data-table/index.tsx +1 -1
- package/docs/data-display/permission-matrix.tsx +2 -2
- package/docs/data-display/scroll-area.tsx +1 -1
- package/docs/data-display/table.tsx +1 -1
- package/docs/data-display/timeline-grid.tsx +119 -0
- package/docs/data-entry/branch-scope-picker.tsx +1 -1
- package/docs/data-entry/input-otp.tsx +1 -1
- package/docs/data-entry/textarea.tsx +1 -1
- package/docs/data-entry/toggle-count.tsx +1 -1
- package/docs/feedback/alert.tsx +1 -1
- package/docs/feedback/banner.tsx +1 -1
- package/docs/foundation/email-tokens.tsx +1 -1
- package/docs/general/activity.tsx +1 -1
- package/docs/layout/auth-account-summary.tsx +1 -1
- package/docs/layout/auth-recovery/examples/mobile-390.tsx +1 -1
- package/docs/layout/auth-recovery/examples/password-recovery.tsx +0 -2
- package/docs/layout/auth-shell-context.tsx +1 -1
- package/docs/layout/auth-shell-device.tsx +2 -2
- package/docs/layout/auth-shell-registration.tsx +1 -1
- package/docs/layout/auth-shell.tsx +1 -1
- package/docs/layout/master-detail.tsx +2 -2
- package/docs/layout/mobile-shell.tsx +101 -0
- package/docs/layout/page-container.tsx +6 -6
- package/docs/layout/responsive-grid.tsx +2 -2
- package/docs/layout/separator.tsx +2 -2
- package/docs/layout/service-role-panel.tsx +1 -1
- package/docs/layout/sidebar.tsx +6 -6
- package/docs/layout/split-pane.tsx +1 -1
- package/docs/layout/topbar.tsx +2 -8
- package/docs/navigation/filter-bar.tsx +2 -2
- package/docs/navigation/pagination.tsx +2 -2
- package/docs/navigation/steps.tsx +1 -1
- package/docs/navigation/tabs.tsx +1 -1
- package/docs/showcase/acme-portal.tsx +11 -12
- package/docs/showcase/acme-website.tsx +7 -7
- package/docs/showcase/case1-warehouse-dashboard.tsx +11 -12
- package/docs/showcase/case2-employee-me.tsx +10 -16
- package/docs/showcase/case4-login.tsx +144 -156
- package/docs/showcase/case5-shift-calendar.tsx +181 -280
- package/docs/showcase/case6-agency-handy.tsx +446 -443
- package/docs/showcase/futurelastic-web.tsx +9 -8
- package/docs/showcase/org-switcher.tsx +18 -11
- package/docs/showcase/permission-matrix.tsx +13 -13
- package/docs/showcase/public-landing.tsx +1 -1
- package/docs/showcase/settings-account-sections.tsx +2 -2
- package/docs/showcase/settings-security-mfa.tsx +3 -3
- package/docs/showcase/table-approval-queue.tsx +1 -1
- package/docs/showcase/table-bulk-actions.tsx +49 -52
- package/docs/showcase/table-conditional-format.tsx +1 -1
- package/docs/showcase/table-crud-list.tsx +1 -1
- package/docs/showcase/table-expandable-rows.tsx +101 -98
- package/docs/showcase/table-filter-chips.tsx +78 -66
- package/docs/showcase/table-footer-totals.tsx +23 -19
- package/docs/showcase/table-grouped-subtotals.tsx +7 -4
- package/docs/showcase/table-master-detail.tsx +12 -14
- package/docs/showcase/table-states.tsx +34 -29
- package/docs/showcase/table-sticky-columns.tsx +3 -2
- package/docs/showcase/table-tree-rows.tsx +22 -15
- package/docs/showcase/table-view-tabs.tsx +12 -14
- package/package.json +7 -6
|
@@ -251,7 +251,6 @@ const EMPLOYEES: Employee[] = [
|
|
|
251
251
|
// ── Shared cell padding to match compact DataTable density ─────────────────────
|
|
252
252
|
|
|
253
253
|
const CELL = "align-middle";
|
|
254
|
-
const HEAD = "px-3";
|
|
255
254
|
|
|
256
255
|
function StatusBadge({ status }: { status: ShiftStatus }) {
|
|
257
256
|
return (
|
|
@@ -265,103 +264,105 @@ function StatusBadge({ status }: { status: ShiftStatus }) {
|
|
|
265
264
|
|
|
266
265
|
function DetailPanel({ employee }: { employee: Employee }) {
|
|
267
266
|
return (
|
|
268
|
-
<
|
|
269
|
-
<
|
|
270
|
-
<Flex direction="
|
|
271
|
-
<
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
<Flex align="center" gap="xs">
|
|
275
|
-
<Text size="xs" tone="muted">
|
|
276
|
-
<MapPin className="size-3.5" aria-hidden="true" />
|
|
277
|
-
{employee.site}
|
|
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}
|
|
278
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>
|
|
279
280
|
</Flex>
|
|
280
|
-
</Flex>
|
|
281
281
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
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>
|
|
298
298
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
</TableRow>
|
|
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
|
|
339
|
-
className={`${CELL} text-muted-foreground inline-flex items-center gap-1 tabular-nums`}
|
|
340
|
-
>
|
|
341
|
-
<Coffee className="size-3.5" aria-hidden="true" />
|
|
342
|
-
{d.break}
|
|
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>
|
|
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>
|
|
350
325
|
</TableRow>
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
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>
|
|
356
356
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
357
|
+
<Flex direction="row" gap="sm">
|
|
358
|
+
<Button size="sm" variant="outline">
|
|
359
|
+
勤怠詳細を開く
|
|
360
|
+
</Button>
|
|
361
|
+
<Button size="sm">承認する</Button>
|
|
362
|
+
</Flex>
|
|
362
363
|
</Flex>
|
|
363
|
-
</
|
|
364
|
-
</
|
|
364
|
+
</CardContent>
|
|
365
|
+
</Card>
|
|
365
366
|
);
|
|
366
367
|
}
|
|
367
368
|
|
|
@@ -381,12 +382,12 @@ function ExpandableList() {
|
|
|
381
382
|
<Table>
|
|
382
383
|
<TableHeader className="bg-secondary sticky top-0 z-10">
|
|
383
384
|
<TableRow>
|
|
384
|
-
<TableHead className=
|
|
385
|
-
<TableHead
|
|
386
|
-
<TableHead
|
|
387
|
-
<TableHead className=
|
|
388
|
-
<TableHead className=
|
|
389
|
-
<TableHead className=
|
|
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>
|
|
390
391
|
</TableRow>
|
|
391
392
|
</TableHeader>
|
|
392
393
|
<TableBody>
|
|
@@ -434,7 +435,9 @@ function ExpandableList() {
|
|
|
434
435
|
</TableRow>
|
|
435
436
|
{isOpen && (
|
|
436
437
|
<TableRow className="hover:bg-transparent">
|
|
437
|
-
|
|
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}>
|
|
438
441
|
<DetailPanel employee={emp} />
|
|
439
442
|
</TableCell>
|
|
440
443
|
</TableRow>
|
|
@@ -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 {
|
|
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"
|
|
266
|
+
<Badge tone={tone ?? "neutral"} variant="outline">
|
|
260
267
|
{label}
|
|
261
268
|
<Button
|
|
262
269
|
variant="ghost"
|
|
@@ -354,64 +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
|
-
<
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
372
|
+
{!hasFilters && (
|
|
373
|
+
<Text size="xs" tone="muted">
|
|
374
|
+
条件なし · 全 {ROWS.length} 件
|
|
375
|
+
</Text>
|
|
376
|
+
)}
|
|
374
377
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
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
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
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>
|
|
415
425
|
|
|
416
426
|
{/* The filtered table */}
|
|
417
427
|
<DataTable
|
|
@@ -425,15 +435,17 @@ export default function Demo() {
|
|
|
425
435
|
onSortChange={setSort}
|
|
426
436
|
density="compact"
|
|
427
437
|
empty={
|
|
428
|
-
<
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
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
|
+
/>
|
|
437
449
|
}
|
|
438
450
|
>
|
|
439
451
|
<DataTable.Toolbar>
|
|
@@ -289,25 +289,29 @@ export default function Demo() {
|
|
|
289
289
|
</CardContent>
|
|
290
290
|
</Card>
|
|
291
291
|
|
|
292
|
-
<Flex direction="row" align="center" gap="
|
|
293
|
-
<
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
292
|
+
<Flex direction="row" align="center" wrap gap="md">
|
|
293
|
+
<Flex direction="row" align="center" gap="xs">
|
|
294
|
+
<Text size="xs" tone="muted">
|
|
295
|
+
残業 凡例:
|
|
296
|
+
</Text>
|
|
297
|
+
<Badge tone="success" variant="outline">
|
|
298
|
+
~15h
|
|
299
|
+
</Badge>
|
|
300
|
+
<Badge tone="info" variant="outline">
|
|
301
|
+
15h~
|
|
302
|
+
</Badge>
|
|
303
|
+
<Badge tone="warning" variant="outline">
|
|
304
|
+
25h~
|
|
305
|
+
</Badge>
|
|
306
|
+
</Flex>
|
|
307
|
+
<Flex direction="row" align="center" gap="xs">
|
|
308
|
+
<Text size="xs" tone="muted">
|
|
309
|
+
遅刻:
|
|
310
|
+
</Text>
|
|
311
|
+
<Badge tone="destructive" variant="outline">
|
|
312
|
+
回数
|
|
313
|
+
</Badge>
|
|
314
|
+
</Flex>
|
|
311
315
|
</Flex>
|
|
312
316
|
</PageContainer>
|
|
313
317
|
);
|
|
@@ -226,18 +226,18 @@ function GroupHeaderRow({
|
|
|
226
226
|
const Chevron = open ? ChevronDown : ChevronRight;
|
|
227
227
|
return (
|
|
228
228
|
<TableRow className="bg-secondary hover:bg-secondary border-b">
|
|
229
|
-
<TableCell
|
|
229
|
+
<TableCell colSpan={2}>
|
|
230
230
|
<Button
|
|
231
231
|
variant="ghost"
|
|
232
232
|
size="sm"
|
|
233
233
|
onClick={onToggle}
|
|
234
234
|
aria-expanded={open}
|
|
235
235
|
aria-controls={`grp-${group.id}`}
|
|
236
|
-
className="h-7
|
|
236
|
+
className="h-7 font-medium"
|
|
237
237
|
>
|
|
238
238
|
<Chevron className="text-muted-foreground size-4" aria-hidden="true" />
|
|
239
239
|
{group.label}
|
|
240
|
-
<Badge variant="outline" tone="neutral"
|
|
240
|
+
<Badge variant="outline" tone="neutral">
|
|
241
241
|
{group.members.length}名
|
|
242
242
|
</Badge>
|
|
243
243
|
</Button>
|
|
@@ -266,7 +266,10 @@ function GroupHeaderRow({
|
|
|
266
266
|
function MemberRow({ m }: { m: Employee }) {
|
|
267
267
|
return (
|
|
268
268
|
<TableRow>
|
|
269
|
-
|
|
269
|
+
{/* `indent` — the detail row sits one hierarchy level under its group header. */}
|
|
270
|
+
<TableCell indent={1} className="text-muted-foreground font-mono text-xs">
|
|
271
|
+
{m.id}
|
|
272
|
+
</TableCell>
|
|
270
273
|
<TableCell>{m.name}</TableCell>
|
|
271
274
|
<TableCell className="text-end tabular-nums">{m.days}日</TableCell>
|
|
272
275
|
<TableCell className="text-end tabular-nums">{fmtH(m.work)}</TableCell>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Composition map (intent → real @godxjp/ui primitive):
|
|
10
10
|
* resizable split ........ ResizablePanelGroup + ResizablePanel + ResizableHandle
|
|
11
|
-
*
|
|
11
|
+
* fixed-track split ...... MasterDetail (tokenized rail + stacking threshold, )
|
|
12
12
|
* master list ............ DataTable (compact, clickable rows, selected row)
|
|
13
13
|
* status cell ............ Badge tone (出勤/遅刻/早退/休暇 — fixed signaling)
|
|
14
14
|
* detail header .......... Avatar + heading + Badge + action Buttons
|
|
@@ -398,7 +398,7 @@ export default function Demo() {
|
|
|
398
398
|
|
|
399
399
|
{/* Detail pane */}
|
|
400
400
|
<ResizablePanel defaultSize="58%" minSize="34%">
|
|
401
|
-
<
|
|
401
|
+
<CardContent solo className="h-full overflow-auto">
|
|
402
402
|
{selected ? (
|
|
403
403
|
<EmployeeDetail employee={selected} />
|
|
404
404
|
) : (
|
|
@@ -410,7 +410,7 @@ export default function Demo() {
|
|
|
410
410
|
/>
|
|
411
411
|
</Flex>
|
|
412
412
|
)}
|
|
413
|
-
</
|
|
413
|
+
</CardContent>
|
|
414
414
|
</ResizablePanel>
|
|
415
415
|
</ResizablePanelGroup>
|
|
416
416
|
</CardContent>
|
|
@@ -442,13 +442,11 @@ export default function Demo() {
|
|
|
442
442
|
/>
|
|
443
443
|
}
|
|
444
444
|
>
|
|
445
|
-
<
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
/>
|
|
451
|
-
</div>
|
|
445
|
+
<EmptyState
|
|
446
|
+
icon={UserRound}
|
|
447
|
+
title="従業員を選択してください"
|
|
448
|
+
description="一覧から行を選ぶと詳細が表示されます。"
|
|
449
|
+
/>
|
|
452
450
|
</MasterDetail>
|
|
453
451
|
</CardContent>
|
|
454
452
|
</Card>
|
|
@@ -472,10 +470,10 @@ export default function Demo() {
|
|
|
472
470
|
selected={new Set(["E-1042"])}
|
|
473
471
|
onRowClick={() => {}}
|
|
474
472
|
/>
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
473
|
+
</CardContent>
|
|
474
|
+
<Separator />
|
|
475
|
+
<CardContent solo>
|
|
476
|
+
<EmployeeDetail employee={EMPLOYEES[0]} />
|
|
479
477
|
</CardContent>
|
|
480
478
|
</Card>
|
|
481
479
|
</Flex>
|