Buttondown Documentation
shadcn/ui is a collection of re-usable components that you can copy and paste into your apps. You can install different shadcn/ui components and use them to create a subscription component for your newsletter.
To use the examples below, you'll need to install the Card, Button, Input, and Label components:
npx shadcn-ui@latest add button card input label
You may notice that we do not install the Form
component. That's intentional; shadcn's form boilerplate pulls in React Hook Form and Zod, both of which are great libraries but overkill for simple subscription forms. If you've already installed them and want to use them, you can, but use the URL shown in the examples below for the action
prop of Form
.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>shadcn/ui Buttondown Example - Basic</title>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
border: "hsl(214.3 31.8% 91.4%)",
input: "hsl(214.3 31.8% 91.4%)",
ring: "hsl(222.2 84% 4.9%)",
background: "hsl(0 0% 100%)",
foreground: "hsl(222.2 84% 4.9%)",
primary: {
DEFAULT: "hsl(222.2 47.4% 11.2%)",
foreground: "hsl(210 40% 98%)",
},
secondary: {
DEFAULT: "hsl(210 40% 96.1%)",
foreground: "hsl(222.2 47.4% 11.2%)",
},
muted: {
DEFAULT: "hsl(210 40% 96.1%)",
foreground: "hsl(215.4 16.3% 46.9%)",
},
card: {
DEFAULT: "hsl(0 0% 100%)",
foreground: "hsl(222.2 84% 4.9%)",
},
},
borderRadius: {
lg: "0.5rem",
md: "calc(0.5rem - 2px)",
sm: "calc(0.5rem - 4px)",
},
},
},
}
</script>
<style>
* { box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", sans-serif; }
</style>
</head>
<body class="min-h-screen flex items-center justify-center bg-gray-50">
<div class="w-full max-w-sm mx-auto rounded-lg border bg-card text-card-foreground shadow-sm">
<form
action="https://buttondown.com/api/emails/embed-subscribe/YOUR-BUTTONDOWN-USERNAME"
method="post"
>
<div class="flex flex-col space-y-1.5 p-6">
<h3 class="text-2xl font-semibold leading-none tracking-tight">Stay informed</h3>
<p class="text-sm text-muted-foreground">
You'll be the first to know when we launch.
</p>
</div>
<div class="p-6 pt-0 grid gap-4">
<div class="grid gap-2">
<label class="text-sm font-medium leading-none" for="email">Email</label>
<input
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
id="email"
name="email"
type="email"
placeholder="m@example.com"
required
/>
</div>
</div>
<div class="flex items-center p-6 pt-0">
<button class="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 bg-primary text-primary-foreground hover:bg-primary/90 h-10 px-4 py-2 w-full" type="submit">
Subscribe
</button>
</div>
</form>
</div>
</body>
</html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>shadcn/ui Buttondown Example - Dropdown</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
border: "hsl(214.3 31.8% 91.4%)",
input: "hsl(214.3 31.8% 91.4%)",
ring: "hsl(222.2 84% 4.9%)",
background: "hsl(0 0% 100%)",
foreground: "hsl(222.2 84% 4.9%)",
primary: {
DEFAULT: "hsl(222.2 47.4% 11.2%)",
foreground: "hsl(210 40% 98%)",
},
secondary: {
DEFAULT: "hsl(210 40% 96.1%)",
foreground: "hsl(222.2 47.4% 11.2%)",
},
muted: {
DEFAULT: "hsl(210 40% 96.1%)",
foreground: "hsl(215.4 16.3% 46.9%)",
},
card: {
DEFAULT: "hsl(0 0% 100%)",
foreground: "hsl(222.2 84% 4.9%)",
},
},
borderRadius: {
lg: "0.5rem",
md: "calc(0.5rem - 2px)",
sm: "calc(0.5rem - 4px)",
},
},
},
}
</script>
<style>
* { box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", sans-serif; }
</style>
</head>
<body class="min-h-screen flex items-center justify-center bg-gray-50">
<div id="root"></div>
<script type="text/babel">
function SubscribeForm() {
const [language, setLanguage] = React.useState("english");
return (
<div className="w-full max-w-sm mx-auto rounded-lg border bg-card text-card-foreground shadow-md">
<form
action="https://buttondown.com/api/emails/embed-subscribe/YOUR-BUTTONDOWN-USERNAME"
method="post"
>
<div className="flex flex-col space-y-1.5 p-6">
<h3 className="text-2xl font-semibold leading-none tracking-tight">Stay informed</h3>
<p className="text-sm text-muted-foreground">
You'll be the first to know when we launch.
</p>
</div>
<div className="p-6 pt-0 grid gap-4">
<div className="grid gap-2">
<label className="text-sm font-medium leading-none" htmlFor="email">Email</label>
<input
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
id="email"
name="email"
type="email"
placeholder="m@example.com"
required
/>
</div>
<div className="grid gap-2">
<input type="hidden" name="tag" value={language} />
<label className="text-sm font-medium leading-none" htmlFor="language">Language</label>
<select
className="flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
value={language}
onChange={(e) => setLanguage(e.target.value)}
>
<option value="english">English</option>
<option value="french">French</option>
<option value="spanish">Spanish</option>
</select>
</div>
</div>
<div className="flex items-center p-6 pt-0">
<button className="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 bg-primary text-primary-foreground hover:bg-primary/90 h-10 px-4 py-2 w-full" type="submit">
{language === "english"
? "Subscribe"
: language === "french"
? "S'abonner"
: "Suscribirse"}
</button>
</div>
</form>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<SubscribeForm />);
</script>
</body>
</html>