// components.jsx — UI components in the Casa Lar brand. // Button, Input, Card, Badge, Stat, Quote, Avatar, ListItem. // ──────────────────────────────────────────────────────────────── // Button — primary (ink), accent (sol), secondary (outline), ghost // soft (cream), danger-soft. Plus sizes sm/md/lg/xl and icon-only. // ──────────────────────────────────────────────────────────────── function Button({ variant = 'primary', size = 'md', children, full, icon, iconRight, square }) { const sizes = { sm: { fs: 13, pad: '8px 14px', iconPad: 8 }, md: { fs: 14, pad: '11px 18px', iconPad: 11 }, lg: { fs: 16, pad: '14px 24px', iconPad: 14 }, xl: { fs: 18, pad: '18px 30px', iconPad: 18 }, }; const s = sizes[size]; const styles = { primary: { bg: 'var(--ink)', color: 'var(--paper)', border: 'none' }, accent: { bg: 'var(--sol)', color: 'var(--ink)', border: 'none' }, secondary: { bg: 'var(--paper)', color: 'var(--ink)', border: '1.5px solid var(--ink)' }, ghost: { bg: 'transparent', color: 'var(--ink)', border: '1.5px solid transparent' }, soft: { bg: 'var(--paper-2)', color: 'var(--ink)', border: '1px solid var(--line)' }, folha: { bg: 'var(--folha)', color: 'var(--paper)', border: 'none' }, ceramica: { bg: 'var(--ceramica)',color: 'var(--paper)', border: 'none' }, }; const v = styles[variant]; return ( ); } // ──────────────────────────────────────────────────────────────── // Input — text input with label, helper, optional icon // ──────────────────────────────────────────────────────────────── function Input({ label, helper, value, placeholder, type = 'text', state = 'default', icon, suffix, multiline }) { const borderColor = state === 'error' ? 'var(--ceramica)' : state === 'focus' ? 'var(--ink)' : 'var(--line-strong)'; return (
{label && ( )}
{icon && {icon}} {value || placeholder} {suffix && {suffix}}
{helper && (
{helper}
)}
); } // ──────────────────────────────────────────────────────────────── // Badge — tag/chip // ──────────────────────────────────────────────────────────────── function Badge({ tone = 'neutral', children, dot, size = 'md' }) { const map = { neutral: { bg: 'var(--paper-2)', fg: 'var(--ink)', bd: 'var(--line)' }, sol: { bg: 'color-mix(in oklab, var(--sol) 30%, var(--paper))', fg: 'var(--ink)', bd: 'transparent' }, ceramica: { bg: 'color-mix(in oklab, var(--ceramica) 18%, var(--paper))', fg: 'var(--ceramica)', bd: 'transparent' }, folha: { bg: 'color-mix(in oklab, var(--folha) 18%, var(--paper))', fg: 'var(--folha)', bd: 'transparent' }, ceu: { bg: 'color-mix(in oklab, var(--ceu) 18%, var(--paper))', fg: 'var(--ceu)', bd: 'transparent' }, rosa: { bg: 'color-mix(in oklab, var(--rosa) 30%, var(--paper))', fg: 'var(--ink)', bd: 'transparent' }, ink: { bg: 'var(--ink)', fg: 'var(--paper)', bd: 'transparent' }, }; const v = map[tone]; const sizes = { sm: { fs: 10.5, pad: '3px 8px', dot: 5 }, md: { fs: 11.5, pad: '4px 9px', dot: 6 }, lg: { fs: 13, pad: '6px 12px', dot: 7 }, }; const s = sizes[size]; return ( {dot && ( )} {children} ); } // ──────────────────────────────────────────────────────────────── // Card — content surface (default, accent-bordered, elevated, dark) // ──────────────────────────────────────────────────────────────── function Card({ children, accent, variant = 'default', padding = 22, full }) { const variants = { default: { bg: 'var(--paper)', color: 'var(--ink)', border: '1px solid var(--line)', shadow: 'none' }, soft: { bg: 'var(--paper-2)', color: 'var(--ink)', border: '1px solid var(--line)', shadow: 'none' }, elevated: { bg: 'var(--paper)', color: 'var(--ink)', border: '1px solid var(--line)', shadow: '0 1px 2px rgba(0,0,0,.04), 0 8px 24px rgba(0,0,0,.06)' }, dark: { bg: 'var(--ink)', color: 'var(--paper)', border: 'none', shadow: 'none' }, }; const v = variants[variant]; return (
{children}
); } // ──────────────────────────────────────────────────────────────── // Stat — big number with label // ──────────────────────────────────────────────────────────────── function Stat({ value, label, suffix, accent }) { return (
{value}{suffix && {suffix}}
{label}
); } // ──────────────────────────────────────────────────────────────── // Quote — editorial pull-quote // ──────────────────────────────────────────────────────────────── function Quote({ children, author, role }) { return (
{children}
{author && (
{author} {role && · {role}}
)}
); } // ──────────────────────────────────────────────────────────────── // Avatar — initials circle // ──────────────────────────────────────────────────────────────── function Avatar({ initials, color, size = 44 }) { const colors = ['var(--ceu)', 'var(--ceramica)', 'var(--sol)', 'var(--rosa)', 'var(--folha)']; const c = color || colors[(initials.charCodeAt(0) + initials.charCodeAt(1 % initials.length)) % colors.length]; return (
{initials}
); } // ──────────────────────────────────────────────────────────────── // ListItem — row with leading icon/dot, primary, secondary, trailing // ──────────────────────────────────────────────────────────────── function ListItem({ leading, primary, secondary, trailing, divider }) { return (
{leading &&
{leading}
}
{primary}
{secondary &&
{secondary}
}
{trailing &&
{trailing}
}
); } // ──────────────────────────────────────────────────────────────── // Icons — small inline SVGs (sized via currentColor) // ──────────────────────────────────────────────────────────────── const Icons = { Heart: , Arrow: , Mail: , Phone: , Pin: , Check: , User: , Pix: , Shirt: , Gift: , Play: , Hand: , }; // ──────────────────────────────────────────────────────────────── // Showcase artboards // ──────────────────────────────────────────────────────────────── function ComponentsShowcaseA() { return (
Componentes · Botões & Campos
{/* Buttons */}
Botões
{/* Inputs */}
Campos
); } function ComponentsShowcaseB() { return (
Componentes · Etiquetas, Cards, Listas
Etiquetas
Em andamento Acolhido Voluntária Padrinho Urgente Mantenedor Aguarda
SM MD LG
Cards
Apadrinhamento
Sustente um lugar
R$ 120/mês cobre alimentação e escola.
Transparência · 2025
Lista
} primary="Maria das Graças" secondary="Coordenadora pedagógica · desde 2014" trailing="EQUIPE" divider /> } primary="Luiz Renato" secondary="Educador · turno tarde" trailing="EQUIPE" divider /> } primary="Antonia Berenice" secondary="Psicóloga · quartas e sextas" trailing="EQUIPE" />
); } function ComponentsShowcaseC() { return (
Componentes · Estatísticas & Citação
Estatísticas
Quando entrei, eu não sabia que aniversário tinha bolo. Hoje sei que a casa é minha.
); } Object.assign(window, { Button, Input, Badge, Card, Stat, Quote, Avatar, ListItem, Icons, ComponentsShowcaseA, ComponentsShowcaseB, ComponentsShowcaseC, });