Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Restaurant Finder Map Block for Vue

A dining map with cuisine, price and rating filters whose options show how many places each choice would leave, price-and-cuisine pills that hide in place, a best-rated list and opening hours worked out from a fixed time.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Let diners narrow a city by what they feel like eating with this restaurant finder map for Vue with Ark UI. Supperly, a dining guide, draws the invented town of Dunscombe as an SVG street map with ten places as pills, each with a two-letter cuisine code and a price level. A cuisine Toggle Group (Italian, Thai, Lebanese, Vegetarian, Bakery; any of the ones pressed), a price toggle group and a minimum rating select narrow the list, and every option carries the count the other choices would leave, so the number on "Thai" is how many Thai places pass the price and rating you set. A place that stops matching stays on the map in its spot, unseen, so nothing reflows, and leaves the list at the side, best rated first, with its cuisine, price, rating and opening hours ("Open until 22:30", "Closed on Mondays") worked out from one fixed time. A combination with nothing in it shows an empty state in the same box with a button that clears the filters. The list is a scroll region of its own and the way in for the keyboard; the pins are a shortcut for the pointer. A polite status line speaks the count once the controls settle. On a phone the map comes first and the list sits under it. It's built from Toggle Group, Native Select, Empty, Button and Guides, with a CSS entrance only. For dining guides, delivery apps and city guides.

FAQ

How do I fill it with my restaurants?

Edit PLACES. Each place has an id, a name, a cuisine id from CUISINES, a price level from 1 to 3, a rating in tenths (46 is 4.6), opening and closing times in minutes after midnight, an optional closedDay, and an x and y in the drawing's 480 by 360 units. In your app project each restaurant's latitude and longitude onto the map you use and keep passes, the one function that decides whether a place matches.

How are the counts on the options worked out?

Each count is the number of places that would match if that option were the only one chosen in its group, with the other two facets held as they are. So pressing "Thai" never lowers the count on "Italian", because cuisines are an "any of" choice; the price and rating counts do move when you change a cuisine. All three come from the same matchesOf function that builds the list, so they can't disagree with it.

Where do the opening hours come from?

From AS_OF, a fixed Monday evening in the file, compared with each place's opening and closing times and its closed day. It is never read from the clock, so the demo looks the same at any hour. In your app pass the visitor's current time and the venue's time zone.

Can I use it without a mouse?

Yes. The cuisine and price groups are toggle buttons you can reach with Tab and press with Space or Enter, the rating is a native select, and every match is a button in the list that marks the place. The pins on the map are hidden from assistive technology and skipped by the Tab key because the list says the same things in text.

What stays local in the demo, and how do I wire it up?

All of it. The places are typed sample data, the map is a drawing and nothing is searched, saved or sent. Marking a place only highlights it. In your app load the places from your search service when a facet changes, keep the pins mounted so the map doesn't jump, and make a row open the place's page.

How does it look on a phone?

The three filters wrap above the map, which keeps its full width and a fixed height. The list stacks under it in a box that scrolls on its own, so the page never jumps as filters change. The pills are the same size at every width.