Marketing Button
The gradient marketing buttons from the Notra landing page.
import { ArrowRight } from "lucide-react";
import { MarketingButton } from "../components/marketing-button";
export default function MarketingButtonDemo() {
return (
<div className="flex w-full min-w-0 flex-wrap items-center justify-center gap-6 p-8">
<MarketingButton>
Start for free
<ArrowRight />
</MarketingButton>
<MarketingButton variant="light">Book a call</MarketingButton>
</div>
);
}
$ bunx --bun shadcn@latest add @notra/marketing-buttonMarketingButton is built on Base UI’s Button, like the shadcn Button, so it takes every Button prop, including a className callback. The gradients and hover states ship as three Tailwind utilities, marketing-gradient-primary, marketing-gradient-flat and marketing-gradient-light, added to your CSS by the install.
| Prop | Default | Description |
|---|---|---|
variant |
primary |
primary is the purple gradient, flat is the same gradient without the halo, light is the white one. |
size |
default |
sm is 40px tall, default is 44px, lg is 48px. |
loading |
false |
Swaps the label for a spinner, like Button’s loading state, and keeps the button’s width. The button stays focusable and ignores clicks. |
render |
none | Base UI’s render prop. Pass an element to render a link. |
nativeButton |
true |
Set to false when render is not a <button>. |
Primary
The purple gradient, for the main call to action.
import { ArrowRight } from "lucide-react";
import { MarketingButton } from "../components/marketing-button";
export default function MarketingButtonPrimary() {
return (
<div className="flex w-full min-w-0 flex-wrap items-center justify-center gap-6 p-8">
<MarketingButton>
Start for free
<ArrowRight />
</MarketingButton>
</div>
);
}
Secondary
The white gradient with variant="light", for the action next to it.
import { MarketingButton } from "../components/marketing-button";
export default function MarketingButtonSecondary() {
return (
<div className="flex w-full min-w-0 flex-wrap items-center justify-center gap-6 p-8">
<MarketingButton variant="light">Book a call</MarketingButton>
</div>
);
}
Loading
Set loading while the action runs. The label blurs up and out and a spinner rises in at its center, the same swap as Button with a spinner instead of dots. The button keeps its width, so nothing around it moves.
"use client";
import { ArrowRight } from "lucide-react";
import { useState } from "react";
import {
MarketingButton,
type MarketingButtonProps,
} from "../components/marketing-button";
const LOADING_DURATION_MS = 2400;
function LoadingMarketingButton(
props: Omit<MarketingButtonProps, "loading" | "onClick">
) {
const [loading, setLoading] = useState(false);
const handleClick = () => {
setLoading(true);
setTimeout(() => setLoading(false), LOADING_DURATION_MS);
};
return <MarketingButton {...props} loading={loading} onClick={handleClick} />;
}
export default function MarketingButtonLoading() {
return (
<div className="flex w-full min-w-0 flex-wrap items-center justify-center gap-6 p-8">
<LoadingMarketingButton>
Start for free
<ArrowRight />
</LoadingMarketingButton>
<LoadingMarketingButton variant="light">
Book a call
</LoadingMarketingButton>
</div>
);
}
As a link
Render an anchor or your router’s link and set nativeButton={false}.
import { MarketingButton } from "../components/marketing-button";
export default function MarketingButtonLink() {
return (
<div className="flex w-full min-w-0 flex-wrap items-center justify-center gap-6 p-8">
<MarketingButton
nativeButton={false}
render={<a href="https://usenotra.com" rel="noopener" />}
>
Visit Notra
</MarketingButton>
</div>
);
}