/* ============================================================ Motion + Design Tokens export ============================================================ */ function MotionSection() { const [hover, setHover] = useState(false); const [pressed, setPressed] = useState(false); const [pageKey, setPageKey] = useState(0); const [toastOpen, setToastOpen] = useState(false); const [sheetOpen, setSheetOpen] = useState(false); const [tab, setTab] = useState("a"); return ( <>
Tokens de duração e easing
{[ { token: "--dur-fast", val: "120ms", use: "Hover, press, micro" }, { token: "--dur-base", val: "220ms", use: "Mudança de estado padrão" }, { token: "--dur-slow", val: "420ms", use: "Entrada de tela, sheet" }, { token: "--ease-out", val: "cubic-bezier(.2,.8,.2,1)", use: "Padrão · saída suave" }, { token: "--ease-spring", val: "cubic-bezier(.34,1.3,.64,1)", use: "Apenas para entrada de toast/sheet" }, ].map(t => (
{t.token}
{t.val}
{t.use}
))}
Demonstrações
{/* Page transition */}
page-transition
Tela {pageKey + 1}
Entrada com fade + Y translate 8px
{/* Card hover */}
card-hover
setHover(true)} onMouseLeave={()=>setHover(false)} style={{ padding: 18, background: "var(--sand-100)", borderRadius: 12, transition: "transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out)", transform: hover ? "translateY(-3px)" : "translateY(0)", boxShadow: hover ? "var(--shadow-md)" : "var(--shadow-flat)", cursor:"pointer" }}>
Passe o mouse aqui
−3px Y · md shadow · 220ms
{/* Button press */}
button-press
scale(.96) · 120ms · ease-out
{/* Skeleton shimmer */}
skeleton-shimmer
1.4s linear · loop infinito
{/* Toast */}
toast-enter
{toastOpen && (
Produto adicionado
)}
fade + slide-up 12px · 420ms
{/* Bottom sheet */}
bottom-sheet-open
{sheetOpen && (
Conteúdo da sheet
)}
backdrop fade + slide-up · 350ms
{/* Tab transition */}
tab-indicator
{[["a","Produtos"],["b","Sobre"],["c","Contato"]].map(([id, l]) => ( ))}
indicador desliza · 220ms ease-out
); } /* ---------- TOKENS export block ---------- */ function TokensSection() { const [copied, setCopied] = useState(false); const tokenCode = `:root { /* Colors — Plum (primário dominante) */ --plum-50: #F7F2F7; --plum-100: #EDE2EE; --plum-200: #D6C2DA; --plum-300: #B597BC; --plum-400: #8B6892; --plum-500: #65466D; --plum-600: #4A2F52; --plum-700: #36213D; --plum-800: #2A1B2E; --plum-900: #1A0F1D; /* Colors — Ember (brand action) */ --ember-50: #FEF4ED; --ember-100: #FDE5D2; --ember-200: #FBC79F; --ember-300: #F8A267; --ember-400: #F08544; --ember-500: #E8712A; --ember-600: #C95A1B; --ember-700: #A14716; --ember-800: #7B3613; --ember-900: #5C2810; /* Colors — Sand (fundos warm) */ --sand-50: #FFFCF6; --sand-100: #FAF6EE; --sand-200: #F2EBDD; --sand-300: #E6DBC3; --sand-400: #D2C19E; /* Colors — Neutral (texto, bordas) */ --neutral-50: #FAF8F5; --neutral-100: #F1EEE9; --neutral-200: #E1DCD3; --neutral-300: #C9C2B6; --neutral-400: #9B9389; --neutral-500: #6D6760; --neutral-600: #4D4944; --neutral-700: #36332F; --neutral-800: #211F1D; --neutral-900: #100F0E; /* Semantic */ --success-500: #2D7A4F; --warning-500: #C88A1F; --error-500: #B83A3A; --info-500: #2C5F87; /* Surface aliases */ --bg: var(--sand-100); --bg-elevated: #FFFFFF; --bg-inverse: var(--plum-800); --fg-primary: var(--neutral-900); --fg-secondary: var(--neutral-600); --fg-muted: var(--neutral-400); --hairline: rgba(33, 31, 29, .08); --accent: var(--ember-500); --accent-press: var(--ember-600); /* Typography */ --font-display: 'Bricolage Grotesque', system-ui, sans-serif; --font-body: 'Inter Tight', system-ui, sans-serif; --font-mono: 'JetBrains Mono', ui-monospace, monospace; --fs-display-xl: 56px; --fs-display-lg: 44px; --fs-h1: 32px; --fs-h2: 26px; --fs-h3: 22px; --fs-h4: 18px; --fs-body-lg: 18px; --fs-body: 16px; --fs-body-sm: 14px; --fs-caption: 12px; --fs-label: 11px; --lh-display: 1.05; --lh-heading: 1.2; --lh-body: 1.55; --tracking-display: -0.025em; --tracking-eyebrow: 0.12em; /* Spacing — base 4px */ --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 20px; --space-6: 24px; --space-7: 32px; --space-8: 40px; --space-9: 48px; --space-10: 64px; --space-11: 80px; --space-12: 96px; /* Radius */ --radius-none: 0; --radius-sm: 6px; --radius-md: 10px; --radius-lg: 16px; --radius-xl: 24px; --radius-full: 9999px; /* Shadows */ --shadow-flat: none; --shadow-low: 0 1px 2px rgba(33, 31, 29, .06); --shadow-md: 0 4px 12px -2px rgba(33,31,29,.10), 0 2px 4px -2px rgba(33,31,29,.06); --shadow-high: 0 12px 32px -8px rgba(33,31,29,.16), 0 4px 8px -2px rgba(33,31,29,.06); --shadow-overlay: 0 24px 64px -16px rgba(26,15,29,.28), 0 8px 16px -4px rgba(33,31,29,.12); --shadow-focus: 0 0 0 3px rgba(232, 113, 42, .28); /* Motion */ --ease-out: cubic-bezier(.2,.8,.2,1); --ease-in: cubic-bezier(.4,0,.6,.4); --ease-spring: cubic-bezier(.34,1.3,.64,1); --dur-fast: 120ms; --dur-base: 220ms; --dur-slow: 420ms; /* Z-index */ --z-base: 0; --z-sticky: 10; --z-overlay: 100; --z-modal: 200; --z-toast: 300; /* Layout */ --container: 1200px; --gutter: 24px; --gutter-mobile: 16px; }`; const copy = () => { navigator.clipboard.writeText(tokenCode); setCopied(true); setTimeout(()=>setCopied(false), 1600); }; return ( <>
CSS Variables completas
{tokenCode}
Imports necessários no HTML
{` `}
); } Object.assign(window, { MotionSection, TokensSection });