chore(ui,icons,ui-preset,toolbox): Move design system packages to monorepo (#5470)
This commit is contained in:
committed by
GitHub
parent
71853eafdd
commit
e4ce2f4e07
@@ -0,0 +1,275 @@
|
||||
import { EllipsisHorizontal, PencilSquare, Plus, Trash } from "@medusajs/icons"
|
||||
import type { Meta, StoryObj } from "@storybook/react"
|
||||
import * as React from "react"
|
||||
|
||||
import { Button } from "@/components/button"
|
||||
import { IconButton } from "@/components/icon-button"
|
||||
import { Select } from "@/components/select"
|
||||
|
||||
import { DatePicker } from "../date-picker"
|
||||
import { FocusModal } from "../focus-modal"
|
||||
import { DropdownMenu } from "./dropdown-menu"
|
||||
|
||||
const meta: Meta<typeof DropdownMenu> = {
|
||||
title: "Components/DropdownMenu",
|
||||
component: DropdownMenu,
|
||||
}
|
||||
|
||||
export default meta
|
||||
|
||||
type Story = StoryObj<typeof DropdownMenu>
|
||||
|
||||
type SortingState = "asc" | "desc" | "alpha" | "alpha-reverse" | "none"
|
||||
|
||||
const SortingDemo = () => {
|
||||
const [sort, setSort] = React.useState<SortingState>("none")
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-y-2">
|
||||
<DropdownMenu>
|
||||
<DropdownMenu.Trigger asChild>
|
||||
<IconButton variant="primary">
|
||||
<EllipsisHorizontal />
|
||||
</IconButton>
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Content className="w-[300px]">
|
||||
<DropdownMenu.RadioGroup
|
||||
value={sort}
|
||||
onValueChange={(v) => setSort(v as SortingState)}
|
||||
>
|
||||
<DropdownMenu.RadioItem value="none">
|
||||
No Sorting
|
||||
</DropdownMenu.RadioItem>
|
||||
<DropdownMenu.Separator />
|
||||
<DropdownMenu.RadioItem value="alpha">
|
||||
Alphabetical
|
||||
<DropdownMenu.Hint>A-Z</DropdownMenu.Hint>
|
||||
</DropdownMenu.RadioItem>
|
||||
<DropdownMenu.RadioItem value="alpha-reverse">
|
||||
Reverse Alphabetical
|
||||
<DropdownMenu.Hint>Z-A</DropdownMenu.Hint>
|
||||
</DropdownMenu.RadioItem>
|
||||
<DropdownMenu.RadioItem value="asc">
|
||||
Created At - Ascending
|
||||
<DropdownMenu.Hint>1 - 30</DropdownMenu.Hint>
|
||||
</DropdownMenu.RadioItem>
|
||||
<DropdownMenu.RadioItem value="desc">
|
||||
Created At - Descending
|
||||
<DropdownMenu.Hint>30 - 1</DropdownMenu.Hint>
|
||||
</DropdownMenu.RadioItem>
|
||||
</DropdownMenu.RadioGroup>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu>
|
||||
<div>
|
||||
<pre>Sorting by: {sort}</pre>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const SortingMenu: Story = {
|
||||
render: () => {
|
||||
return <SortingDemo />
|
||||
},
|
||||
}
|
||||
|
||||
const SelectDemo = () => {
|
||||
const [currencies, setCurrencies] = React.useState<string[]>([])
|
||||
const [regions, setRegions] = React.useState<string[]>([])
|
||||
|
||||
const onSelectCurrency = (currency: string) => {
|
||||
if (currencies.includes(currency)) {
|
||||
setCurrencies(currencies.filter((c) => c !== currency))
|
||||
} else {
|
||||
setCurrencies([...currencies, currency])
|
||||
}
|
||||
}
|
||||
|
||||
const onSelectRegion = (region: string) => {
|
||||
if (regions.includes(region)) {
|
||||
setRegions(regions.filter((r) => r !== region))
|
||||
} else {
|
||||
setRegions([...regions, region])
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-y-2">
|
||||
<DropdownMenu>
|
||||
<DropdownMenu.Trigger asChild>
|
||||
<IconButton>
|
||||
<EllipsisHorizontal />
|
||||
</IconButton>
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Content className="w-[300px]">
|
||||
<DropdownMenu.Group>
|
||||
<DropdownMenu.Label>Currencies</DropdownMenu.Label>
|
||||
<DropdownMenu.CheckboxItem
|
||||
checked={currencies.includes("EUR")}
|
||||
onSelect={(e) => {
|
||||
e.preventDefault()
|
||||
onSelectCurrency("EUR")
|
||||
}}
|
||||
>
|
||||
EUR
|
||||
<DropdownMenu.Hint>Euro</DropdownMenu.Hint>
|
||||
</DropdownMenu.CheckboxItem>
|
||||
<DropdownMenu.CheckboxItem
|
||||
checked={currencies.includes("USD")}
|
||||
onSelect={(e) => {
|
||||
e.preventDefault()
|
||||
onSelectCurrency("USD")
|
||||
}}
|
||||
>
|
||||
USD
|
||||
<DropdownMenu.Hint>US Dollar</DropdownMenu.Hint>
|
||||
</DropdownMenu.CheckboxItem>
|
||||
<DropdownMenu.CheckboxItem
|
||||
checked={currencies.includes("DKK")}
|
||||
onSelect={(e) => {
|
||||
e.preventDefault()
|
||||
onSelectCurrency("DKK")
|
||||
}}
|
||||
>
|
||||
DKK
|
||||
<DropdownMenu.Hint>Danish Krone</DropdownMenu.Hint>
|
||||
</DropdownMenu.CheckboxItem>
|
||||
</DropdownMenu.Group>
|
||||
<DropdownMenu.Separator />
|
||||
<DropdownMenu.Group>
|
||||
<DropdownMenu.Label>Regions</DropdownMenu.Label>
|
||||
<DropdownMenu.CheckboxItem
|
||||
checked={regions.includes("NA")}
|
||||
onSelect={(e) => {
|
||||
e.preventDefault()
|
||||
onSelectRegion("NA")
|
||||
}}
|
||||
>
|
||||
North America
|
||||
</DropdownMenu.CheckboxItem>
|
||||
<DropdownMenu.CheckboxItem
|
||||
checked={regions.includes("EU")}
|
||||
onSelect={(e) => {
|
||||
e.preventDefault()
|
||||
onSelectRegion("EU")
|
||||
}}
|
||||
>
|
||||
Europe
|
||||
</DropdownMenu.CheckboxItem>
|
||||
<DropdownMenu.CheckboxItem
|
||||
checked={regions.includes("DK")}
|
||||
onSelect={(e) => {
|
||||
e.preventDefault()
|
||||
onSelectRegion("DK")
|
||||
}}
|
||||
>
|
||||
Denmark
|
||||
</DropdownMenu.CheckboxItem>
|
||||
</DropdownMenu.Group>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu>
|
||||
<div>
|
||||
<pre>Currencies: {currencies.join(", ")}</pre>
|
||||
<pre>Regions: {regions.join(", ")}</pre>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const SelectMenu: Story = {
|
||||
render: () => {
|
||||
return <SelectDemo />
|
||||
},
|
||||
}
|
||||
|
||||
export const SimpleMenu: Story = {
|
||||
render: () => {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenu.Trigger asChild>
|
||||
<IconButton>
|
||||
<EllipsisHorizontal />
|
||||
</IconButton>
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Content>
|
||||
<DropdownMenu.Item className="gap-x-2">
|
||||
<PencilSquare className="text-ui-fg-subtle" />
|
||||
Edit
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item className="gap-x-2">
|
||||
<Plus className="text-ui-fg-subtle" />
|
||||
Add
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Separator />
|
||||
<DropdownMenu.Item className="gap-x-2">
|
||||
<Trash className="text-ui-fg-subtle" />
|
||||
Delete
|
||||
</DropdownMenu.Item>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
const ComplexMenuDemo = () => {
|
||||
return (
|
||||
<FocusModal>
|
||||
<FocusModal.Trigger asChild>
|
||||
<Button>Open</Button>
|
||||
</FocusModal.Trigger>
|
||||
<FocusModal.Content>
|
||||
<FocusModal.Header>
|
||||
<Button>Save</Button>
|
||||
</FocusModal.Header>
|
||||
<FocusModal.Body className="item-center flex justify-center">
|
||||
<div>
|
||||
<DropdownMenu>
|
||||
<DropdownMenu.Trigger asChild>
|
||||
<Button>View</Button>
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Content>
|
||||
<DropdownMenu.Item className="gap-x-2">
|
||||
<PencilSquare className="text-ui-fg-subtle" />
|
||||
Edit
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item className="gap-x-2">
|
||||
<Plus className="text-ui-fg-subtle" />
|
||||
Add
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Separator />
|
||||
<DropdownMenu.Item className="gap-x-2">
|
||||
<Trash className="text-ui-fg-subtle" />
|
||||
Delete
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Separator />
|
||||
<div className="flex flex-col gap-y-2 p-2">
|
||||
<Select>
|
||||
<Select.Trigger>
|
||||
<Select.Value placeholder="Select" />
|
||||
</Select.Trigger>
|
||||
<Select.Content>
|
||||
<Select.Item value="1">One</Select.Item>
|
||||
<Select.Item value="2">Two</Select.Item>
|
||||
<Select.Item value="3">Three</Select.Item>
|
||||
</Select.Content>
|
||||
</Select>
|
||||
<DatePicker />
|
||||
</div>
|
||||
<div className="border-ui-border-base flex items-center gap-x-2 border-t p-2">
|
||||
<Button variant="secondary">Clear</Button>
|
||||
<Button>Apply</Button>
|
||||
</div>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</FocusModal.Body>
|
||||
</FocusModal.Content>
|
||||
</FocusModal>
|
||||
)
|
||||
}
|
||||
|
||||
export const ComplexMenu: Story = {
|
||||
render: () => {
|
||||
return <ComplexMenuDemo />
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
"use client"
|
||||
|
||||
import { CheckMini, ChevronRightMini, EllipseMiniSolid } from "@medusajs/icons"
|
||||
import * as Primitives from "@radix-ui/react-dropdown-menu"
|
||||
import * as React from "react"
|
||||
|
||||
import { clx } from "@/utils/clx"
|
||||
|
||||
const Root = Primitives.Root
|
||||
Root.displayName = "DropdownMenu.Root"
|
||||
|
||||
const Trigger = Primitives.Trigger
|
||||
Trigger.displayName = "DropdownMenu.Trigger"
|
||||
|
||||
const Group = Primitives.Group
|
||||
Group.displayName = "DropdownMenu.Group"
|
||||
|
||||
const SubMenu = Primitives.Sub
|
||||
SubMenu.displayName = "DropdownMenu.SubMenu"
|
||||
|
||||
const RadioGroup = Primitives.RadioGroup
|
||||
RadioGroup.displayName = "DropdownMenu.RadioGroup"
|
||||
|
||||
const SubMenuTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof Primitives.SubTrigger>,
|
||||
React.ComponentPropsWithoutRef<typeof Primitives.SubTrigger>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<Primitives.SubTrigger
|
||||
ref={ref}
|
||||
className={clx(
|
||||
"focus:bg-ui-bg-base-pressed data-[state=open]:bg-ui-bg-base-pressed txt-compact-small flex cursor-default select-none items-center rounded-sm px-3 py-2 outline-none",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<ChevronRightMini className="ml-auto" />
|
||||
</Primitives.SubTrigger>
|
||||
))
|
||||
SubMenuTrigger.displayName = "DropdownMenu.SubMenuTrigger"
|
||||
|
||||
const SubMenuContent = React.forwardRef<
|
||||
React.ElementRef<typeof Primitives.SubContent>,
|
||||
React.ComponentPropsWithoutRef<typeof Primitives.SubContent>
|
||||
>(({ className, collisionPadding = 8, ...props }, ref) => (
|
||||
<Primitives.Portal>
|
||||
<Primitives.SubContent
|
||||
ref={ref}
|
||||
collisionPadding={collisionPadding}
|
||||
className={clx(
|
||||
"bg-ui-bg-base text-ui-fg-base shadow-elevation-flyout max-h-[var(--radix-popper-available-height)] min-w-[8rem] overflow-hidden rounded-lg border p-1",
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</Primitives.Portal>
|
||||
))
|
||||
SubMenuContent.displayName = "DropdownMenu.SubMenuContent"
|
||||
|
||||
const Content = React.forwardRef<
|
||||
React.ElementRef<typeof Primitives.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof Primitives.Content>
|
||||
>(
|
||||
(
|
||||
{
|
||||
className,
|
||||
sideOffset = 8,
|
||||
collisionPadding = 8,
|
||||
align = "start",
|
||||
...props
|
||||
},
|
||||
ref
|
||||
) => (
|
||||
<Primitives.Portal>
|
||||
<Primitives.Content
|
||||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
align={align}
|
||||
collisionPadding={collisionPadding}
|
||||
className={clx(
|
||||
"bg-ui-bg-base text-ui-fg-base shadow-elevation-flyout max-h-[var(--radix-popper-available-height)] min-w-[220px] overflow-hidden rounded-lg p-1",
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</Primitives.Portal>
|
||||
)
|
||||
)
|
||||
Content.displayName = "DropdownMenu.Content"
|
||||
|
||||
const Item = React.forwardRef<
|
||||
React.ElementRef<typeof Primitives.Item>,
|
||||
React.ComponentPropsWithoutRef<typeof Primitives.Item>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<Primitives.Item
|
||||
ref={ref}
|
||||
className={clx(
|
||||
"bg-ui-bg-base focus:bg-ui-bg-base-pressed text-ui-fg-base data-[disabled]:text-ui-fg-disabled txt-compact-small relative flex cursor-pointer select-none items-center rounded-md px-3 py-2 outline-none transition-colors data-[disabled]:pointer-events-none",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Item.displayName = "DropdownMenu.Item"
|
||||
|
||||
const CheckboxItem = React.forwardRef<
|
||||
React.ElementRef<typeof Primitives.CheckboxItem>,
|
||||
React.ComponentPropsWithoutRef<typeof Primitives.CheckboxItem>
|
||||
>(({ className, children, checked, ...props }, ref) => (
|
||||
<Primitives.CheckboxItem
|
||||
ref={ref}
|
||||
className={clx(
|
||||
"focus:bg-ui-bg-base-pressed text-ui-fg-base data-[disabled]:text-ui-fg-disabled relative flex cursor-pointer select-none items-center rounded-md py-2 pl-10 pr-3 text-sm outline-none transition-colors data-[disabled]:pointer-events-none",
|
||||
className
|
||||
)}
|
||||
checked={checked}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute left-3 flex h-5 w-5 items-center justify-center">
|
||||
<Primitives.ItemIndicator>
|
||||
<CheckMini />
|
||||
</Primitives.ItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
</Primitives.CheckboxItem>
|
||||
))
|
||||
CheckboxItem.displayName = "DropdownMenu.CheckboxItem"
|
||||
|
||||
const RadioItem = React.forwardRef<
|
||||
React.ElementRef<typeof Primitives.RadioItem>,
|
||||
React.ComponentPropsWithoutRef<typeof Primitives.RadioItem>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<Primitives.RadioItem
|
||||
ref={ref}
|
||||
className={clx(
|
||||
"focus:bg-ui-bg-base-pressed hover:bg-ui-base-hover bg-ui-bg-base txt-compact-small relative flex cursor-pointer select-none items-center rounded-md py-2 pl-10 pr-3 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[state=checked]:font-medium data-[disabled]:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute left-3 flex h-5 w-5 items-center justify-center">
|
||||
<Primitives.ItemIndicator>
|
||||
<EllipseMiniSolid className="text-ui-fg-base" />
|
||||
</Primitives.ItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
</Primitives.RadioItem>
|
||||
))
|
||||
RadioItem.displayName = "DropdownMenu.RadioItem"
|
||||
|
||||
const Label = React.forwardRef<
|
||||
React.ElementRef<typeof Primitives.Label>,
|
||||
React.ComponentPropsWithoutRef<typeof Primitives.Label>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<Primitives.Label
|
||||
ref={ref}
|
||||
className={clx(
|
||||
"text-ui-fg-subtle txt-compact-xsmall-plus px-2 py-1.5",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Label.displayName = "DropdownMenu.Label"
|
||||
|
||||
const Separator = React.forwardRef<
|
||||
React.ElementRef<typeof Primitives.Separator>,
|
||||
React.ComponentPropsWithoutRef<typeof Primitives.Separator>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<Primitives.Separator
|
||||
ref={ref}
|
||||
className={clx("bg-ui-border-base -mx-1 my-1 h-px", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Separator.displayName = "DropdownMenu.Separator"
|
||||
|
||||
const Shortcut = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||
return (
|
||||
<span
|
||||
className={clx(
|
||||
"text-ui-fg-subtle txt-compact-small ml-auto tracking-widest",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
Shortcut.displayName = "DropdownMenu.Shortcut"
|
||||
|
||||
const Hint = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||
return (
|
||||
<span
|
||||
className={clx(
|
||||
"text-ui-fg-subtle txt-compact-small ml-auto tracking-widest",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
Hint.displayName = "DropdownMenu.Hint"
|
||||
|
||||
const DropdownMenu = Object.assign(Root, {
|
||||
Trigger,
|
||||
Group,
|
||||
SubMenu,
|
||||
SubMenuContent,
|
||||
SubMenuTrigger,
|
||||
Content,
|
||||
Item,
|
||||
CheckboxItem,
|
||||
RadioGroup,
|
||||
RadioItem,
|
||||
Label,
|
||||
Separator,
|
||||
Shortcut,
|
||||
Hint,
|
||||
})
|
||||
|
||||
export { DropdownMenu }
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./dropdown-menu"
|
||||
Reference in New Issue
Block a user