shadcn.io is not affiliated with official shadcn/ui
Download App Dialog Block for Vue
A hiking-map app landing page with its install dialog shown open: a QR code to scan, App Store and Google Play links named in text, iPhone and Android install steps in tabs, and a text-me-a-link field that sends nothing.
Installation
Overview
Get a visitor from a desktop page onto their phone, with this install dialog for Vue with Ark UI. It opens from the landing page of Ridgefold, an offline hiking-map app: the header holds an outline Get the app Button, and the page, a top bar, a headline, two buttons and a phone showing a trail map, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The Dialog shows a QR Code of the download page with "Scan with your phone's camera" under it, and two outline buttons for the App Store and Google Play, named in text beside a two-letter tile. Next to them Tabs hold iPhone and Android with three numbered steps each, the first tab always the same since the page does not sniff the browser. Under it a phone Input offers to text the link: Text me the link, the only Shine Button, checks the number and says what it would do, and nothing is sent. On a phone the code is hidden, because you are already on one, and the store links lead. For preview the dialog is drawn open in place when the page loads; the header button opens the real Dialog.
FAQ
Why is the dialog already open, and what do I keep?
So you can see it without a click. On load the dialog is a copy drawn in place over the page: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Get the app button opens the real Dialog, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same InstallFields component and share the block's state, so a number typed in the copy is there in the real one. In your app keep the Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.
Is the QR code real, and where does it point?
It is a real QR code, drawn by the catalog component from the address in LINK, so a phone pointed at the screen reads it. The address is a placeholder; point it at a page that detects the phone and forwards to the right store, so one code serves both. The code sits in a light tile with a ring so it stays readable in a dark theme.
Do the store links go anywhere?
No. App Store and Google Play are links to # whose handlers say in a polite message that they go nowhere in this demo. Their tiles are two typed letters, not logos. In your app link to your store pages and follow each store's badge and trademark rules if you use their official artwork, which is up to you.
What stays local in the demo, and how do I wire it up?
Text me the link checks that the number has 7 to 15 digits, then says "A text with the link would go to ..." and nothing is sent; a number that doesn't pass shows its problem under the field and keeps focus there. In your app post the number to your server in text, have the server send one message with the link and rate-limit it, and keep the message's wording in the dialog's hint so people know what they agreed to.
Is it accessible from the keyboard?
Yes. The two tabs are a tab list you move through with the arrow keys, the steps are numbered lists named for the phone, the store links are real links, and the field is named by its label. The trigger is the Get the app button wrapped in DialogTrigger with asChild, and the dialog is controlled with open and onOpenChange. The copy shown on load moves no focus; Escape inside it, Close and its close button close it and put focus on Get the app. One polite message reports what a press did.
How does it look on a phone?
The copy shown on load docks to the foot of the page as a bottom sheet, its actions pinned at the bottom with Text me the link on top. The code is hidden and the two store buttons come first, then the install steps and the phone field, all scrolling above the actions. The real dialog keeps the Dialog's own phone layout: a sheet stuck to the bottom of the screen.