Primitives

Menu

Five looks, one API. The highlight slides to the chosen item; a folded branch that holds it lights up instead.

soft · Default — settings, panels

line · Long lists, docs, drawers

raised · Side panels on a page

gradient · The main menu of a page

dark · Command areas, over media

Import#

Everything comes from the package root. The example above uses:

your-component.tsx
import { Badge, Menu, MenuGroup, MenuItem, MenuSub, type MenuLook } from "@waveinno/ui";

Props#

Read from the source of this version, so they match the code exactly.

<Menu>

src/components/ui/menu.tsx
PropTypeDefaultDescription
variant"soft" | "line" | "raised" | "gradient" | "dark" | "panel" | "rail""soft"
valuestring—The chosen item's `value` (controlled).
defaultValuestring—
onValueChange(value: string) => void—
headingReact.ReactNode—On top of the list: a title, or in the rail, the product mark.
collapsibleboolean—A collapse toggle in the heading row.
collapsedboolean—
defaultCollapsedbooleanfalse
onCollapsedChange(collapsed: boolean) => void—
collapsedMode"icons" | "hidden""icons"`icons`: narrow to the icons. `hidden`: fold away entirely (toggle it from outside).
collapseShortcutbooleanfalse⌘B / Ctrl+B toggles it. Off by default: AppShell already uses ⌘B for its panel.

Also takes Omit<React.HTMLAttributes<HTMLElement>, "defaultValue" | "onChange">.

<MenuGroup>

src/components/ui/menu.tsx
PropTypeDefaultDescription
labelReact.ReactNode—
actionReact.ReactNode—Something small on the label's right: a "+" button, a count.
classNamestring—
childrenrequiredReact.ReactNode—

<MenuItem>

src/components/ui/menu.tsx
PropTypeDefaultDescription
iconReact.ReactNode—
descriptionReact.ReactNode—Second line, muted: what is behind the item. Puts the icon in a tile.
badgeReact.ReactNode—
countnumber | string—A number on the right: unread, pending, items inside.
shortcutstring—
valuestring—Chosen when it matches Menu's `value`; clicking makes it the value.
activeboolean—Mark it chosen yourself, e.g. from the router's pathname. Overrides `value`.
dangerboolean—
asChildboolean—Render your own element (a Next.js Link): `<MenuItem asChild><Link href="/x">Label</Link></MenuItem>`.

Also takes Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "value">.

<MenuSub>

src/components/ui/menu.tsx
PropTypeDefaultDescription
iconReact.ReactNode—
descriptionReact.ReactNode—Second line, muted: what is behind the item. Puts the icon in a tile.
badgeReact.ReactNode—
countnumber | string—A number on the right: unread, pending, items inside.
shortcutstring—
labelrequiredReact.ReactNode—
defaultOpenbooleanfalse
openboolean—
onOpenChange(open: boolean) => void—
disabledboolean—
classNamestring—
childrenrequiredReact.ReactNode—

<Badge>

src/components/ui/badge.tsx
PropTypeDefaultDescription
dotbooleantrue
variant"soft" | "solid" | "outline" | "dot" | "gradient" | "live""soft"

Also takes HTMLAttributes<HTMLSpanElement> & VariantProps<typeof badgeVariants>.

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