@godxjp/ui 31.28.3 → 31.29.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/agent/START-HERE.md +5 -5
- package/agent/components/AppLauncher.json +5 -0
- package/agent/components/Avatar.json +1 -0
- package/agent/components/Dialog.json +3 -1
- package/agent/components/ResponsiveGrid.json +7 -0
- package/agent/components/Sidebar.json +5 -0
- package/agent/components/SortableList.json +78 -0
- package/agent/components/TopbarItem.json +1 -1
- package/agent/components-index.json +5 -0
- package/agent/components.json +100 -2
- package/agent/index.json +6 -6
- package/agent/llms.txt +6 -6
- package/agent/tokens.json +74 -2
- package/dist/components/data-entry/index.d.ts +2 -0
- package/dist/components/data-entry/index.js +2 -0
- package/dist/components/data-entry/sortable-list.d.ts +10 -0
- package/dist/components/data-entry/sortable-list.js +237 -0
- package/dist/components/feedback/dialog.d.ts +8 -2
- package/dist/components/feedback/dialog.js +8 -1
- package/dist/components/feedback/sheet.js +1 -1
- package/dist/components/layout/app-launcher.d.ts +1 -1
- package/dist/components/layout/app-launcher.js +18 -14
- package/dist/components/layout/responsive-grid.d.ts +17 -2
- package/dist/components/layout/responsive-grid.js +17 -4
- package/dist/components/layout/sidebar.d.ts +1 -1
- package/dist/components/layout/sidebar.js +3 -0
- package/dist/components/layout/topbar-item.js +8 -2
- package/dist/components/ui/avatar.d.ts +3 -1
- package/dist/components/ui/avatar.js +2 -1
- package/dist/contracts/measurement.json +1 -1
- package/dist/i18n/messages/en.json +8 -0
- package/dist/i18n/messages/ja.json +8 -0
- package/dist/i18n/messages/vi.json +8 -0
- package/dist/props/components/data-display.prop.d.ts +9 -0
- package/dist/props/components/data-entry.prop.d.ts +34 -0
- package/dist/props/components/feedback.prop.d.ts +6 -1
- package/dist/props/components/layout.prop.d.ts +22 -0
- package/dist/props/registry.d.ts +33 -2
- package/dist/props/registry.js +44 -1
- package/dist/styles/control.css +50 -0
- package/dist/styles/data-display-layout.css +4 -0
- package/dist/styles/dialog-layout.css +14 -1
- package/dist/styles/layers.json +6 -1
- package/dist/styles/layout.css +29 -7
- package/dist/styles/shell-layout.css +26 -0
- package/dist/tokens/components/control.css +5 -0
- package/dist/tokens/components/feedback.css +6 -0
- package/dist/tokens/components/shell.css +6 -0
- package/dist/tokens/semantic/layout.css +1 -4
- package/docs/FRAME-COVERAGE-REPORT.md +3 -2
- package/docs/data-display/avatar.tsx +32 -0
- package/docs/data-entry/sortable-list.tsx +76 -0
- package/docs/feedback/dialog.tsx +37 -1
- package/docs/i18n/messages/en.json +51 -0
- package/docs/i18n/messages/ja.json +51 -0
- package/docs/i18n/messages/vi.json +51 -0
- package/docs/layout/app-launcher.tsx +17 -1
- package/docs/layout/responsive-grid.tsx +23 -0
- package/docs/layout/sidebar.tsx +24 -0
- package/docs/layout/topbar-item.tsx +11 -0
- package/package.json +2 -2
package/docs/feedback/dialog.tsx
CHANGED
|
@@ -21,7 +21,8 @@ import {
|
|
|
21
21
|
CardTitle,
|
|
22
22
|
} from "@godxjp/ui/data-display";
|
|
23
23
|
import { Button, Text } from "@godxjp/ui/general";
|
|
24
|
-
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
24
|
+
import { Flex, PageContainer, ResponsiveGrid } from "@godxjp/ui/layout";
|
|
25
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
25
26
|
|
|
26
27
|
/** Every branch of DialogHeader's `tone`, in the order the vocabulary declares them. */
|
|
27
28
|
const headerTones = [
|
|
@@ -49,6 +50,8 @@ const yen = new Intl.NumberFormat("ja-JP", { style: "currency", currency: "JPY"
|
|
|
49
50
|
* Use DialogFooter for primary/cancel actions.
|
|
50
51
|
*/
|
|
51
52
|
export default function Demo() {
|
|
53
|
+
const { t } = useTranslation();
|
|
54
|
+
const [wideOpen, setWideOpen] = useState(false);
|
|
52
55
|
const [createOpen, setCreateOpen] = useState(true);
|
|
53
56
|
const [detailOpen, setDetailOpen] = useState(false);
|
|
54
57
|
const [toneOpen, setToneOpen] = useState(false);
|
|
@@ -128,6 +131,39 @@ export default function Demo() {
|
|
|
128
131
|
</CardContent>
|
|
129
132
|
</Card>
|
|
130
133
|
|
|
134
|
+
<Card>
|
|
135
|
+
<CardHeader>
|
|
136
|
+
<CardTitle level={2}>{t("dialogWidthDocs.title")}</CardTitle>
|
|
137
|
+
<CardDescription>{t("dialogWidthDocs.description")}</CardDescription>
|
|
138
|
+
</CardHeader>
|
|
139
|
+
<CardContent>
|
|
140
|
+
<Dialog open={wideOpen} onOpenChange={setWideOpen}>
|
|
141
|
+
<DialogTrigger asChild>
|
|
142
|
+
<Button variant="outline" size="sm">
|
|
143
|
+
{t("dialogWidthDocs.open")}
|
|
144
|
+
</Button>
|
|
145
|
+
</DialogTrigger>
|
|
146
|
+
<DialogContent width="60rem">
|
|
147
|
+
<DialogHeader>
|
|
148
|
+
<DialogTitle>{t("dialogWidthDocs.dialogTitle")}</DialogTitle>
|
|
149
|
+
<DialogDescription>{t("dialogWidthDocs.dialogDescription")}</DialogDescription>
|
|
150
|
+
</DialogHeader>
|
|
151
|
+
<DialogBody>
|
|
152
|
+
<ResponsiveGrid columns={{ base: 1, sm: 3 }}>
|
|
153
|
+
{[1, 2, 3, 4, 5, 6].map((n) => (
|
|
154
|
+
<Card key={n}>
|
|
155
|
+
<CardContent>
|
|
156
|
+
<Text>{t("dialogWidthDocs.desktop", { n: String(n) })}</Text>
|
|
157
|
+
</CardContent>
|
|
158
|
+
</Card>
|
|
159
|
+
))}
|
|
160
|
+
</ResponsiveGrid>
|
|
161
|
+
</DialogBody>
|
|
162
|
+
</DialogContent>
|
|
163
|
+
</Dialog>
|
|
164
|
+
</CardContent>
|
|
165
|
+
</Card>
|
|
166
|
+
|
|
131
167
|
<Card>
|
|
132
168
|
<CardHeader>
|
|
133
169
|
<CardTitle level={2}>Read-only detail pop-up</CardTitle>
|
|
@@ -1638,5 +1638,56 @@
|
|
|
1638
1638
|
"label": "Icon",
|
|
1639
1639
|
"chosen": "Chosen: {icon}",
|
|
1640
1640
|
"none": "No icon"
|
|
1641
|
+
},
|
|
1642
|
+
"dialogWidthDocs": {
|
|
1643
|
+
"title": "Wide dialog (width)",
|
|
1644
|
+
"description": "DialogContent width sizes the panel for an overview grid; it is capped at the viewport minus the inset, so it still fits a phone.",
|
|
1645
|
+
"open": "Open the overview",
|
|
1646
|
+
"dialogTitle": "All desktops",
|
|
1647
|
+
"dialogDescription": "A 60rem dialog holding a three-column grid.",
|
|
1648
|
+
"desktop": "Desktop {n}"
|
|
1649
|
+
},
|
|
1650
|
+
"sortableListDocs": {
|
|
1651
|
+
"subtitle": "Drag a grip, or Space · arrows · Space · Esc — every move is announced",
|
|
1652
|
+
"widgetsTitle": "Home widgets",
|
|
1653
|
+
"widgetsDescription": "Order the tiles on your desktop. The order is saved once, when you drop.",
|
|
1654
|
+
"calendar": "Calendar",
|
|
1655
|
+
"mail": "Mail",
|
|
1656
|
+
"tasks": "Tasks",
|
|
1657
|
+
"notes": "Notes",
|
|
1658
|
+
"slot": "Slot {position}",
|
|
1659
|
+
"saved": "Saved order: {order}",
|
|
1660
|
+
"tabsTitle": "Project tabs",
|
|
1661
|
+
"tabsDescription": "A list layout. Billing is locked by your plan, so it cannot be picked up — the others still move past it.",
|
|
1662
|
+
"overview": "Overview",
|
|
1663
|
+
"members": "Members",
|
|
1664
|
+
"billing": "Billing",
|
|
1665
|
+
"audit": "Audit log"
|
|
1666
|
+
},
|
|
1667
|
+
"topbarItemDocs": {
|
|
1668
|
+
"notifications": "Notifications",
|
|
1669
|
+
"notificationsUnread": "Notifications, {count} unread"
|
|
1670
|
+
},
|
|
1671
|
+
"appLauncherDocs": {
|
|
1672
|
+
"requestAccess": "Request access",
|
|
1673
|
+
"allApps": "All apps"
|
|
1674
|
+
},
|
|
1675
|
+
"responsiveGridDocs": {
|
|
1676
|
+
"boardTitle": "Widget board (rowSpan + dense)",
|
|
1677
|
+
"boardDescription": "A 2×1 cell, a tall 1×2 cell (ResponsiveGrid.Item rowSpan={2}) and 1×1 cells. dense lets the small cells fill the space beside the wide and tall ones.",
|
|
1678
|
+
"revenue": "Monthly revenue",
|
|
1679
|
+
"tasks": "Open tasks",
|
|
1680
|
+
"members": "Members",
|
|
1681
|
+
"invoices": "Invoices",
|
|
1682
|
+
"services": "Services",
|
|
1683
|
+
"invitations": "Invitations"
|
|
1684
|
+
},
|
|
1685
|
+
"avatarDocs": {
|
|
1686
|
+
"fitTitle": "Logos: fit=\"contain\"",
|
|
1687
|
+
"fitDescription": "cover (the default) crops to fill — right for a face. contain shows a wide or transparent logo whole.",
|
|
1688
|
+
"logo": "Acme logo"
|
|
1689
|
+
},
|
|
1690
|
+
"sidebarDocs": {
|
|
1691
|
+
"newEntry": "New journal entry"
|
|
1641
1692
|
}
|
|
1642
1693
|
}
|
|
@@ -1631,5 +1631,56 @@
|
|
|
1631
1631
|
"label": "アイコン",
|
|
1632
1632
|
"chosen": "選択中: {icon}",
|
|
1633
1633
|
"none": "アイコンなし"
|
|
1634
|
+
},
|
|
1635
|
+
"dialogWidthDocs": {
|
|
1636
|
+
"title": "幅の広いダイアログ(width)",
|
|
1637
|
+
"description": "DialogContent の width で一覧グリッド向けに幅を広げます。画面幅から余白を引いた幅が上限なので、スマートフォンでもはみ出しません。",
|
|
1638
|
+
"open": "一覧を開く",
|
|
1639
|
+
"dialogTitle": "すべてのデスクトップ",
|
|
1640
|
+
"dialogDescription": "3 列のグリッドを収めた 60rem のダイアログです。",
|
|
1641
|
+
"desktop": "デスクトップ {n}"
|
|
1642
|
+
},
|
|
1643
|
+
"sortableListDocs": {
|
|
1644
|
+
"subtitle": "つまみをドラッグ、または Space・矢印・Space・Esc — 移動のたびに読み上げます",
|
|
1645
|
+
"widgetsTitle": "ホームのウィジェット",
|
|
1646
|
+
"widgetsDescription": "デスクトップのタイルを並べ替えます。順序は置いたときに一度だけ保存されます。",
|
|
1647
|
+
"calendar": "カレンダー",
|
|
1648
|
+
"mail": "メール",
|
|
1649
|
+
"tasks": "タスク",
|
|
1650
|
+
"notes": "メモ",
|
|
1651
|
+
"slot": "{position} 番目",
|
|
1652
|
+
"saved": "保存された順序: {order}",
|
|
1653
|
+
"tabsTitle": "プロジェクトのタブ",
|
|
1654
|
+
"tabsDescription": "リスト表示です。請求はプランで固定されているため持ち上げられませんが、ほかの項目はその前後に移動できます。",
|
|
1655
|
+
"overview": "概要",
|
|
1656
|
+
"members": "メンバー",
|
|
1657
|
+
"billing": "請求",
|
|
1658
|
+
"audit": "監査ログ"
|
|
1659
|
+
},
|
|
1660
|
+
"topbarItemDocs": {
|
|
1661
|
+
"notifications": "通知",
|
|
1662
|
+
"notificationsUnread": "通知(未読 {count} 件)"
|
|
1663
|
+
},
|
|
1664
|
+
"appLauncherDocs": {
|
|
1665
|
+
"requestAccess": "アクセスをリクエスト",
|
|
1666
|
+
"allApps": "すべてのアプリ"
|
|
1667
|
+
},
|
|
1668
|
+
"responsiveGridDocs": {
|
|
1669
|
+
"boardTitle": "ウィジェットボード(rowSpan + dense)",
|
|
1670
|
+
"boardDescription": "2×1 のセル、縦長 1×2 のセル(ResponsiveGrid.Item rowSpan={2})、1×1 のセル。dense で小さなセルが横長・縦長セルの隣の空きを埋めます。",
|
|
1671
|
+
"revenue": "月次売上",
|
|
1672
|
+
"tasks": "未完了タスク",
|
|
1673
|
+
"members": "メンバー",
|
|
1674
|
+
"invoices": "請求書",
|
|
1675
|
+
"services": "サービス",
|
|
1676
|
+
"invitations": "招待"
|
|
1677
|
+
},
|
|
1678
|
+
"avatarDocs": {
|
|
1679
|
+
"fitTitle": "ロゴ:fit=\"contain\"",
|
|
1680
|
+
"fitDescription": "cover(既定)は枠いっぱいに切り抜きます(顔写真向け)。contain は横長・透過のロゴを切らずに全体表示します。",
|
|
1681
|
+
"logo": "Acme ロゴ"
|
|
1682
|
+
},
|
|
1683
|
+
"sidebarDocs": {
|
|
1684
|
+
"newEntry": "仕訳を追加"
|
|
1634
1685
|
}
|
|
1635
1686
|
}
|
|
@@ -1631,5 +1631,56 @@
|
|
|
1631
1631
|
"label": "Biểu tượng",
|
|
1632
1632
|
"chosen": "Đã chọn: {icon}",
|
|
1633
1633
|
"none": "Không có biểu tượng"
|
|
1634
|
+
},
|
|
1635
|
+
"dialogWidthDocs": {
|
|
1636
|
+
"title": "Hộp thoại rộng (width)",
|
|
1637
|
+
"description": "width của DialogContent nới rộng bảng cho một lưới tổng quan; bị giới hạn bằng chiều rộng màn hình trừ lề, nên vẫn vừa điện thoại.",
|
|
1638
|
+
"open": "Mở tổng quan",
|
|
1639
|
+
"dialogTitle": "Tất cả màn hình làm việc",
|
|
1640
|
+
"dialogDescription": "Hộp thoại 60rem chứa một lưới ba cột.",
|
|
1641
|
+
"desktop": "Màn hình {n}"
|
|
1642
|
+
},
|
|
1643
|
+
"sortableListDocs": {
|
|
1644
|
+
"subtitle": "Kéo tay nắm, hoặc Space · mũi tên · Space · Esc — mỗi lần di chuyển đều được đọc",
|
|
1645
|
+
"widgetsTitle": "Widget trang chủ",
|
|
1646
|
+
"widgetsDescription": "Sắp xếp các ô trên màn hình. Thứ tự được lưu một lần khi bạn thả.",
|
|
1647
|
+
"calendar": "Lịch",
|
|
1648
|
+
"mail": "Thư",
|
|
1649
|
+
"tasks": "Công việc",
|
|
1650
|
+
"notes": "Ghi chú",
|
|
1651
|
+
"slot": "Ô {position}",
|
|
1652
|
+
"saved": "Thứ tự đã lưu: {order}",
|
|
1653
|
+
"tabsTitle": "Tab dự án",
|
|
1654
|
+
"tabsDescription": "Dạng danh sách. Thanh toán bị khoá theo gói nên không nhấc được — các mục khác vẫn di chuyển qua nó.",
|
|
1655
|
+
"overview": "Tổng quan",
|
|
1656
|
+
"members": "Thành viên",
|
|
1657
|
+
"billing": "Thanh toán",
|
|
1658
|
+
"audit": "Nhật ký kiểm tra"
|
|
1659
|
+
},
|
|
1660
|
+
"topbarItemDocs": {
|
|
1661
|
+
"notifications": "Thông báo",
|
|
1662
|
+
"notificationsUnread": "Thông báo, {count} chưa đọc"
|
|
1663
|
+
},
|
|
1664
|
+
"appLauncherDocs": {
|
|
1665
|
+
"requestAccess": "Yêu cầu quyền truy cập",
|
|
1666
|
+
"allApps": "Tất cả ứng dụng"
|
|
1667
|
+
},
|
|
1668
|
+
"responsiveGridDocs": {
|
|
1669
|
+
"boardTitle": "Bảng widget (rowSpan + dense)",
|
|
1670
|
+
"boardDescription": "Một ô 2×1, một ô cao 1×2 (ResponsiveGrid.Item rowSpan={2}) và các ô 1×1. dense cho các ô nhỏ lấp chỗ trống cạnh ô rộng và ô cao.",
|
|
1671
|
+
"revenue": "Doanh thu tháng",
|
|
1672
|
+
"tasks": "Công việc đang mở",
|
|
1673
|
+
"members": "Thành viên",
|
|
1674
|
+
"invoices": "Hoá đơn",
|
|
1675
|
+
"services": "Dịch vụ",
|
|
1676
|
+
"invitations": "Lời mời"
|
|
1677
|
+
},
|
|
1678
|
+
"avatarDocs": {
|
|
1679
|
+
"fitTitle": "Logo: fit=\"contain\"",
|
|
1680
|
+
"fitDescription": "cover (mặc định) cắt cho đầy khung — hợp với ảnh khuôn mặt. contain hiện trọn logo rộng hoặc trong suốt.",
|
|
1681
|
+
"logo": "Logo Acme"
|
|
1682
|
+
},
|
|
1683
|
+
"sidebarDocs": {
|
|
1684
|
+
"newEntry": "Thêm bút toán"
|
|
1634
1685
|
}
|
|
1635
1686
|
}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
ResponsiveGrid,
|
|
12
12
|
Topbar,
|
|
13
13
|
} from "@godxjp/ui/layout";
|
|
14
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
14
15
|
|
|
15
16
|
const apps = [
|
|
16
17
|
{ id: "console", name: "Console", href: "/console", icon: <BarChart3 />, current: true },
|
|
@@ -62,6 +63,7 @@ const labels: AppLauncherLabels = {
|
|
|
62
63
|
* width (the Slack shape). Shipping both puts one scope in two places.
|
|
63
64
|
*/
|
|
64
65
|
export default function Demo() {
|
|
66
|
+
const { t } = useTranslation();
|
|
65
67
|
const [error, setError] = useState<string | undefined>("アプリ一覧を取得できませんでした。");
|
|
66
68
|
|
|
67
69
|
return (
|
|
@@ -82,7 +84,21 @@ export default function Demo() {
|
|
|
82
84
|
<Flex direction="col" gap="md">
|
|
83
85
|
<Topbar
|
|
84
86
|
start={<Text weight="medium">Acme Console</Text>}
|
|
85
|
-
end={
|
|
87
|
+
end={
|
|
88
|
+
<AppLauncher
|
|
89
|
+
apps={apps}
|
|
90
|
+
groups={groups}
|
|
91
|
+
labels={labels}
|
|
92
|
+
footer={
|
|
93
|
+
<>
|
|
94
|
+
<a href="#app-launcher-request-access">
|
|
95
|
+
{t("appLauncherDocs.requestAccess")}
|
|
96
|
+
</a>
|
|
97
|
+
<a href="#app-launcher-all-apps">{t("appLauncherDocs.allApps")}</a>
|
|
98
|
+
</>
|
|
99
|
+
}
|
|
100
|
+
/>
|
|
101
|
+
}
|
|
86
102
|
/>
|
|
87
103
|
<Text size="sm" tone="muted">
|
|
88
104
|
current のアプリだけが `aria-current="page"` を持ちます。
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from "@godxjp/ui/data-entry";
|
|
18
18
|
import { Text } from "@godxjp/ui/general";
|
|
19
19
|
import { Flex, PageContainer, ResponsiveGrid, SplitPane } from "@godxjp/ui/layout";
|
|
20
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* ResponsiveGrid · equal-width multi-column tile grid with automatic responsive
|
|
@@ -44,6 +45,7 @@ const KANBAN_TASKS: { id: string; title: string; lane: KanbanLane; priority: str
|
|
|
44
45
|
];
|
|
45
46
|
|
|
46
47
|
export default function Demo() {
|
|
48
|
+
const { t } = useTranslation();
|
|
47
49
|
// Kanban: which lane each card is in, moved by native drag and drop.
|
|
48
50
|
const [tasks, setTasks] = useState(KANBAN_TASKS);
|
|
49
51
|
const moveTask = (id: string, lane: KanbanLane) =>
|
|
@@ -54,6 +56,27 @@ export default function Demo() {
|
|
|
54
56
|
subtitle="等幅タイルグリッド · KPI・カード比較・ダッシュボード行"
|
|
55
57
|
>
|
|
56
58
|
<Flex direction="col" gap="lg">
|
|
59
|
+
<Card>
|
|
60
|
+
<CardHeader>
|
|
61
|
+
<CardTitle level={2}>{t("responsiveGridDocs.boardTitle")}</CardTitle>
|
|
62
|
+
<CardDescription>{t("responsiveGridDocs.boardDescription")}</CardDescription>
|
|
63
|
+
</CardHeader>
|
|
64
|
+
<CardContent>
|
|
65
|
+
{/* gh#1175: a widget board — 2×1, 1×2 (rowSpan) and 1×1 cells, packed dense. */}
|
|
66
|
+
<ResponsiveGrid columns={4} dense>
|
|
67
|
+
<ResponsiveGrid.Item span={2}>
|
|
68
|
+
<StatCard label={t("responsiveGridDocs.revenue")} value="¥12,400,000" />
|
|
69
|
+
</ResponsiveGrid.Item>
|
|
70
|
+
<ResponsiveGrid.Item rowSpan={2}>
|
|
71
|
+
<StatCard label={t("responsiveGridDocs.tasks")} value="18" />
|
|
72
|
+
</ResponsiveGrid.Item>
|
|
73
|
+
<StatCard label={t("responsiveGridDocs.members")} value="14" />
|
|
74
|
+
<StatCard label={t("responsiveGridDocs.invoices")} value="2" />
|
|
75
|
+
<StatCard label={t("responsiveGridDocs.services")} value="3" />
|
|
76
|
+
<StatCard label={t("responsiveGridDocs.invitations")} value="0" />
|
|
77
|
+
</ResponsiveGrid>
|
|
78
|
+
</CardContent>
|
|
79
|
+
</Card>
|
|
57
80
|
<Card>
|
|
58
81
|
<CardHeader>
|
|
59
82
|
<CardTitle level={2}>Compact mobile metrics</CardTitle>
|
package/docs/layout/sidebar.tsx
CHANGED
|
@@ -23,6 +23,8 @@ import {
|
|
|
23
23
|
CardTitle,
|
|
24
24
|
} from "@godxjp/ui/data-display";
|
|
25
25
|
import { Button, Text } from "@godxjp/ui/general";
|
|
26
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "@godxjp/ui/feedback";
|
|
27
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
26
28
|
import {
|
|
27
29
|
LayoutDashboard,
|
|
28
30
|
FileText,
|
|
@@ -207,6 +209,7 @@ const COMPOSED_ITEMS: SidebarItemData[] = [
|
|
|
207
209
|
];
|
|
208
210
|
|
|
209
211
|
export default function Demo() {
|
|
212
|
+
const { t } = useTranslation();
|
|
210
213
|
const [activeId, setActiveId] = useState("journal");
|
|
211
214
|
const [collapsed, setCollapsed] = useState(false);
|
|
212
215
|
const [brandActiveId, setBrandActiveId] = useState("projects");
|
|
@@ -235,6 +238,27 @@ export default function Demo() {
|
|
|
235
238
|
* を読むと、AppShell が同じ Sidebar をドロワーにも渡す(ドロワーは展開表示に戻す)ため
|
|
236
239
|
* 全幅のドロワーの中でアイコンだけの足元になります。
|
|
237
240
|
*/
|
|
241
|
+
/*
|
|
242
|
+
* action · the rail's ONE primary action (gh#1185), above the scrolling nav. Full width
|
|
243
|
+
* when expanded; icon-only with a tooltip in the collapsed rail.
|
|
244
|
+
*/
|
|
245
|
+
action={(railCollapsed) =>
|
|
246
|
+
railCollapsed ? (
|
|
247
|
+
<Tooltip>
|
|
248
|
+
<TooltipTrigger asChild>
|
|
249
|
+
<Button size="sm" aria-label={t("sidebarDocs.newEntry")}>
|
|
250
|
+
<Plus />
|
|
251
|
+
</Button>
|
|
252
|
+
</TooltipTrigger>
|
|
253
|
+
<TooltipContent side="right">{t("sidebarDocs.newEntry")}</TooltipContent>
|
|
254
|
+
</Tooltip>
|
|
255
|
+
) : (
|
|
256
|
+
<Button size="sm" fullWidth>
|
|
257
|
+
<Plus />
|
|
258
|
+
{t("sidebarDocs.newEntry")}
|
|
259
|
+
</Button>
|
|
260
|
+
)
|
|
261
|
+
}
|
|
238
262
|
footer={(railCollapsed) =>
|
|
239
263
|
railCollapsed ? (
|
|
240
264
|
<Flex justify="center">
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from "@godxjp/ui/data-display";
|
|
12
12
|
import { Button, Icon, Text } from "@godxjp/ui/general";
|
|
13
13
|
import { AppShell, Flex, PageContainer, Sidebar, Topbar, TopbarItem } from "@godxjp/ui/layout";
|
|
14
|
+
import { useTranslation } from "@godxjp/ui/i18n";
|
|
14
15
|
import type { SidebarSectionProp } from "@godxjp/ui/layout";
|
|
15
16
|
import {
|
|
16
17
|
DropdownMenu,
|
|
@@ -51,6 +52,7 @@ const SECTIONS: SidebarSectionProp[] = [
|
|
|
51
52
|
];
|
|
52
53
|
|
|
53
54
|
export default function Demo() {
|
|
55
|
+
const { t } = useTranslation();
|
|
54
56
|
const [collapsed, setCollapsed] = useState(false);
|
|
55
57
|
|
|
56
58
|
return (
|
|
@@ -199,6 +201,15 @@ export default function Demo() {
|
|
|
199
201
|
<TopbarItem asChild icon={<Target aria-hidden="true" />}>
|
|
200
202
|
<a href="#topbar-item-goals">目標</a>
|
|
201
203
|
</TopbarItem>
|
|
204
|
+
{/* gh#1171: a bell that is a LINK keeps its count under asChild. */}
|
|
205
|
+
<TopbarItem asChild badge={3} icon={<Bell aria-hidden="true" />}>
|
|
206
|
+
<a
|
|
207
|
+
href="#topbar-item-notifications"
|
|
208
|
+
aria-label={t("topbarItemDocs.notificationsUnread", { count: 3 })}
|
|
209
|
+
>
|
|
210
|
+
{t("topbarItemDocs.notifications")}
|
|
211
|
+
</a>
|
|
212
|
+
</TopbarItem>
|
|
202
213
|
<TopbarItem
|
|
203
214
|
asChild
|
|
204
215
|
icon={<Target aria-hidden="true" />}
|