Offset Shadow Button
One solid offset fill, three ways to move it on hover.
light onlyOne solid offset fill, three ways to move it on hover.
light onlyexperiments/offset-shadow-button/index.tsx
const VARIANTS: Record<string, string> = {
Slide: [
'shadow-[5px_5px_0_0_var(--osb-fill)] duration-200',
'hover:translate-x-[5px] hover:translate-y-[5px] hover:shadow-[0_0_0_0_var(--osb-fill)]',
].join(' '),
Lift: [
'shadow-[5px_5px_0_0_var(--osb-fill)] duration-200',
'hover:-translate-x-[3px] hover:-translate-y-[3px] hover:shadow-[8px_8px_0_0_var(--osb-fill)]',
].join(' '),
Riser: [
'shadow-none duration-300',
'hover:shadow-[0_5px_0_0_var(--osb-fill)]',
'active:shadow-none',
].join(' '),
}
export default function OffsetShadowButton({ variant = 'Slide' }: { variant?: string }) {
return (
<button
type="button"
className={[
'[--osb-fill:#1d1d20] [--osb-face:#f5f5f6]',
'rounded-md border border-[var(--osb-fill)] bg-[var(--osb-face)] px-5 py-2.5',
'text-sm font-semibold text-[var(--osb-fill)]',
'transition-[box-shadow,transform] ease-[cubic-bezier(0.2,0,0,1)]',
VARIANTS[variant] ?? VARIANTS.Slide,
'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--osb-fill)]',
].join(' ')}
>
Ship it
</button>
)
}