@precisa-saude/ui
v3.1.0
Published
Shared React components and hooks for Precisa Saúde sites and apps.
Maintainers
Readme
@precisa-saude/ui
Shared React components, hooks, and utilities for Precisa Saúde sites and apps.
Built on Base UI (shadcn base-nova style) for headless primitives. Uses the tokens from @precisa-saude/themes for styling; consumers should import that package's CSS first.
Status
In early development. Current surface:
utils/cn()— Tailwind class merger (clsx + tailwind-merge)hooks/useMediaQuery— SSR-safe matchMedia subscriptionhooks/useWideGrid/useDesktop— viewport breakpoints aligned with@precisa-saude/themes/grid.csshooks/useGridCol— inline-style builder for the 14/16-col gridhooks/useReducedMotion—prefers-reduced-motionsubscriptiondecorative/CornerSquares— two-square corner accents on the responsive griddecorative/DuotoneFilter— SVG filter for duotone image treatments (dark shadows → light highlights, configurable)decorative/GridOverlay— dev-mode fixed overlay that visualizes the 14/16-col grid (pressgto cycle)decorative/MosaicBg— canvas-based animated mosaic background with OKLCh color interpolationprimitives/Button— Base UI button with CVA variants (default/outline/secondary/ghost/destructive/link × xs/sm/default/lg/icon sizes)primitives/Badge— pill label with CVA variants (default/secondary/destructive/outline + success/warning/elevated/critical/info semantic variants)primitives/Tooltip— Base UI tooltip (Provider/Root/Trigger/Content sub-components + convenienceTooltipwrapper)primitives/Select— Base UI select with full sub-component set (Trigger/Content/Item/Label/Separator/Group/Value/ScrollUp/ScrollDown)primitives/Dialog— Base UI dialog with built-in backdrop + close button (Root/Trigger/Portal/Backdrop/Content/Header/Footer/Title/Description/Close)primitives/Tabs— Base UI tabs (Root/List/Trigger/Panel/Indicator)primitives/Accordion— Base UI accordion with chevron that rotates on open (Root/Item/Header/Trigger/Panel)primitives/Popover— Base UI popover (Root/Trigger/Portal/Content/Close)primitives/Switch— Base UI toggle switchprimitives/Checkbox— Base UI checkbox with determinate + indeterminate statesprimitives/Field— Base UI form field (Root/Label/Control/Description/Error/Validity)layout/PageContainer— top-level 14/16-col grid wrapperlayout/SectionContainer— section wrapper with configurable vertical spacingmarketing/Marquee— seamless horizontally-scrolling container with edge fade + reduced-motion supportmarketing/Callout— info/success/warning/critical/note alert block (maps to--status-*tokens)marketing/StatsGrid— responsive grid of label/value stat cardsmarketing/FeatureGrid— responsive grid of icon/title/description feature cardscards/ActionCard— icon + title + subtitle + chevron clickable card (renders as<a>or<button>)cards/NewsCard— news/blog card withcompactandherolayouts (tag badge, title, date, excerpt, tag pills, optional hero image)navigation/Breadcrumbs— simple segmented breadcrumbs with customizable separatornavigation/NavigationalBreadcrumbs— breadcrumbs where each segment opens a searchable Popover of sibling options (with status dots, icons, check indicator)navigation/SlidingTabs— pill-shaped tabs with an animated indicator (built on Base UI Tabs)navigation/Pagination— numbered pagination with prev/next + optional page-size selectorprimitives/Menu— Base UI dropdown menu with Item / CheckboxItem / RadioItem / Group / Label / Separator / Shortcut / SubmenuRoot + SubmenuTriggerprimitives/Toast— Base UI toast system (Provider + Viewport + Root + Title + Description + Action + Close). UseuseToastManager()from@base-ui/react/toastto emit imperatively.layout/Header— fixed top nav with logo slot, desktop nav items, action slot, mobile-toggle buttonlayout/Footer— site footer with logo / socials / legal links / app-store badges / version pill (click to copy)layout/MobileDrawer— slide-out drawer with profile header (avatar + name + email), menu list (icon + label + optional danger color), and footer slot (typically a version string)marketing/Hero— layout shell with eyebrow + title + subtitle + primary/secondary CTAs + optional side slot; bring your own backgroundmarketing/CodeExample— syntax-highlighted code block with optional copy button. Shiki is an optional peer: pass a pre-built highlighter, pre-rendered HTML, or skip both for plain-text fallback.charts/ChartContainer— rechartsResponsiveContainerwrapper that applies token-backed grid/axis/tooltip styling. Recharts is an optional peer — consumers passResponsiveContainerin as a prop.charts/ChartTooltip— sharedcontentStyle/itemStyle/labelStyle/cursorpresets for recharts<Tooltip>+ aChartTooltipBoxhelper for custom tooltips.charts/ParticleCanvas,charts/WaveCanvas— pure canvas animation primitives (promoted from platform's radar-chart). Honorprefers-reduced-motion.
Install
pnpm add @precisa-saude/ui @precisa-saude/themesPeer dependencies: react@^19, react-dom@^19.
Use
Utilities
import { cn } from '@precisa-saude/ui/utils';
<div className={cn('px-4 py-2', isActive && 'bg-primary')} />;Hooks
import { useGridCol, useMediaQuery, useReducedMotion, useWideGrid } from '@precisa-saude/ui/hooks';
function Hero() {
const col = useGridCol();
const reduced = useReducedMotion();
return (
<section className="grid grid-cols-[repeat(var(--grid-cols),1fr)] gap-4">
<h1 style={col(3, 10)}>Welcome</h1>
{!reduced && <video autoPlay loop muted src="/hero.webm" />}
</section>
);
}Convenience root import
import { cn, useWideGrid } from '@precisa-saude/ui';Sub-path exports
| Path | Contents |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| @precisa-saude/ui | Everything (re-exports from all sub-paths) |
| @precisa-saude/ui/utils | cn |
| @precisa-saude/ui/hooks | useMediaQuery, useWideGrid, useDesktop, useGridCol, useReducedMotion |
| @precisa-saude/ui/decorative | CornerSquares, DuotoneFilter, GridOverlay, MosaicBg |
| @precisa-saude/ui/primitives | Button, Badge, Tooltip, Select, Dialog, Tabs, Accordion, Popover, Switch, Checkbox, Field, Menu, Toast (+ sub-components / variants) |
| @precisa-saude/ui/layout | PageContainer, SectionContainer, Header, Footer, MobileDrawer |
| @precisa-saude/ui/marketing | Marquee, Callout, StatsGrid, FeatureGrid, Hero, CodeExample |
| @precisa-saude/ui/cards | ActionCard, NewsCard |
| @precisa-saude/ui/navigation | Breadcrumbs, NavigationalBreadcrumbs, SlidingTabs, Pagination |
| @precisa-saude/ui/charts | ChartContainer, ChartTooltipBox, chartTooltipStyles, ParticleCanvas, WaveCanvas |
Tree-shakable: bundle only what you import.
License
Apache-2.0
Composição geométrica da marca
import { BrandComposition } from '@precisa-saude/ui/brand';
export function FundoDaSecao() {
return (
<section style={{ position: 'relative', isolation: 'isolate', overflow: 'clip' }}>
<BrandComposition
anchor="top"
bleed={false}
className="fundo-marca"
mode="varied"
seed={12}
texture={0.16}
viewBoxX={0}
/>
{/* Conteúdo do projeto */}
</section>
);
}.fundo-marca {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
z-index: -1;
pointer-events: none;
opacity: 0.35;
}O mesmo import atende FHIR Brasil, MedBench Brasil, DataSUS Viz e platform.
Não requer Motion, Tailwind, assets de fotografia nem CSS adicional da biblioteca.
O consumidor define dimensões e recorte; a composição usa coordenadas 1672 × 941.
mode="reference" preserva os planos da capa, e mode="varied" varia a geometria
com uma semente estável. mirror espelha apenas as formas; children aceita SVG
em primeiro plano, por exemplo um retrato do projeto. Use label quando esse
conteúdo for significativo; sem rótulo, o SVG é decorativo.
- Pontos entram individualmente a cada 18 ms.
- Círculos crescem do centro; retângulos e planos de canto deslizam da borda.
- Trilhos e fragmentos têm deslocamentos laterais individuais durante a rolagem.
- Saídas percorrem a mesma sequência ao contrário, inclusive se a entrada for interrompida.
- O grão é estático, limitado aos planos sólidos e configurável por
texture(0 a 1). parallax={0}desativa apenas a deriva;animated={false}mostra a composição estática.prefers-reduced-motion: reducedesativa ambos, inclusive ao mudar a preferência ao vivo.- Sem IntersectionObserver, SSR ou sem JavaScript, conserva a geometria estática completa.
- Observadores e listeners são removidos no unmount; a aba oculta pausa a animação.
Desenvolvimento entre repositórios
Antes da publicação, construa packages/ui neste worktree. Em platform, execute
node scripts/preview-shared-ui.mjs /caminho/tooling/packages/ui. Esse utilitário
copia apenas o build para o node_modules da landing e não altera o lockfile.
Para outros consumidores, use um pacote local gerado por pnpm pack em um
checkout de teste. Evite symlinks para SSR: dependências externas podem resolver
uma segunda cópia de React no repositório de origem.
Não salve caminhos absolutos no manifesto ou lockfile. Refaça o build de UI, atualize a cópia local e reinicie o preview após editar a biblioteca.
A ordem de entrega é tooling primeiro: publicar a versão com o subpath ./brand,
atualizar a dependência e o lockfile de cada consumidor para essa versão real,
e então integrar os imports. A versão publicada atual ainda não possui essa API.
O vínculo local serve para revisão; não substitui essa atualização antes de CI/merge.
Validação: pnpm --filter @precisa-saude/ui test:coverage compila a biblioteca,
verifica o controlador e SSR usando o runner nativo do Node, com limites de 80%
para linhas, funções e ramos. Não adiciona dependências de runtime ou de teste.
Consulte a baseline e o escopo do gate de CI.
