diff --git a/web/src/beta/lib/reearth-ui/components/Breadcrumb/index.stories.tsx b/web/src/beta/lib/reearth-ui/components/Breadcrumb/index.stories.tsx new file mode 100644 index 0000000000..790cf43481 --- /dev/null +++ b/web/src/beta/lib/reearth-ui/components/Breadcrumb/index.stories.tsx @@ -0,0 +1,120 @@ +import { Meta, StoryObj } from "@storybook/react"; + +import { PopupMenu, PopupMenuItem as PopupItems } from "@reearth/beta/lib/reearth-ui"; + +import { Breadcrumb, BreadcrumbProp, BreadcrumbItem } from "./"; + +const meta: Meta = { + component: Breadcrumb, +}; + +export default meta; + +type Story = StoryObj; + +const defaultItems: BreadcrumbItem[] = [ + { + title: "First", + }, + { + title: "Second", + }, + { + title: "Third", + }, +]; + +const multiLevelItems: BreadcrumbItem[] = [ + { + title: "First Item", + icon: "addStyle", + subItem: [ + { + id: "one", + title: "Sub Item one", + subItem: [ + { + id: "sub-one", + title: "Item one", + }, + { + id: "sub-two", + title: "Item two", + }, + ], + }, + { + id: "two", + title: "Sub Item two", + }, + { + id: "three", + title: "Sub Item three", + }, + ], + }, + { + title: "Second Item", + }, +]; + +const itemMenu: BreadcrumbItem[] = [ + { + title: "First Item", + subItem: [ + { + id: "one-1", + title: "Sub Menu 1", + }, + { + id: "two-2", + title: "Sub Menu 2", + }, + ], + }, + { + title: "Second Item", + }, + { + title: "Third Item", + }, +]; + +const renderPopupMenu = (items: BreadcrumbItem[], level: number) => { + return items.map(item => { + if (item.subItem) { + return { + ...item, + title: ( + 0} /> + ), + subItem: undefined, + }; + } + return item; + }); +}; + +export const Default: Story = { + render: () => ( +
+ +
+ ), +}; + +export const DropdownMenu: Story = { + render: () => ( +
+ +
+ ), +}; + +export const MultiLevelMenu: Story = { + render: () => ( +
+ +
+ ), +}; diff --git a/web/src/beta/lib/reearth-ui/components/Breadcrumb/index.tsx b/web/src/beta/lib/reearth-ui/components/Breadcrumb/index.tsx new file mode 100644 index 0000000000..2e6e6eae1e --- /dev/null +++ b/web/src/beta/lib/reearth-ui/components/Breadcrumb/index.tsx @@ -0,0 +1,68 @@ +import { FC, ReactNode } from "react"; + +import { Icon, IconName, Typography } from "@reearth/beta/lib/reearth-ui"; +import { styled, useTheme } from "@reearth/services/theme"; + +import { PopupMenuItem } from "../PopupMenu"; + +export type BreadcrumbItem = { + title: string | ReactNode; + icon?: IconName; + subItem?: PopupMenuItem[]; +}; + +export type BreadcrumbProp = { + items: BreadcrumbItem[]; + separator?: ReactNode; + onClick?: () => void; +}; + +export const Breadcrumb: FC = ({ items = [], separator = " / ", onClick }) => { + const theme = useTheme(); + return ( + + {items.map((item, index) => ( + + + {typeof item.title === "string" ? ( + <> + {item.icon && } + + {item.title} + + + ) : ( + item.title + )} + + {index < items.length - 1 && {separator}} + + ))} + + ); +}; + +const Wrapper = styled("div")(({ theme }) => ({ + display: "flex", + gap: theme.spacing.smallest, +})); + +const ItemWrapper = styled("div")(({ theme }) => ({ + display: "flex", + alignItems: "center", + gap: theme.spacing.smallest, + cursor: "pointer", +})); + +const Item = styled("div")(({ theme }) => ({ + padding: `${theme.spacing.micro}px ${theme.spacing.small}px`, + borderRadius: theme.radius.smallest, + display: "flex", + gap: theme.spacing.smallest, + alignItems: "center", +})); + +const Separator = styled("div")(({ theme }) => ({ + color: theme.content.weak, + userSelect: "none", +})); diff --git a/web/src/beta/lib/reearth-ui/components/Button/index.stories.tsx b/web/src/beta/lib/reearth-ui/components/Button/index.stories.tsx index cabd61a2a1..d099db8a10 100644 --- a/web/src/beta/lib/reearth-ui/components/Button/index.stories.tsx +++ b/web/src/beta/lib/reearth-ui/components/Button/index.stories.tsx @@ -19,6 +19,7 @@ export const Default: Story = {