A production button: gradient fill + inner-light rim
Most of my flashy buttons are one-offs. This is the one I reach for everywhere. I ported it from the B3OS design system. It looks like a real object without a wall of CSS, because the depth lives on two pseudo-element layers.
Two layers do the work
The element carries a color-matched drop shadow. A before: layer paints the
gradient fill, an after: layer paints the inner-light rim, and the label sits
on a relative z-10 wrapper above both:
default: [
"text-white shadow-[0_1px_2px_rgba(0,0,0,.35),0_6px_18px_-6px_hsl(var(--primary)/.6)]",
"before:absolute before:inset-0 before:rounded-[inherit] before:bg-gradient-to-b " +
"before:from-[hsl(217_92%_64%)] before:to-[hsl(217_90%_50%)]",
"after:absolute after:inset-0 after:rounded-[inherit] after:pointer-events-none " +
"after:shadow-[inset_0_1px_0_rgba(255,255,255,.3),inset_0_0_0_1px_rgba(255,255,255,.08)]",
"hover:before:brightness-110 active:translate-y-px active:before:brightness-90",
],Why pseudo-elements instead of just a gradient background? Because you can
animate the fill on its own. hover:before:brightness-110 brightens the
gradient and leaves the text alone, while active:translate-y-px presses the
whole key. rounded-[inherit] keeps the layers matching whatever radius the
size sets.
Variants are cheap
Every variant is the same recipe with two gradient stops and a shadow tint
swapped out: black, white, destructive, success, plus the flat
outline, ghost, and link. It's a cva config, so
variant and size come through as typed props.
asChild
asChild (via Radix Slot) lets a <Link> wear the button styling without
nesting an <a> inside a <button>:
<Button asChild>
<Link to="/components">Browse components</Link>
</Button>The trick is that the content-wrapper span gets cloned onto the child, so the
z-10 layering still works when the rendered element is an anchor.
It's the default Button across this site. See every variant on the
Button page.
Ask your agent to implement this
Read the full writeup at https://seangeng.com/writing/a-production-button.md and implement it in my project.
It covers: A production button: gradient fill + inner-light rim — The button I actually ship: a class-variance-authority component whose depth comes from two pseudo-element layers (gradient fill, inner-light rim) and a color-matched shadow. Eight variants, four sizes, asChild.
Requirements:
- Follow the technique/approach exactly as described in the writeup.
- Adapt names, colors, and styling to my project's existing conventions.
- If it's a component, make it reusable with sensible props and TypeScript types.
- Keep it accessible: semantic HTML, keyboard support, and respect prefers-reduced-motion.
- When done, tell me which files you created or changed and how to use it.Paste into Claude Code, Codex, Cursor, or any agent. view raw .md