A dark all-day menu with dietary filter chips and a search field. Dishes animate out and back in as filters change, with a live counter and an empty state.
Greenline Kitchen · All-day menu
Twelve dishes, cooked to order. Filter by what works for you and every plate is clearly marked.
Showing 12 of 12
Quinoa, charred broccolini, avocado, edamame, herb tahini
Three corn tortillas, chipotle beans, pickled onion, lime crema
Wheat noodles, Sichuan chili oil, crispy tofu, bok choy, sesame
Grilled halloumi, za'atar, blistered tomato, mint yogurt
Buttermilk thigh, hot honey, cabbage slaw, toasted brioche
Brown rice, smashed cucumber, sesame greens, pickled ginger
Slow-roasted tomatoes, basil oil, garlic sourdough crumbs
Herbed chickpea falafel, hummus, pickled turnip, tahini
Lacinato kale, aged parmesan, lemon, garlic crumbs
Rice-flour crunch, sticky gochujang glaze, scallion, sesame
8 oz hanger steak, herb butter, hand-cut fries, aioli
Coconut milk, passion fruit, toasted coconut flakes
npx shadcn@latest add https://hyperblur.dev/r/menu-dietary-filter.jsonWorks in any React project set up with the shadcn CLI. The file lands in components/hyperblur/menu-dietary-filter.tsx.
import { MenuDietaryFilter } from "@/components/hyperblur/menu-dietary-filter"
<MenuDietaryFilter defaultFilters={["vegan"]} onFilterChange={(s) => console.log(s.count)} />| Prop | Type | Default | Description |
|---|---|---|---|
| eyebrow | string | "Greenline Kitchen · All-day menu" | Small line above the heading. |
| title | string | "Eat the way you eat." | Heading. |
| subtitle | string | "Twelve dishes, cooked to order. ..." | Paragraph under the heading. |
| items | { id: string; name: string; description: string; price: number; tags?: MenuDietaryTag[]; art?: "bowl" | "plate" | "wrap" | "soup"; hue?: number }[] | 12 dishes | Menu items. Tags are vegan, vegetarian, gluten-free, spicy, new and popular. Vegan dishes also match the Vegetarian filter. |
| defaultFilters | ("vegan" | "vegetarian" | "gluten-free" | "spicy" | "under-10")[] | [] | Filters active on first render. Several filters combine, so a dish must match all of them. |
| defaultQuery | string | "" | Initial search text. Matches dish names and descriptions. |
| priceLimit | number | 10 | Price used by the Under filter; the chip label follows it. |
| onFilterChange | (state: { filters; query; count }) => void | Called whenever a chip or the search changes, with the number of matching dishes. | |
| accent | string | "#34d399" | Accent color used for highlights, selected states and buttons. |
| className | string | Extra classes on the section root. | |
| style | React.CSSProperties | Inline styles on the section root. |