npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

sistemasintegrados-ui

v0.1.1

Published

Design system padrão dos sistemas integrados

Readme

sistemasintegrados-ui

Design system padrão dos Sistemas Integrados — componentes React construídos sobre Radix UI e Tailwind CSS v4, com suporte nativo a dark mode.

Instalação

npm install sistemasintegrados-ui

CSS (obrigatório)

Importe o CSS uma única vez na raiz da sua aplicação (ex.: main.tsx, app.tsx ou o arquivo de estilos global):

import 'sistemasintegrados-ui/styles'

O CSS contém:

  • Tokens de cor para temas claro e escuro (variáveis CSS HSL)
  • Tipografia: Inter (sans-serif) e JetBrains Mono (monospace) via Google Fonts
  • Tokens de border-radius, sombras, espaçamento e tracking
  • Utilitários de elevação (hover-elevate, toggle-elevate) para estados interativos sem mudar cor de fundo
  • Customização de scrollbars alinhada ao tema
  • Suporte a .dark e [data-theme="dark"]

Configuração do Tailwind

O pacote usa Tailwind CSS v4. Para que as classes do design system sejam geradas corretamente no projeto consumidor, aponte o scanner para o dist do pacote.

Com @import "tailwindcss" no CSS (v4 puro):

@import "tailwindcss";
@source "../node_modules/sistemasintegrados-ui/dist";

Com arquivo tailwind.config.ts (v3/v4 compat):

export default {
  content: [
    './src/**/*.{ts,tsx}',
    './node_modules/sistemasintegrados-ui/dist/**/*.{js,cjs}',
  ],
  darkMode: 'class',
}

Tema escuro

Adicione a classe .dark ou o atributo data-theme="dark" no elemento raiz:

document.documentElement.classList.add('dark')
// ou
document.documentElement.setAttribute('data-theme', 'dark')

Componentes

Inputs

Button

import { Button } from 'sistemasintegrados-ui'

<Button>Salvar</Button>
<Button variant="outline">Cancelar</Button>
<Button variant="destructive" size="sm">Excluir</Button>
<Button variant="ghost" size="icon"><PlusIcon /></Button>
<Button disabled>Indisponível</Button>

| Prop | Valores | |------|---------| | variant | default · secondary · outline · ghost · link · destructive | | size | default · sm · lg · icon | | asChild | boolean — renderiza o filho como elemento raiz (útil com <Link>) |

Input / Textarea

import { Input, Textarea, Label } from 'sistemasintegrados-ui'

<Label htmlFor="nome">Nome</Label>
<Input id="nome" placeholder="Digite o nome..." />

<Label htmlFor="obs">Observações</Label>
<Textarea id="obs" rows={4} placeholder="Detalhes..." />

Checkbox / RadioGroup

import { Checkbox, Label, RadioGroup, RadioGroupItem } from 'sistemasintegrados-ui'

<div className="flex items-center gap-2">
  <Checkbox id="ativo" />
  <Label htmlFor="ativo">Ativo</Label>
</div>

<RadioGroup defaultValue="op1">
  <div className="flex items-center gap-2">
    <RadioGroupItem value="op1" id="op1" />
    <Label htmlFor="op1">Opção 1</Label>
  </div>
  <div className="flex items-center gap-2">
    <RadioGroupItem value="op2" id="op2" />
    <Label htmlFor="op2">Opção 2</Label>
  </div>
</RadioGroup>

Select

import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from 'sistemasintegrados-ui'

<Select>
  <SelectTrigger>
    <SelectValue placeholder="Selecione..." />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="a">Opção A</SelectItem>
    <SelectItem value="b">Opção B</SelectItem>
  </SelectContent>
</Select>

MultiSelectCombobox

Dropdown com busca e seleção múltipla via checkboxes.

import { MultiSelectCombobox, type MultiSelectOption } from 'sistemasintegrados-ui'

const options: MultiSelectOption[] = [
  { value: 'ti', label: 'TI' },
  { value: 'rh', label: 'RH' },
]

<MultiSelectCombobox
  options={options}
  value={selected}
  onChange={setSelected}
  placeholder="Selecionar setores..."
/>

MultipleSelector

Seletor múltiplo com tags removíveis, busca assíncrona e limite de seleções.

import MultipleSelector, { type Option } from 'sistemasintegrados-ui'

<MultipleSelector
  defaultOptions={options}
  value={value}
  onChange={setValue}
  placeholder="Adicionar responsáveis..."
  maxSelected={3}
  onMaxSelected={(max) => alert(`Máximo de ${max} seleções`)}
/>

Suporta opções com color (exibe bolinha de status antes do label) e busca assíncrona via onSearch.

ColorPicker

Seletor de tema de cor com paleta pré-definida. Salva a preferência no localStorage.

import { ColorPicker } from 'sistemasintegrados-ui'

<ColorPicker />

Display

Badge

import { Badge } from 'sistemasintegrados-ui'

