@wellingtonhlc/shared-ui
v0.25.1
Published
Conjunto de componentes visuais padronizados, criado por Wellington Henrique para aplicacoes React.
Downloads
6,163
Readme
Wellington Shared UI
Conjunto de componentes visuais padronizados, criado por Wellington Henrique para aplicacoes React.
O objetivo deste pacote e concentrar componentes base, tokens, presets e helpers de UI reutilizaveis, sem regras de negocio de dominio.
Pacote
npm install @wellingtonhlc/shared-uiUso basico:
import { Button, Card, Page, Table } from '@wellingtonhlc/shared-ui';
export function ExamplePage() {
return (
<Page.Root>
<Card.Root>
<Card.Header>
<Card.Title>Registros</Card.Title>
<Card.Description>Consulta de dados</Card.Description>
</Card.Header>
<Card.Body>
<Button>Salvar</Button>
</Card.Body>
</Card.Root>
</Page.Root>
);
}Principios
Este pacote foi desenhado para oferecer infraestrutura visual generica:
- componentes base de interface;
- campos de formulario reutilizaveis;
- primitivas de acao;
- tokens, estilos e presets;
- helpers sem dependencia de dominio;
- composicao por slots quando o componente possui partes internas.
Validacao de Page Actions
O pacote publica o CLI shared-ui-check-page-actions para validar o contrato de actions em uma aplicacao.
Contrato esperado:
AppLayout.actionse somente o slot de layout.Page.Actionse o root visual da barra.- Props como
helpContent,helpLabel,position,alignesizepertencem aoPage.Actions. - Nao usar
ActionBar.*,Page.Root actions=...dentro deAppLayout, Fragment,divouPage.ActionButtonsolto como root deAppLayout.actions.
Uso recomendado:
{
"scripts": {
"check:page-actions": "shared-ui-check-page-actions"
}
}Tambem e possivel apontar um diretorio explicitamente:
shared-ui-check-page-actions ./srcPage Actions
Page.Actions e a raiz visual das acoes de tela. O pacote suporta left, top, right e
bottom, com left como padrao desktop e bottom como fallback mobile quando permitido.
Persistencia de preferencia continua sendo responsabilidade do consumidor. Use
Page.ActionsProvider para fornecer a preferencia global sem acoplar o pacote a
localStorage:
import { useCallback, useMemo, useState } from 'react';
import { Page, type PageActionsPosition, type PageActionsPreferences } from '@wellingtonhlc/shared-ui';
const storageKey = '@my-app/preference/page-actions-position';
const positions: PageActionsPosition[] = ['left', 'top', 'right', 'bottom'];
function readStoredPosition() {
const stored = window.localStorage.getItem(storageKey);
return positions.includes(stored as PageActionsPosition) ? (stored as PageActionsPosition) : undefined;
}
export function AppLayout({ children }: { children: React.ReactNode }) {
const [position, setPosition] = useState<PageActionsPosition | undefined>(readStoredPosition);
const handlePositionChange = useCallback(function handlePositionChange(nextPosition: PageActionsPosition) {
setPosition(nextPosition);
window.localStorage.setItem(storageKey, nextPosition);
}, []);
const preferences = useMemo<PageActionsPreferences>(
() => ({
mobilePosition: 'bottom',
movable: true,
onPositionChange: handlePositionChange,
position,
}),
[handlePositionChange, position],
);
return (
<Page.ActionsProvider preferences={preferences}>
<Page.ActionsSlot position="left" />
<main>{children}</main>
<Page.ActionsSlot position="right" />
<Page.ActionsSlot position="top" />
<Page.ActionsSlot position="bottom" />
</Page.ActionsProvider>
);
}Acoes de uma tela devem continuar usando Page.Actions; o provider apenas controla onde elas serao exibidas:
import { Page } from '@wellingtonhlc/shared-ui/components/Page';
import { Save } from 'lucide-react';
export function EditPageActions() {
return (
<Page.Actions helpLabel="Ajuda" helpContent="Revise os dados antes de salvar.">
<Page.ActionButton icon={<Save />} label="Salvar" />
</Page.Actions>
);
}Telas podem limitar o contrato localmente:
<Page.Actions allowedPositions={['top', 'bottom']} movable={false}>
<Page.ActionButton label="Salvar" />
</Page.Actions>Acoes auxiliares podem ser passadas por helpContent, metaActions ou por componentes
marcados como meta. Em barras verticais, o grupo meta e renderizado em modo compacto
e alinhado na borda externa da barra para preservar leitura visual; as labels continuam
obrigatorias no contrato e sao usadas para acessibilidade e tooltip.
Exportacoes
Entrada principal:
import { Button, Card, Modal, Table, cn } from '@wellingtonhlc/shared-ui';Subpaths recomendados para telas grandes ou rotas lazy-loaded:
import { Button } from '@wellingtonhlc/shared-ui/components/Button';
import { Table } from '@wellingtonhlc/shared-ui/components/Table';
import { cn } from '@wellingtonhlc/shared-ui/utils/cn';Estilos:
import '@wellingtonhlc/shared-ui/styles.css';Preset Tailwind:
import sharedUiPreset from '@wellingtonhlc/shared-ui/tailwind-preset';Componentes
Componentes disponiveis na API publica:
| Grupo | Componentes |
|-------|-------------|
| Layout | AppShell, Page, Sidebar, Card, StatCard |
| Acoes | Button, ActionPrimitives, AppShellActions, ConfirmationDialog |
| Feedback | Badge, EmptyState, PageMessage, Tooltip, CopyableField |
| Formularios | FieldControl, FieldGroup, TextField, TextareaField, SelectField, SelectionField, DateField, DecimalField, MultiSelectField, PasswordInput, Switch, RadioGroup |
| Consulta | Filter, Workspace |
| Dados | Table, Pagination, TabsUnderlined |
| Controle de renderizacao | RenderIf, RenderCase |
| Tema | ThemePreferencesSelector |
AppShell.Topbar.Button
Use AppShell.Topbar.Button para acoes de icone na barra superior, como notificacoes,
configuracoes e atalhos globais. O componente reutiliza o mesmo contrato visual dos
primitivos de acao, mas aplica o tamanho esperado para a topbar.
import { AppShell } from '@wellingtonhlc/shared-ui';
import { Bell, Settings } from 'lucide-react';
<AppShell.Actions>
<AppShell.Topbar.Button icon={<Bell />} tooltip="Notificacoes" />
<AppShell.Topbar.Button icon={<Settings />} tooltip="Configuracoes" />
</AppShell.Actions>ThemePreferencesSelector
ThemePreferencesSelector centraliza a escolha de cor e aparencia (system, light, dark) usada pelos consumidores.
Contrato minimo:
import { ThemePreferencesSelector, type ThemePreferencesValue } from '@wellingtonhlc/shared-ui';
const value: ThemePreferencesValue = {
color: 'indigo',
appearance: 'system',
};
<ThemePreferencesSelector
value={value}
options={[
{ key: 'indigo', label: 'Indigo', primary: '#5b5cff' },
{ key: 'emerald', label: 'Emerald', primary: '#059669' },
]}
onChange={setValue}
/>;Pontos de validacao:
- O botao de aparencia selecionado deve ficar perceptivelmente destacado sem depender de hover.
- Opcoes de cor bloqueadas usam
lockede podem informarrequiredPlan. - Use
showColorSelector={false}oushowAppearanceSelector={false}quando o consumidor precisar exibir apenas uma parte do controle. - A story
AppearanceStatesmostra as tres aparencias ja selecionadas para validacao visual rapida.
SelectionField
SelectionField padroniza campos de selecao que exibem um registro, abrem uma busca externa e permitem limpar o valor selecionado. O componente nao gerencia modal nem estado interno do registro; o consumidor controla value, onClick e onClear.
Contrato minimo:
import { SelectionField, type SelectionDisplayValue } from '@wellingtonhlc/shared-ui';
import { UserCheck } from 'lucide-react';
const value: SelectionDisplayValue = {
title: 'Registro selecionado',
subtitle: 'Descricao complementar',
meta: 'COD-1024',
};
<SelectionField
label="Registro"
value={value}
icon={<UserCheck />}
clearable
size="sm"
selectTooltip="Selecionar registro"
clearTooltip="Limpar registro"
onClick={openSearch}
onClear={clearSelection}
/>;Pontos de validacao:
sizesegue a mesma escala visual dos campos base (xs,sm,md,lg).- Use
triggerSlotquando o consumidor precisar injetar um botao proprio para abrir a selecao. clearableexibe a acao de limpar somente quando havalueeonClear.shortcutHintpode exibir atalhos de teclado, comoF1.
Filter
Filter.Root organiza filtros compactos, ocupando apenas o espaço necessário. Quando houver muitos filtros, somente o corpo do painel rola e as ações continuam visíveis.
import { Button, Filter, TextField } from '@wellingtonhlc/shared-ui';
export function CustomersFilters() {
return (
<Filter.Root description="Refine os critérios antes de consultar os resultados.">
<TextField label="Buscar" size="sm" />
<Filter.Footer>
<Button type="submit" size="sm">
Pesquisar
</Button>
</Filter.Footer>
</Filter.Root>
);
}Padrões do painel:
- Usa
h-fitew-fitpor padrão, sem ocupar a altura inteira da tela. - Limita a altura com
maxHeightClassName; o default émax-h-[calc(100vh-12rem)]. - Aplica rolagem apenas na área de filtros.
- Use
Filter.Footerpara manter botões sempre visíveis no rodapé do painel. - Em interfaces densas, campos dentro do painel devem preferir
size="sm"e nao devem usar formatorounded-full.
Contrato publico 0.1.0
A API pública pré-v1 foi limpa para evitar compatibilidade artificial em produção.
Exports removidos:
ActionBar: usePage.Actions,Page.ActionButtonePage.ActionsSeparator.Dialog: useModal.ChoiceGroup: useRadioGroup.ConditionalCase: useRenderCase.ConditionalRender: useRenderIf.ToggleSwitch: useSwitch.SearchFilter: useFilter.SearchWorkspace: componha layout no consumidor ou com componentes genéricos.TabsUnderlineeUnderlinedTabs: useTabsUnderlined.