npm.io
0.15.0 • Published 11h ago

@schumann-dev/ui

Licence
MIT
Version
0.15.0
Deps
3
Size
165 kB
Vulns
0
Weekly
0

Schumann.ui

Biblioteca de componentes React dark-first, orientada a tokens, extraída do design system do FinTrackr e desacoplada de qualquer regra de negócio.

  • Tipada (TypeScript) · acessível (Radix + ARIA) · temável (CSS custom properties) · tree-shakeable (ESM + sideEffects só em CSS).
  • Documentada e desenvolvida no Storybook.

Instalação

npm install @schumann-dev/ui
# peers (provavelmente já instalados no seu app):
npm install react react-dom

Uso

Importe os componentes e o stylesheet uma única vez (na raiz do app):

import '@schumann-dev/ui/styles.css';
import { Button, Card, Input } from '@schumann-dev/ui';

export function Exemplo() {
  return (
    <Card>
      <Card.Header>
        <Card.Title>Resumo</Card.Title>
      </Card.Header>
      <Card.Content>
        <Input placeholder="Buscar..." />
      </Card.Content>
      <Card.Footer>
        <Button variant="primary">Salvar</Button>
      </Card.Footer>
    </Card>
  );
}

Temas

O tema dark é o padrão. Para trocar, defina data-theme no <html>:

<html data-theme="light"></html>

Customização pontual = redefinir a CSS var num escopo:

.minha-area { --interactive-primary: #0ea5e9; }

Os componentes aceitam className e style, permitindo sobrescrita controlada sem alterar a biblioteca.

Tipografia

A fonte padrão é Roboto. A lib não embute fontes (responsabilidade do app) — carregue a família com os pesos que o DS usa (400/500/600/700/800):

<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700;800&display=swap" rel="stylesheet" />

A família é o token --font-sans. Para trocar por outra fonte, sobrescreva a variável:

:root { --font-sans: 'Inter', system-ui, sans-serif; }

(O mono --font-mono — JetBrains Mono, usado em valores/códigos — segue o mesmo princípio.)

Ícones (~2.000)

O set base do DS vem embutido. Para o set Lucide completo (~2.000 ícones, ISC), importe o entry opt-in uma vez no bootstrap do app:

import '@schumann-dev/ui/icons'; // registra tudo (~100 kB gzip — só quem importa paga)

<Icon name="rocket" />                          // qualquer nome kebab-case do Lucide
<IconPicker icons={getIconNames()} ... />       // picker com todos + busca
  • Os nomes originais do DS (menu, chevDown, tag…) têm precedência e não são sobrescritos.
  • Ícones próprios: registerIcons({ nome: '<path .../>' }). Nomes legados: registerIconAliases({ FiHome: 'home' }).
  • Precisa de mais? O mesmo mecanismo aceita qualquer set do Iconify (ex.: @iconify-json/tabler, ~5.900 ícones).

Desenvolvimento

npm run storybook     # ambiente de dev/documentação
npm run test          # Vitest + Testing Library + jest-axe
npm run build         # gera dist/ (ESM + styles.css + .d.ts)
npm run lint

Componentes (v0.2.0)

Atoms: Button, IconButton, Input, Text, Heading, Label, Badge, Spinner, Icon/IconBox (registro extensível via registerIcons/registerIconAliases), Avatar, Switch, Skeleton, ProgressBar. Molecules: FormField, Combobox, MultiSelect, SegmentedControl (pill/card/tab), SwitchCard, MoneyInput, DateTimeInput, MonthPicker, ColorPicker, IconPicker (busca embutida), StatCard, EmptyState, Tooltip. Organisms: Card, Modal, ConfirmModal, Menu, DataTable. Templates: PageContainer, AppShell, PageHeader.

Mapeamento frontend-v3 → Schumann.ui
App (frontend-v3) Lib Observação
Field FormField fiação ARIA automática via contexto
TextInput Input addons via leftAddon/rightAddon
MoneyInput / DateTimeInput idem moeda configurável; máscara pt-BR
Select / IconSelect Combobox um só componente; visual da opção via leading (app monta o AccountLogo)
MultiSelect MultiSelect igual
StatusSegment SegmentedControl (pill) opções vêm do app
BucketPick SegmentedControl (card) opções 50/30/20 ficam no app
Toggle / ToggleCard Switch / SwitchCard role="switch" acessível
ColorSwatches/ColorSelect/HSVColorPicker ColorPicker visual V2 (handoff ColorPickerV2.dc.html): swatches + botão de cor personalizada + painel inline hex/rgb; paleta via prop swatches
IconPick IconPicker ícones via prop
Icon/IconBox idem aliases legados: registerIconAliases() no bootstrap do app
Avatar Avatar app resolve a URL antes (resolveImageUrl)
RowMenu Menu ícone por nome ou ReactNode
DataGrid DataTable mesma API; strings via props/labels
Modal/ModalHeader Modal + Modal.Content Radix (focus-trap/ESC)
ConfirmModal ConfirmModal mapa de erros do backend vai em formatError
Shell (layout) AppShell nav/slots via props; router/logout ficam no app
stepper de mês do topbar (Shell) MonthPicker mesma pill ‹ mês ›, agora com painel 4×3
cabeçalho inline (eyebrow + h1) das páginas PageHeader 12/12 páginas usavam o mesmo bloco
barra de progresso inline (orçamento/fatura) ProgressBar limiar de perigo embutido
tiles de resumo do dashboard StatCard acento por cor via prop
lista/card vazio ("Nenhum…") EmptyState o DataTable já cobre o caso de tabela
barra de abas inline (Settings/Categorias…) SegmentedControl variante tab sem componente novo
hint title= nativo Tooltip acessível (Radix), hover + teclado
AccountLogo, FamilyCard, TransferModal — (ficam no app) domínio; compõem sobre os genéricos

Atualização

Versionamento por SemVer com Changesets. Veja o CHANGELOG. Para gravar uma mudança:

npx changeset          # descreve a mudança + tipo (patch/minor/major)
  • patch — correção compatível.
  • minor — novo componente/variante/prop.
  • major — quebra de API ou remoção de prop (props depreciadas emitem console.warn por 1 minor antes da remoção).