shadcn.io is an independent project built on shadcn/ui
The title is Leave Site. The buttons are Stay Here and Continue. Continue has an external-link icon after the words, hidden from assistive tech. The demo does not open another site.
Put the icon after the label when it shows where the action goes, and keep the words. If leaving is not a hard choice, a Dialog is enough. In Vue, Ark UI does not open the other site.
Installation
Anatomy

Usage
<AlertDialog>
<AlertDialogTrigger :asChild="true">
<Button variant="outline">Open External Link</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Leave Site?</AlertDialogTitle>
<AlertDialogDescription>
You are about to visit an external website. We are not responsible for the content on external sites.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Stay Here</AlertDialogCancel>
<AlertDialogClose :asChild="true">
<AlertDialogAction>
Continue<ExternalLinkIcon aria-hidden="true" data-icon="inline-end" />
</AlertDialogAction>
</AlertDialogClose>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>FAQ
Should icons go before or after the label?
After it for direction, like an external link or an arrow: they show where the action leads. Before it for icons that describe the action, like download or delete. Mark them with data-icon="inline-end" or data-icon="inline-start" so the button spaces them.
What size should the icon be?
Leave it to the button: it sizes icons to match its text, so there's no size-* class to add.
Should Cancel get an icon too?
Rarely. Stay Here is self-explanatory. Add icons where they add meaning, which is usually only the action.
Do screen readers announce the icon?
No. It's aria-hidden, so the button is read as Continue. Never make a dialog button icon-only; the text is what everyone relies on.
API Reference
Alert Dialog
Sets asChild. The rest is on the Alert Dialog page.
Button
Sets variant="outline". The rest is on the Button page.




