A translucent Button for use over art: a blurred, faint background-tinted fill with a border and inner glow that follow currentColor. Needs a backdrop behind it for the blur to read.
import { cn } from "cn"
import { Button } from "@/components/ui/button"
/**
* A translucent button for use over artwork or photos: a 15% wash of the
* background color (25% on hover) with a backdrop blur, and a border and
* inner glow drawn in the text color. The blur only shows when something
* sits behind the button.
*
* It is the default `Button` with its fill replaced, so `size`, the focus
* ring and the disabled style stay the same. Its text uses the `foreground`
* color, and the border and glow follow any text color you set.
*/
function FrostedButton({
className,
...props
}: Omit<
React.ComponentProps<typeof Button>,
"variant" | "className" | "size"
> & {
/**
* The stock `Button` size: `default` 36px tall, `xs` 24px, `sm` 32px and
* `lg` 40px, or the square `icon` 36px, `icon-xs` 24px, `icon-sm` 32px and
* `icon-lg` 40px.
*/
size?: React.ComponentProps<typeof Button>["size"]
/**
* Extra classes, as a string only: the stock `Button` does not accept a
* `className` function.
*/
className?: string
}) {
return (
<Button
data-slot="frosted-button"
className={cn(
"relative border-current/25 bg-background/15 text-foreground shadow-md backdrop-blur-md hover:bg-background/25",
"after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] after:opacity-20 after:shadow-[inset_0_0_2px_1px_currentColor]",
className
)}
{...props}
/>
)
}
export { FrostedButton }
pnpm dlx shadcn add @01orbital/frosted-buttonnpx shadcn add @01orbital/frosted-buttonyarn shadcn add @01orbital/frosted-buttonbunx --bun shadcn add @01orbital/frosted-buttonFree under the MIT license. Add the @01orbital registry to components.json once (install guide), then run the command.
It lands at components/button/frosted-button.tsx, as source you own and edit.
The example also uses conic-glow. Install it too:
pnpm dlx shadcn add @01orbital/conic-glownpx shadcn add @01orbital/conic-glowyarn shadcn add @01orbital/conic-glowbunx --bun shadcn add @01orbital/conic-glow"use client"
import { useState } from "react"
import { FrostedButton } from "@/components/button/frosted-button"
import { ConicGlow } from "@/components/glow/conic-glow"
// Every word on the page. Change copy here, not in the markup.
const COPY = {
cta: "Turn the light",
} as const
// Each press aims a different stretch of the color wheel at the button.
const ANGLES = [224, 314, 44, 134] as const
// Frost needs color behind it to show.
export default function FrostedButtonDemo() {
const [turn, setTurn] = useState(0)
return (
<div className="dark grid w-full place-items-center bg-background p-6 text-foreground">
<div className="relative isolate grid aspect-4/3 w-full max-w-md place-items-center overflow-hidden rounded-3xl bg-background">
{/* Scaled from its corner so the glow fills a card this small. */}
<ConicGlow
rotate={ANGLES[turn]}
className="-z-10 origin-top-right scale-300"
/>
<FrostedButton
size="lg"
type="button"
onClick={() => setTurn((turn + 1) % ANGLES.length)}
>
{COPY.cta}
</FrostedButton>
</div>
</div>
)
}Prop
Type
It also accepts the props of the Base UI part it wraps, and the HTML attributes of the element it renders.
npm: cn. The CLI installs them for you.
Registry pieces it installs with it:
buttonCloud Dancer Switch
A Base UI switch with a cream pill groove shaded teal that warms to rose when checked, and a dark void orb for a thumb. Default and small sizes, client component.
Menu Button
A hamburger icon Button that morphs into a close cross. The animation is driven entirely by aria-expanded, so the visual state and the screen-reader state stay in sync.