<Badge>Padrão</Badge>
<Badge variant="success">Concluído</Badge>
<Badge variant="warning">Pendente</Badge>
<Badge variant="destructive">Cancelado</Badge>
<Badge variant="info">Em andamento</Badge>
<Badge variant="secondary">Rascunho</Badge>
<Badge variant="outline">Outline</Badge>

7 variantes: default · secondary · outline · success · warning · destructive · info

Card

import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from 'sistemasintegrados-ui'

<Card>
  <CardHeader>
    <CardTitle>Título</CardTitle>
    <CardDescription>Subtítulo ou descrição breve.</CardDescription>
  </CardHeader>
  <CardContent>
    Conteúdo principal do card.
  </CardContent>
  <CardFooter>
    <Button>Ação</Button>
  </CardFooter>
</Card>

Avatar

import { Avatar, AvatarImage, AvatarFallback } from 'sistemasintegrados-ui'

<Avatar>
  <AvatarImage src="/foto.jpg" alt="Guilherme" />
  <AvatarFallback>GP</AvatarFallback>
</Avatar>

Table

import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from 'sistemasintegrados-ui'

<Table>
  <TableHeader>
    <TableRow>
      <TableHead>ID</TableHead>
      <TableHead>Nome</TableHead>
      <TableHead>Status</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell>001</TableCell>
      <TableCell>Instalação de rede</TableCell>
      <TableCell><Badge variant="success">Concluído</Badge></TableCell>
    </TableRow>
  </TableBody>
</Table>

Progress / Skeleton / FilterBadge

import { Progress, Skeleton, FilterBadge } from 'sistemasintegrados-ui'

<Progress value={72} />

<Skeleton className="h-4 w-48" />

<FilterBadge label="Status: Aberto" onRemove={() => clearFilter('status')} />

Navigation

Breadcrumb

import {
  Breadcrumb, BreadcrumbList, BreadcrumbItem,
  BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator,
} from 'sistemasintegrados-ui'

<Breadcrumb>
  <BreadcrumbList>
    <BreadcrumbItem><BreadcrumbLink href="/">Início</BreadcrumbLink></BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem><BreadcrumbLink href="/ordens">Ordens</BreadcrumbLink></BreadcrumbItem>
    <BreadcrumbSeparator />
    <BreadcrumbItem><BreadcrumbPage>OS #1042</BreadcrumbPage></BreadcrumbItem>
  </BreadcrumbList>
</Breadcrumb>

Tabs

import { Tabs, TabsList, TabsTrigger, TabsContent } from 'sistemasintegrados-ui'

<Tabs defaultValue="detalhes">
  <TabsList>
    <TabsTrigger value="detalhes">Detalhes</TabsTrigger>
    <TabsTrigger value="historico">Histórico</TabsTrigger>
  </TabsList>
  <TabsContent value="detalhes">...</TabsContent>
  <TabsContent value="historico">...</TabsContent>
</Tabs>

Separator

import { Separator } from 'sistemasintegrados-ui'

<Separator />                          {/* horizontal */}
<Separator orientation="vertical" />   {/* vertical */}

Overlay

Dialog

import {
  Dialog, DialogTrigger, DialogContent,
  DialogHeader, DialogTitle, DialogFooter,
} from 'sistemasintegrados-ui'

<Dialog>
  <DialogTrigger asChild>
    <Button>Abrir</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Confirmar ação</DialogTitle>
    </DialogHeader>
    <p>Deseja continuar?</p>
    <DialogFooter>
      <Button>Confirmar</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>

AlertDialog

Modal de confirmação com ação destrutiva.

import {
  AlertDialog, AlertDialogTrigger, AlertDialogContent,
  AlertDialogHeader, AlertDialogTitle, AlertDialogDescription,
  AlertDialogFooter, AlertDialogAction, AlertDialogCancel,
} from 'sistemasintegrados-ui'

<AlertDialog>
  <AlertDialogTrigger asChild>
    <Button variant="destructive">Excluir</Button>
  </AlertDialogTrigger>
  <AlertDialogContent>
    <AlertDialogHeader>
      <AlertDialogTitle>Tem certeza?</AlertDialogTitle>
      <AlertDialogDescription>Esta ação não pode ser desfeita.</AlertDialogDescription>
    </AlertDialogHeader>
    <AlertDialogFooter>
      <AlertDialogCancel>Cancelar</AlertDialogCancel>
      <AlertDialogAction>Excluir</AlertDialogAction>
    </AlertDialogFooter>
  </AlertDialogContent>
</AlertDialog>

DropdownMenu

import {
  DropdownMenu, DropdownMenuTrigger, DropdownMenuContent,
  DropdownMenuItem, DropdownMenuSeparator,
} from 'sistemasintegrados-ui'

