Primitives
Dropdown menu and Popover
Rich items (icon tile, description, shortcut, badge), account header, dark menu; popovers with arrow, dark and brand.
"use client";
import {
Avatar,
Badge,
Button,
DropdownMenu,
DropdownMenuContent,
DropdownMenuHeader,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
Popover,
PopoverContent,
PopoverHeader,
PopoverTrigger,
} from "@waveinno/ui";
import {
Banknote,
CalendarClock,
Car,
ChevronDown,
Command,
CreditCard,
DoorOpen,
FileUp,
Info,
Keyboard,
LogOut,
Plus,
Search,
Settings,
Sparkles,
UserRound,
Users,
} from "lucide-react";
export default function MenusExample() {
return (
<div className="space-y-4">
<div className="flex flex-wrap gap-2">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button>
Actions <ChevronDown />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>Session</DropdownMenuLabel>
<DropdownMenuItem>View receipt</DropdownMenuItem>
<DropdownMenuItem>Change plate</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem danger>Void</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
{/* Rich: icon tiles, descriptions, shortcuts, a badge, a submenu. */}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="primary">
<Plus /> Create <ChevronDown />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-72">
<DropdownMenuItem icon={<Car />} description="Record a car or bike at the gate" shortcut="N">
New session
</DropdownMenuItem>
<DropdownMenuItem icon={<CalendarClock />} description="Reserve a space for later">
Booking
</DropdownMenuItem>
<DropdownMenuItem icon={<Users />} description="A pass that bills on the 25th" badge={<Badge variant="gradient" dot={false}>Pro</Badge>}>
Monthly parker
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<FileUp /> Import
</DropdownMenuSubTrigger>
<DropdownMenuSubContent>
<DropdownMenuItem>From CSV</DropdownMenuItem>
<DropdownMenuItem>From Excel</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuSub>
</DropdownMenuContent>
</DropdownMenu>
{/* Account menu: identity header. */}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<button type="button" className="cursor-pointer rounded-full">
<Avatar name="Karim Ahmed" status="online" />
</button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-64">
<DropdownMenuHeader media={<Avatar name="Karim Ahmed" size="lg" />} title="Karim Ahmed" subtitle="Owner · Gulshan Parking Ltd" />
<DropdownMenuSeparator />
<DropdownMenuItem icon={<UserRound />} shortcut="P">
Profile
</DropdownMenuItem>
<DropdownMenuItem icon={<Settings />} shortcut=",">
Settings
</DropdownMenuItem>
<DropdownMenuItem icon={<CreditCard />}>Billing</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem icon={<LogOut />} danger>
Sign out
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="dark">
<Command /> Dark menu
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent variant="dark" className="w-64">
<DropdownMenuLabel>Quick actions</DropdownMenuLabel>
<DropdownMenuItem icon={<Search />} shortcut="⌘K">
Search everything
</DropdownMenuItem>
<DropdownMenuItem icon={<DoorOpen />} shortcut="G">
Open a gate
</DropdownMenuItem>
<DropdownMenuItem icon={<Banknote />} shortcut="C">
Close cash shift
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="flex flex-wrap gap-2">
<Popover>
<PopoverTrigger asChild>
<Button>Popover</Button>
</PopoverTrigger>
<PopoverContent className="text-sm text-body">Any content, anchored to its trigger.</PopoverContent>
</Popover>
<Popover>
<PopoverTrigger asChild>
<Button>
<Info /> With arrow
</Button>
</PopoverTrigger>
<PopoverContent arrow side="top" align="center">
<PopoverHeader icon={<Info />} title="Grace period" description="Drivers who leave within 10 minutes pay nothing. Set it per vehicle class." />
</PopoverContent>
</Popover>
<Popover>
<PopoverTrigger asChild>
<Button variant="dark">Dark tip</Button>
</PopoverTrigger>
<PopoverContent variant="dark" arrow align="center" className="w-64">
<PopoverHeader icon={<Keyboard />} title="Keyboard first" description="Press G to open the gate, C to close the shift, ⌘K to search." />
</PopoverContent>
</Popover>
<Popover>
<PopoverTrigger asChild>
<Button variant="gradient">
<Sparkles /> What's new
</Button>
</PopoverTrigger>
<PopoverContent variant="brand" arrow align="center" className="w-80">
<PopoverHeader icon={<Sparkles />} title="Monthly parking is here" description="Sell day and night passes on the same space; bills go out on the 25th." />
<div className="flex justify-end gap-2">
<Button variant="glass" size="sm">
Later
</Button>
<Button variant="white" size="sm">
Show me
</Button>
</div>
</PopoverContent>
</Popover>
</div>
</div>
);
}Import#
Everything comes from the package root. The example above uses:
import {
Avatar,
Badge,
Button,
DropdownMenu,
DropdownMenuContent,
DropdownMenuHeader,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
Popover,
PopoverContent,
PopoverHeader,
PopoverTrigger,
} from "@waveinno/ui";Props#
Read from the source of this version, so they match the code exactly.
<Avatar>
src/components/ui/avatar.tsx| Prop | Type | Default | Description |
|---|---|---|---|
namerequired | string | — | |
src | string | null | — | |
size | keyof typeof sizes | "md" | |
status | keyof typeof STATUS | — | |
verified | boolean | — | |
ring | "gradient" | — | |
shape | "circle" | "square" | "circle" | |
className | string | — |
<Badge>
src/components/ui/badge.tsx| Prop | Type | Default | Description |
|---|---|---|---|
dot | boolean | true | |
variant | "soft" | "solid" | "outline" | "dot" | "gradient" | "live" | "soft" |
Also takes HTMLAttributes<HTMLSpanElement> & VariantProps<typeof badgeVariants>.
<Button>
src/components/ui/button.tsx| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | |
loading | boolean | — |
Also takes ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof buttonVariants>.
<DropdownMenuContent>
src/components/ui/dropdown-menu.tsx| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "glass" | "dark" | "default" |
Also takes ComponentPropsWithoutRef<typeof Primitive.Content>.
<DropdownMenuHeader>
src/components/ui/dropdown-menu.tsx| Prop | Type | Default | Description |
|---|---|---|---|
titlerequired | React.ReactNode | — | |
subtitle | React.ReactNode | — | |
media | React.ReactNode | — | An Avatar or mark. |
className | string | — |
<DropdownMenuItem>
src/components/ui/dropdown-menu.tsx| Prop | Type | Default | Description |
|---|---|---|---|
danger | boolean | — | |
icon | React.ReactNode | — | Icon in a soft tile on the left. |
description | React.ReactNode | — | Second line, muted: what the item does. |
shortcut | string | — | |
badge | React.ReactNode | — |
Also takes ComponentPropsWithoutRef<typeof Primitive.Item>.
<DropdownMenuLabel>
src/components/ui/dropdown-menu.tsxAlso takes ComponentPropsWithoutRef<typeof Primitive.Label> (passed through).
<DropdownMenuSeparator>
src/components/ui/dropdown-menu.tsxAlso takes ComponentPropsWithoutRef<typeof Primitive.Separator> (passed through).
<DropdownMenuSubContent>
src/components/ui/dropdown-menu.tsxAlso takes ComponentPropsWithoutRef<typeof Primitive.SubContent> (passed through).
<DropdownMenuSubTrigger>
src/components/ui/dropdown-menu.tsxAlso takes ComponentPropsWithoutRef<typeof Primitive.SubTrigger> (passed through).
<PopoverContent>
src/components/ui/popover.tsx| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "glass" | "dark" | "brand" | "default" | |
arrow | boolean | false |
Also takes ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>.
<PopoverHeader>
src/components/ui/popover.tsx| Prop | Type | Default | Description |
|---|---|---|---|
titlerequired | React.ReactNode | — | |
description | React.ReactNode | — | |
icon | React.ReactNode | — | |
className | string | — |
Install#
If the project does not have the package yet, add it, then follow the setup for Next.js or Vite once.
$ npm install @waveinno/ui