feat: Button elevation hover/active effect with snap shadow

Variants now use brutal shadow tokens. On hover the button translates
up-left (−0.5px), on active down-right (+0.5px). Only transform animates
(130ms ease-out); shadow snaps instantly so the eye reads button movement
not shadow resize. Primary keeps rgba alpha shadow; secondary/outline use
solid brutal tokens.
This commit is contained in:
Ilia Mashkov
2026-05-16 19:04:00 +03:00
parent 8db4f81f70
commit a77cd43749
+11 -6
View File
@@ -22,10 +22,14 @@ interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
} }
const VARIANTS: Record<ButtonVariant, string> = { const VARIANTS: Record<ButtonVariant, string> = {
primary: 'bg-blue text-cream outline-[3px] outline-cream', primary:
secondary: 'bg-blue text-cream outline-[3px] outline-cream', 'brutal-border bg-blue text-cream shadow-[5px_5px_0_rgba(4,28,243,0.35)] hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-[7px_7px_0_rgba(4,28,243,0.35)] active:translate-x-0.5 active:translate-y-0.5 active:shadow-[1px_1px_0_rgba(4,28,243,0.35)]',
outline: 'bg-transparent text-blue border-blue', secondary:
ghost: 'bg-cream text-blue border-blue', 'brutal-border bg-blue text-cream shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-md active:translate-x-0.5 active:translate-y-0.5 active:shadow-brutal-xs',
outline:
'brutal-border bg-transparent text-blue shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-md active:translate-x-0.5 active:translate-y-0.5 active:shadow-brutal-xs',
ghost:
'border-[3px] border-solid border-blue/35 bg-cream text-blue hover:border-blue hover:bg-blue/10 active:bg-blue active:text-cream',
}; };
const SIZES: Record<ButtonSize, string> = { const SIZES: Record<ButtonSize, string> = {
@@ -34,8 +38,9 @@ const SIZES: Record<ButtonSize, string> = {
lg: 'px-8 py-4 text-lg', lg: 'px-8 py-4 text-lg',
}; };
const BASE = /* box-shadow excluded from transition intentionally — snaps instantly so the
'brutal-border brutal-shadow transition-all duration-200 hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-[6px_6px_0_var(--blue)] active:translate-x-[4px] active:translate-y-[4px] active:shadow-[4px_4px_0_var(--blue)] uppercase tracking-wider'; * eye follows the 130ms button movement, not the shadow change. */
const BASE = 'btn-transition uppercase tracking-wider';
/** /**
* Brutalist button with variants and sizes. * Brutalist button with variants and sizes.