@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-ui

Uso 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.actions e somente o slot de layout.
  • Page.Actions e o root visual da barra.
  • Props como helpContent, helpLabel, position, align e size pertencem ao Page.Actions.
  • Nao usar ActionBar.*, Page.Root actions=... dentro de AppLayout, Fragment, div ou Page.ActionButton solto como root de AppLayout.actions.

Uso recomendado:

{
  "scripts": {
    "check:page-actions": "shared-ui-check-page-actions"
  }
}

Tambem e possivel apontar um diretorio explicitamente:

shared-ui-check-page-actions ./src

Page 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 locked e podem informar requiredPlan.
  • Use showColorSelector={false} ou showAppearanceSelector={false} quando o consumidor precisar exibir apenas uma parte do controle.
  • A story AppearanceStates mostra 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:

  • size segue a mesma escala visual dos campos base (xs, sm, md, lg).
  • Use triggerSlot quando o consumidor precisar injetar um botao proprio para abrir a selecao.
  • clearable exibe a acao de limpar somente quando ha value e onClear.
  • shortcutHint pode exibir atalhos de teclado, como F1.

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-fit e w-fit por 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.Footer para 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 formato rounded-full.

Contrato publico 0.1.0

A API pública pré-v1 foi limpa para evitar compatibilidade artificial em produção.

Exports removidos:

  • ActionBar: use Page.Actions, Page.ActionButton e Page.ActionsSeparator.
  • Dialog: use Modal.
  • ChoiceGroup: use RadioGroup.
  • ConditionalCase: use RenderCase.
  • ConditionalRender: use RenderIf.
  • ToggleSwitch: use Switch.
  • SearchFilter: use Filter.
  • SearchWorkspace: componha layout no consumidor ou com componentes genéricos.
  • TabsUnderline e UnderlinedTabs: use TabsUnderlined.