<DropdownMenu>
  <DropdownMenuTrigger asChild>
    <Button variant="ghost" size="icon"><MoreHorizontal /></Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent align="end">
    <DropdownMenuItem>Editar</DropdownMenuItem>
    <DropdownMenuItem>Duplicar</DropdownMenuItem>
    <DropdownMenuSeparator />
    <DropdownMenuItem className="text-destructive">Excluir</DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

Command (paleta de busca)

import {
  Command, CommandInput, CommandList,
  CommandGroup, CommandItem, CommandEmpty,
} from 'sistemasintegrados-ui'

<Command>
  <CommandInput placeholder="Buscar..." />
  <CommandList>
    <CommandEmpty>Nenhum resultado.</CommandEmpty>
    <CommandGroup heading="Ações">
      <CommandItem>Nova OS</CommandItem>
      <CommandItem>Relatório</CommandItem>
    </CommandGroup>
  </CommandList>
</Command>

Popover

import { Popover, PopoverTrigger, PopoverContent } from 'sistemasintegrados-ui'

<Popover>
  <PopoverTrigger asChild>
    <Button variant="outline">Filtros</Button>
  </PopoverTrigger>
  <PopoverContent className="w-80">
    Conteúdo do popover
  </PopoverContent>
</Popover>

Feedback

Toast

Baseado em react-hot-toast. Adicione o <Toaster /> na raiz e use toast.* em qualquer lugar.

import { toast } from 'sistemasintegrados-ui'
import { Toaster } from 'react-hot-toast'

// Na raiz da app:
<Toaster position="top-right" />

// Em qualquer componente:
toast.success('Ordem salva com sucesso!')
toast.error('Falha ao enviar.')
toast.warning('Campos incompletos.')
toast.info('Sincronização em andamento.')

// Notificação rica com título e ação:
toast.notification({
  title: 'Nova OS atribuída',
  message: 'OS #1042 foi atribuída a você.',
  type: 'info',
  action: { label: 'Ver', onClick: () => navigate('/ordens/1042') },
})

AnimatedToastProvider

Provider alternativo com animações via Framer Motion e suporte a módulos de notificação (OS, Atendimento, Comentários).

import { AnimatedToastProvider, useAnimatedToast } from 'sistemasintegrados-ui'

// Na raiz:
<AnimatedToastProvider position="top-right">
  <App />
</AnimatedToastProvider>

// Em qualquer componente:
const { showToast } = useAnimatedToast()
showToast({ message: 'Atualizado!', type: 'success' })

NotificationInboxPopover

Sino de notificações in-app com badge de não lidas, feed de itens e integração com a API do backend.

import { NotificationInboxPopover } from 'sistemasintegrados-ui'

<NotificationInboxPopover
  usuarioId={user.id}
  initialUnreadCount={sharedData.unreadCount}
  clientId={transmitClientId}
/>

Requer backend com endpoints /api/notificacoes e SSE via @adonisjs/transmit.

FileUploadProgress

Área de upload com drag-and-drop, barra de progresso por arquivo e tabela de itens enviados.

import { FileUploadProgress, type FileUploadItem } from 'sistemasintegrados-ui'

<FileUploadProgress
  files={files}
  onFilesAdded={handleFilesAdded}
  onRemove={handleRemove}
/>

DateTime

DatePicker / DateTimePicker

import { DatePicker, DateTimePicker } from 'sistemasintegrados-ui'

<DatePicker
  value={date}
  onChange={setDate}
  placeholder="Selecione uma data"
/>

<DateTimePicker
  value={datetime}
  onChange={setDatetime}
/>

DateRangePicker

Seletor de intervalo com calendário duplo e presets em pt-BR (Hoje, Últimos 7 dias, Este mês, etc.).

import { DateRangePicker } from 'sistemasintegrados-ui'

<DateRangePicker
  from={filters.dataInicio}
  to={filters.dataFim}
  onChange={({ from, to }) => setFilters({ dataInicio: from, dataFim: to })}
/>

Layout

ScrollArea

import { ScrollArea } from 'sistemasintegrados-ui'

<ScrollArea className="h-72">
  {longContent}
</ScrollArea>

Utilitários

import { cn, formatDateTime, formatDateBr, formatTimeBr, getInitials, getCsrfHeaders } from 'sistemasintegrados-ui'

cn('px-4 py-2', isActive && 'bg-primary')          // merge de classes Tailwind
formatDateTime('2025-11-26T06:33:00Z')              // "26/11/2025 às 06:33:00"
formatDateBr('2025-11-26')                          // "26/11/2025"
formatTimeBr('2025-11-26T14:30:00Z')               // "14:30"
getInitials('Guilherme Patuci')                     // "GP"
getCsrfHeaders()                                    // { 'X-XSRF-TOKEN': '...' }

Locale pt-BR para calendários

import { calendarDateFnsLocalePt, presetsPt } from 'sistemasintegrados-ui'

// Usar em <Calendar locale={calendarDateFnsLocalePt} />
// presetsPt = array com Hoje, Ontem, Últimos 7 dias, Últimos 30 dias, Este mês, Mês passado, Este ano