chore(ui,icons,ui-preset,toolbox): Move design system packages to monorepo (#5470)

This commit is contained in:
Kasper Fabricius Kristensen
2023-11-07 22:17:44 +01:00
committed by GitHub
parent 71853eafdd
commit e4ce2f4e07
722 changed files with 30300 additions and 186 deletions

View File

@@ -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 />
},
}

View File

@@ -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 }

View File

@@ -0,0 +1 @@
export * from "./dropdown-menu"