Primitives
Dialog and Sheet
The drawer dialog is full width on phones; the centred one is for short confirmations.
"use client";
import {
Button,
Dialog,
DialogBody,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
Input,
Label,
Switch,
Sheet,
SheetContent,
SheetDescription,
SheetTitle,
SheetTrigger,
} from "@waveinno/ui";
import { Tag } from "lucide-react";
export default function DialogExample() {
return (
<div className="flex flex-wrap gap-2">
<Dialog>
<DialogTrigger asChild>
<Button>Open drawer dialog</Button>
</DialogTrigger>
<DialogContent size="md">
<DialogHeader icon={<Tag />} eyebrow="Rate plan · Gulshan">
<DialogTitle>Edit car rates</DialogTitle>
<DialogDescription>Changes apply to new sessions only. Vehicles inside keep their rate.</DialogDescription>
</DialogHeader>
<DialogBody className="space-y-4">
<div className="grid grid-cols-2 gap-3">
<div className="space-y-1.5">
<Label htmlFor="d-first">First hour (৳)</Label>
<Input id="d-first" defaultValue="60" />
</div>
<div className="space-y-1.5">
<Label htmlFor="d-next">Each next hour (৳)</Label>
<Input id="d-next" defaultValue="40" />
</div>
</div>
<div className="space-y-1.5">
<Label htmlFor="d-cap">Daily cap (৳)</Label>
<Input id="d-cap" defaultValue="400" />
</div>
<label className="flex items-center justify-between rounded-ctl border border-border p-3 text-[13px] text-body">
Grace period of 10 minutes <Switch defaultChecked />
</label>
{Array.from({ length: 6 }, (_, i) => (
<p key={i} className="text-[13px] leading-relaxed text-muted">
Long forms scroll under the frosted footer; the actions never leave the screen.
</p>
))}
</DialogBody>
<DialogFooter className="justify-between">
<Button variant="ghost">Preview receipt</Button>
<div className="flex gap-2">
<Button>Cancel</Button>
<Button variant="primary">Publish v7</Button>
</div>
</DialogFooter>
</DialogContent>
</Dialog>
<Dialog>
<DialogTrigger asChild>
<Button>Open centred dialog</Button>
</DialogTrigger>
<DialogContent variant="center" width="max-w-[420px]">
<DialogHeader>
<DialogTitle>Delete this rate?</DialogTitle>
<DialogDescription>This cannot be undone.</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant="danger">Delete</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<Sheet>
<SheetTrigger asChild>
<Button>Open sheet</Button>
</SheetTrigger>
<SheetContent>
<div className="p-5">
<SheetTitle className="text-base font-semibold text-text">Sheet</SheetTitle>
<SheetDescription className="mt-1 text-sm text-muted">Side panel for details and forms.</SheetDescription>
</div>
</SheetContent>
</Sheet>
</div>
);
}Import#
Everything comes from the package root. The example above uses:
import {
Button,
Dialog,
DialogBody,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
Input,
Label,
Switch,
Sheet,
SheetContent,
SheetDescription,
SheetTitle,
SheetTrigger,
} from "@waveinno/ui";Props#
Read from the source of this version, so they match the code exactly.
<DialogBody>
src/components/ui/dialog.tsxAlso takes HTMLAttributes<HTMLDivElement> (passed through).
<DialogContent>
src/components/ui/dialog.tsx| Prop | Type | Default | Description |
|---|---|---|---|
width | string | — | Maximum width, e.g. "max-w-[560px]". The drawer is full width on phones. |
size | keyof typeof SIZES | "md" | Width preset; `width` wins when both are given. |
resizable | boolean | true | Drawer only: show the widen / full-width buttons. On by default. |
hideClose | boolean | — | |
variant | "drawer" | "center" | "drawer" |
Also takes ComponentPropsWithoutRef<typeof DialogPrimitive.Content>.
<DialogDescription>
src/components/ui/dialog.tsxAlso takes ComponentPropsWithoutRef<typeof DialogPrimitive.Description> (passed through).
<DialogFooter>
src/components/ui/dialog.tsxAlso takes HTMLAttributes<HTMLDivElement> (passed through).
<DialogHeader>
src/components/ui/dialog.tsx| Prop | Type | Default | Description |
|---|---|---|---|
icon | React.ReactNode | — | A lucide icon (or any node) in a tinted tile beside the title. |
eyebrow | React.ReactNode | — | One short line above the title: the object or step, e.g. "Rate plan" or "Step 2 of 3". |
Also takes HTMLAttributes<HTMLDivElement>.
<DialogTitle>
src/components/ui/dialog.tsxAlso takes ComponentPropsWithoutRef<typeof DialogPrimitive.Title> (passed through).
<Button>
src/components/ui/button.tsx| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | |
loading | boolean | — |
Also takes ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof buttonVariants>.
<Input>
src/components/ui/input.tsx| Prop | Type | Default | Description |
|---|---|---|---|
state | "default" | "error" | "warning" | "success" | "default" | |
leading | React.ReactNode | — | Icon or text inside the box, before the value (a search icon, "৳", "+880"). |
trailing | React.ReactNode | — | After the value: a unit, a clear button, a status icon. |
Also takes InputHTMLAttributes<HTMLInputElement>.
<Label>
src/components/ui/label.tsx| Prop | Type | Default | Description |
|---|---|---|---|
required | boolean | — |
Also takes ComponentPropsWithoutRef<typeof LabelPrimitive.Root>.
<Switch>
src/components/ui/switch.tsxAlso takes ComponentPropsWithoutRef<typeof SwitchPrimitive.Root> (passed through).
<SheetContent>
src/components/ui/sheet.tsx| Prop | Type | Default | Description |
|---|---|---|---|
side | "right" | "left" | "bottom" | "right" | |
width | string | — | Width classes for a side sheet. Default "w-full sm:w-drawer". |
scrim | boolean | true | |
hideClose | boolean | — |
Also takes ComponentPropsWithoutRef<typeof DialogPrimitive.Content>.
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