A bottom sheet on narrow screens and a side drawer on wide ones for customizing one item: single and multiple choice groups, removable ingredients, quantity, a note and a live total on the add button.
7 oz chuck and brisket patty, aged cheddar, charred onion jam, brioche bun.
npx shadcn@latest add https://hyperblur.dev/r/order-item-drawer.jsonWorks in any React project set up with the shadcn CLI. The file lands in components/hyperblur/order-item-drawer.tsx.
import { OrderItemDrawer } from "@/components/hyperblur/order-item-drawer"
<OrderItemDrawer open={open} onOpenChange={setOpen} onAdd={(order) => addToCart(order)} />| Prop | Type | Default | Description |
|---|---|---|---|
| item | { id: string; name: string; description: string; price: number; badge?: string; tint?: string } | Steakhouse Burger, $15.50 | The item being customized. |
| groups | OrderItemGroup[] | Doneness, side, extras, remove | Option groups: { id, title, type: "single" | "multiple" | "remove", required?, min?, max?, options: { id, label, price?, hint? }[], defaultSelected? }. Required groups block the button until satisfied. |
| image | ReactNode | Hero art slot. Defaults to an illustrated burger. | |
| open | boolean | Controlled open state. | |
| defaultOpen | boolean | false | Initial open state when uncontrolled. |
| onOpenChange | (open: boolean) => void | Called on close button, Escape, backdrop click and after adding. | |
| onAdd | (payload: { itemId; quantity; selections: Record<string, string[]>; note; unitPrice; total }) => void | Called with the configured item when the button is pressed and every required group is satisfied. | |
| currency | string | "USD" | ISO currency code passed to Intl.NumberFormat. Prices are plain numbers. |
| locale | string | "en-US" | Locale passed to Intl.NumberFormat for every price. |
| labels | Partial<OrderItemDrawerLabels> | English copy | Every visible string: dialog, close, required, optional, done, chooseOne, chooseUpTo, chooseBetween, chooseAtLeast, removeHint, missing, note, notePlaceholder, quantity, decrease, increase, add, added. Rules use {min} and {max}. |
| accent | string | "#ff6a3d" | Color of the button, selected options and focus rings. |
| appearance | "dark" | "light" | "dark" | Dark or light panel. |
| inline | boolean | false | Render the panel in place, always open and without the overlay, to embed it in a page or preview. It fills its parent height. |
| defaultQuantity | number | 1 | Quantity when the drawer opens. |
| maxQuantity | number | 20 | Upper limit of the stepper. |
| noteMaxLength | number | 140 | Character limit of the note. |
| closeOnAdd | boolean | true | Close the drawer after a successful add. Inline panels show an Added state instead. |
| className | string | Extra classes on the root. | |
| style | React.CSSProperties | Inline styles on the root. |