Tasteful Button
How a flat shadcn button becomes a Clerk-like control, one Tailwind class at a time.

Faisal Husain
Published
This is the same control as the "View all writing" link on the home page. The jump is not a new component. It is a flat shadcn button with light, weight, and press added in Tailwind.
Brighten on fine pointers. Skip hover on touch so a tap does not leave it stuck lit.
Click through the lab, then we will add each class in order.
Step 1 : Shadcn default
This is the default shadcn button. Flat fill. Fine. It just does not feel like something you can press.
<button className="inline-flex h-10 items-center justify-center rounded-md bg-zinc-900 px-4 text-sm font-medium text-white">
View all writing
</button>Step 2 : Shape the control
Bring it closer to a real toolbar control. Shorter. Rounder. A border. Room for an icon.
<button className="inline-flex h-9 items-center justify-center gap-2 rounded-lg border border-zinc-800 bg-zinc-900 px-4 text-sm font-medium text-white">
View all writing
<ArrowUpRight className="size-3.5" />
</button>Still a painted rectangle. The shape is right. The surface is not.
Step 3 : Paint a surface
Do not fill it with one color. Paint a vertical gradient so the top catches more light than the bottom. That is the Clerk move.
<button className="inline-flex h-9 items-center justify-center gap-2 rounded-lg border border-zinc-800 bg-gradient-to-b from-zinc-700 via-zinc-800 to-zinc-950 px-4 text-sm font-medium text-white dark:border-zinc-300 dark:from-white dark:via-zinc-100 dark:to-zinc-300 dark:text-zinc-950">
View all writing
<ArrowUpRight className="size-3.5" />
</button>Stock zinc. Dark page gets a light button. Light page gets a dark one. Paste it into any Tailwind project.
Step 4 : Light from above
Two shadows. One under the button so it lifts. One inset along the top edge so it looks lit.
<button className="inline-flex h-9 items-center justify-center gap-2 rounded-lg border border-zinc-800 bg-gradient-to-b from-zinc-700 via-zinc-800 to-zinc-950 px-4 text-sm font-medium text-white shadow-[0_1px_1px_rgb(0_0_0/0.08),0_2px_6px_rgb(0_0_0/0.16),inset_0_1px_0_rgb(255_255_255/0.18)] dark:border-zinc-300 dark:from-white dark:via-zinc-100 dark:to-zinc-300 dark:text-zinc-950">
View all writing
<ArrowUpRight className="size-3.5" />
</button>That inset 1px highlight is the whole taste. Without it the gradient looks printed. With it the button looks machined.
Step 5 : Press like a key
A button that does not move on press feels broken. Drop it one pixel, scale it a hair, and flatten the highlight.
<button className="inline-flex h-9 items-center justify-center gap-2 rounded-lg border border-zinc-800 bg-gradient-to-b from-zinc-700 via-zinc-800 to-zinc-950 px-4 text-sm font-medium text-white shadow-[0_1px_1px_rgb(0_0_0/0.08),0_2px_6px_rgb(0_0_0/0.16),inset_0_1px_0_rgb(255_255_255/0.18)] transition-[filter,scale,translate,box-shadow] duration-150 ease-out active:translate-y-px active:scale-[0.98] active:shadow-[0_1px_2px_rgb(0_0_0/0.16),inset_0_1px_0_rgb(255_255_255/0.1)] motion-reduce:active:translate-y-0 motion-reduce:active:scale-100 dark:border-zinc-300 dark:from-white dark:via-zinc-100 dark:to-zinc-300 dark:text-zinc-950">
View all writing
<ArrowUpRight className="size-3.5" />
</button>Keep the press under 160ms. ease-out so it answers immediately.
Step 6 : Hover only when it is honest
On a mouse, brighten a little. On a phone, do not. Touch fires :hover and leaves the button looking stuck.
<button className="inline-flex h-9 items-center justify-center gap-2 rounded-lg border border-zinc-800 bg-gradient-to-b from-zinc-700 via-zinc-800 to-zinc-950 px-4 text-sm font-medium text-white shadow-[0_1px_1px_rgb(0_0_0/0.08),0_2px_6px_rgb(0_0_0/0.16),inset_0_1px_0_rgb(255_255_255/0.18)] transition-[filter,scale,translate,box-shadow] duration-150 ease-out active:translate-y-px active:scale-[0.98] active:shadow-[0_1px_2px_rgb(0_0_0/0.16),inset_0_1px_0_rgb(255_255_255/0.1)] motion-reduce:active:translate-y-0 motion-reduce:active:scale-100 [@media(hover:hover)_and_(pointer:fine)]:hover:brightness-105 dark:border-zinc-300 dark:from-white dark:via-zinc-100 dark:to-zinc-300 dark:text-zinc-950">
View all writing
<ArrowUpRight className="size-3.5" />
</button>That last class is the full button. Copy it as is.
Hence completed. Thank you for reading.
Let's work together
Have a product problem worth solving?
I help teams build fast, dependable products with thoughtful interfaces and strong engineering foundations.