shadcn.io is an independent project built on shadcn/ui
The default button, with a mail icon before the word. The icon is hidden from assistive tech, so the label has to say what happens.
Use it for Send or Download, where people scan a picture and a word together. If the word is already clear, drop the icon. A text Button is enough. In React, Base UI lines the icon up with the label.
Installation
Anatomy

Usage
<Button>
<MailIcon aria-hidden="true" data-icon="inline-start" />
Button
</Button>FAQ
Why is the icon before the label?
The demo puts MailIcon before the text and sets data-icon="inline-start". That attribute is how the button's padding treats an icon, and it flips in a right-to-left layout. The gap comes from the button size.
How do I use a different icon?
Swap the component. MailIcon is a placeholder from lucide-react. Keep data-icon="inline-start" and aria-hidden="true" when the label already says what the button does.
Will a screen reader announce the icon?
No. aria-hidden="true" takes it out, and the label is the accessible name. Drop the label only if you add an aria-label on the button. An icon with no name is an unlabeled control.
How big is the icon?
You don't pass a numeric size. The button styles an svg that has no size-* class, and these demos leave that alone. Add className="size-4" on the icon only when you need to override it.
API Reference
Button
No extra props in this demo. The rest is on the Button page.

