ナビ行NavRowExperimental
設定画面やマイページで使う、ラベル、説明、現在値、末尾操作を持つ行です。
プレビュー
お支払い
状態とバリエーション
ナビゲーション行
onSelect を渡すと行全体が詳細へ進むボタンになり、既定で chevron が付きます。
お支払い
操作行
trailing に Switch などを渡す場合、行自体はボタンにせず操作対象を分けます。
通知・セキュリティ
配達前プッシュ通知お届け予定をプッシュでお知らせ
状態表示
Badge や値だけを見せる読み取り行にも使えます。
通知・セキュリティ
二段階認証アカウント保護の状態必須有効
プロパティ
表は横にスクロールできます
| プロパティ | 型 | 初期値 | 説明 |
|---|---|---|---|
| label | ReactNode | - | 主ラベルです。 |
| icon | ReactNode | - | 先頭に置くアイコンです。 |
| description | ReactNode | - | ラベル下の補足行です。 |
| value | ReactNode | - | 右寄せで表示する現在値です。 |
| trailing | ReactNode | - | 末尾アクセサリです。未指定で onSelect がある場合は chevron を出します。 |
| opensDialog | boolean | - | 行が詳細ダイアログやシートを開く場合に aria-haspopup="dialog" を付けます。 |
| onSelect | () => void | - | 行全体をナビゲーション/開示ボタンにします。トグルではないため aria-pressed は使いません。 |
| SettingGroup.label | ReactNode | - | グループ見出しです。 |
| SettingGroup.children | ReactNode | - | 丸角コンテナ内に配置する NavRow 群です。 |
使い方
import * as React from "react";
import {
Button,
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
NavRow,
SettingGroup,
} from "@gunjo/ui";
import { IconCreditCard, IconMail } from "@tabler/icons-react";
export function BillingRows() {
const rootRef = React.useRef<HTMLDivElement | null>(null);
const [portalContainer, setPortalContainer] = React.useState<HTMLElement | null>(null);
const [detail, setDetail] = React.useState<"payment" | "invoice" | null>(null);
React.useEffect(() => {
setPortalContainer(rootRef.current?.closest<HTMLElement>("[data-doc-component-preview-surface]") ?? rootRef.current);
}, []);
const detailContent = detail === "invoice"
? {
title: "請求書の送付方法",
value: "Web(メール通知)",
description: "毎月の請求書はメール通知つきの Web 配信で送付されます。",
}
: {
title: "お支払い方法",
value: "口座振替",
description: "登録済みの口座振替を確認し、必要に応じて変更申請へ進みます。",
};
return (
<div ref={rootRef} className="relative flex w-full max-w-sm flex-col gap-4">
<SettingGroup label="お支払い">
<NavRow
icon={<IconCreditCard className="size-5" />}
label="お支払い方法"
value="口座振替"
opensDialog
onSelect={() => setDetail("payment")}
/>
<NavRow
icon={<IconMail className="size-5" />}
label="請求書の送付方法"
description="毎月の請求書をどう受け取るか"
value="Web(メール通知)"
opensDialog
onSelect={() => setDetail("invoice")}
/>
</SettingGroup>
<Dialog open={detail !== null} onOpenChange={(open) => !open && setDetail(null)} modal={false}>
<DialogContent portalContainer={portalContainer} closeLabel="閉じる" className="sm:max-w-sm">
<DialogHeader>
<DialogTitle>{detailContent.title}</DialogTitle>
<DialogDescription>{detailContent.description}</DialogDescription>
</DialogHeader>
<div className="rounded-md border bg-muted/30 px-3 py-2 text-sm">
<span className="text-muted-foreground">現在値</span>
<span className="mt-1 block font-medium text-foreground">{detailContent.value}</span>
</div>
<DialogFooter>
<Button type="button" size="sm">変更する</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
);
}