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

@odd-studio/ui

v1.0.0

Published

Biblioteca de componentes React + Tailwind profissional, minimalista e sofisticada

Readme

🎨 Odd Prototype UI

Biblioteca de componentes React + Tailwind com estilo visual profissional, minimalista e sofisticado.

📦 Instalação

npm install @odd-prototype/ui

🚀 Configuração

1. Configure o Tailwind

Adicione o caminho dos componentes no seu tailwind.config.js:

module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
    "./node_modules/@odd-prototype/ui/**/*.{js,jsx}"
  ],
  // Extenda com as configurações do Odd Prototype UI
  presets: [require('@odd-prototype/ui/tailwind.config.js')],
}

2. Importe os estilos

No arquivo principal da sua aplicação (ex: index.js ou App.js):

import '@odd-prototype/ui/src/styles.css';

📚 Componentes

Button

Botões com estilo profissional e variantes.

import { Button } from '@odd-prototype/ui';

// Botão primário (padrão)
<Button onClick={handleClick}>
  Salvar Proposta
</Button>

// Botão secundário
<Button variant="secondary" size="large">
  Cancelar
</Button>

// Botão texto
<Button variant="text" size="small">
  Ver detalhes
</Button>

// Botão full width
<Button fullWidth>
  Criar Nova Proposta
</Button>

// Botão desabilitado
<Button disabled>
  Processando...
</Button>

Props:

  • variant: 'primary' | 'secondary' | 'text' (padrão: 'primary')
  • size: 'small' | 'medium' | 'large' (padrão: 'medium')
  • fullWidth: boolean (padrão: false)
  • disabled: boolean (padrão: false)
  • onClick: Function

Card

Containers para agrupar conteúdo relacionado.

import { Card } from '@bencao/ui';

// Card simples
<Card>
  <h3>Resumo de Vendas</h3>
  <p>Conteúdo do card...</p>
</Card>

// Card com estrutura completa
<Card>
  <Card.Header>
    <h2>Análise de Desempenho</h2>
  </Card.Header>
  
  <Card.Body>
    <p>Conteúdo principal...</p>
  </Card.Body>
  
  <Card.Footer>
    <Button>Exportar Relatório</Button>
  </Card.Footer>
</Card>

// Card sem padding ou sombra
<Card noPadding noShadow>
  <img src="chart.png" alt="Gráfico" />
</Card>

Props:

  • noPadding: boolean - Remove padding interno
  • noShadow: boolean - Remove sombra

Input

Campos de entrada com labels e validação.

import { Input } from '@bencao/ui';

// Input básico
<Input
  label="Nome do Cliente"
  placeholder="Digite o nome..."
  value={name}
  onChange={(e) => setName(e.target.value)}
/>

// Input com erro
<Input
  label="Email"
  type="email"
  value={email}
  onChange={(e) => setEmail(e.target.value)}
  error={true}
  errorMessage="Email inválido"
/>

// Input com texto de ajuda
<Input
  label="Valor da Proposta"
  type="number"
  helperText="Valor em reais (R$)"
/>

// Select
<Input.Select
  label="Status"
  options={[
    { value: 'negociacao', label: 'Em Negociação' },
    { value: 'faturado', label: 'Faturado' },
  ]}
  value={status}
  onChange={(e) => setStatus(e.target.value)}
/>

// Textarea
<Input.Textarea
  label="Observações"
  rows={4}
  value={notes}
  onChange={(e) => setNotes(e.target.value)}
/>

Props:

  • label: string - Label do input
  • type: string - Tipo do input (padrão: 'text')
  • placeholder: string
  • value: string
  • onChange: Function
  • disabled: boolean
  • error: boolean
  • errorMessage: string
  • helperText: string
  • fullWidth: boolean (padrão: true)

MetricCard

Cards para exibir métricas e KPIs.

import { MetricCard } from '@bencao/ui';

// Métrica simples
<MetricCard
  value="R$ 125.000"
  label="Faturamento Total"
/>

// Métrica com variante de cor
<MetricCard
  value="87"
  suffix="%"
  label="Taxa de Conversão"
  variant="excellent"
/>

// Métrica com tendência
<MetricCard
  value="23"
  label="Propostas em Negociação"
  trend="+15% vs mês anterior"
  trendDirection="up"
/>

// Grid de métricas
<MetricCard.Grid columns={4} gap="20px">
  <MetricCard value="45" label="Propostas" />
  <MetricCard value="R$ 2.3M" label="Valor Total" />
  <MetricCard value="76%" label="Taxa Sucesso" variant="good" />
  <MetricCard value="12" label="Em Aberto" />
</MetricCard.Grid>

Props:

  • value: string | number - Valor principal
  • label: string - Label da métrica
  • prefix: string - Prefixo (ex: "R$")
  • suffix: string - Sufixo (ex: "%")
  • variant: 'default' | 'excellent' | 'good' | 'average' | 'poor'
  • trend: string - Texto de tendência
  • trendDirection: 'up' | 'down' | 'neutral'

StatusBadge

Badges para exibir status de propostas.

import { StatusBadge } from '@bencao/ui';

// Status predefinidos
<StatusBadge status="negociacao" />
<StatusBadge status="aguardando" />
<StatusBadge status="faturado" />
<StatusBadge status="perdida" />
<StatusBadge status="standby" />
<StatusBadge status="anulada" />

// Status customizado
<StatusBadge
  status="custom"
  label="Em Análise"
  color="#3498db"
/>

// Badge genérico
<StatusBadge.Badge variant="success">
  Aprovado
</StatusBadge.Badge>

<StatusBadge.Badge variant="warning">
  Atenção
</StatusBadge.Badge>

Props:

  • status: 'negociacao' | 'aguardando' | 'faturado' | 'perdida' | 'standby' | 'anulada' | 'custom'
  • label: string - Texto customizado (obrigatório se status='custom')
  • color: string - Cor customizada (obrigatório se status='custom')

Table

Tabelas responsivas com estilo profissional.

import { Table } from '@bencao/ui';

<Table>
  <Table.Header>
    <Table.Row>
      <Table.HeaderCell>Cliente</Table.HeaderCell>
      <Table.HeaderCell align="right">Valor</Table.HeaderCell>
      <Table.HeaderCell>Status</Table.HeaderCell>
      <Table.HeaderCell align="center">Ações</Table.HeaderCell>
    </Table.Row>
  </Table.Header>
  
  <Table.Body>
    <Table.Row hoverable onClick={() => handleView(id)}>
      <Table.Cell>Empresa ABC</Table.Cell>
      <Table.Cell align="right" numeric>R$ 50.000</Table.Cell>
      <Table.Cell>
        <StatusBadge status="negociacao" />
      </Table.Cell>
      <Table.Cell align="center">
        <Button size="small">Ver</Button>
      </Table.Cell>
    </Table.Row>
  </Table.Body>
</Table>

Props:

  • hoverable: boolean - Hover nas linhas (padrão: true)
  • striped: boolean - Linhas zebradas
  • TableCell:
    • align: 'left' | 'center' | 'right'
    • numeric: boolean - Usa fonte monospace

BrandTag

Logo/marca da aplicação.

import { BrandTag } from '@bencao/ui';

// Tag simples
<BrandTag />

// Tag com texto customizado
<BrandTag text="BENDITO" size="large" />

// Logo completo com título
<BrandTag.Logo
  title="Sistema de Propostas"
  subtitle="Gestão Comercial"
  size="medium"
/>

Props:

  • text: string (padrão: 'BENÇÃO')
  • size: 'small' | 'medium' | 'large'

Alert

Mensagens de alerta e notificações.

import { Alert } from '@bencao/ui';

// Alerta de informação
<Alert variant="info" title="Informação">
  Dados salvos com sucesso!
</Alert>

// Alerta de aviso
<Alert variant="warning">
  Verifique os campos obrigatórios antes de continuar.
</Alert>

// Alerta de sucesso
<Alert variant="success" title="Sucesso!">
  Proposta criada e enviada ao cliente.
</Alert>

// Alerta de erro dismissível
<Alert
  variant="danger"
  title="Erro"
  dismissible
  onDismiss={() => setShowAlert(false)}
>
  Não foi possível salvar os dados.
</Alert>

Props:

  • variant: 'info' | 'warning' | 'success' | 'danger'
  • title: string
  • dismissible: boolean
  • onDismiss: Function

Layout Components

Container

Container responsivo com max-width padrão (1400px).

import { Container } from '@bencao/ui';

<Container>
  <h1>Minha Aplicação</h1>
  {/* Conteúdo */}
</Container>

// Sem padding lateral
<Container noPadding>
  {/* Conteúdo */}
</Container>

Divider

Linha divisória horizontal.

import { Divider } from '@bencao/ui';

// Divider simples
<Divider />

// Divider com texto
<Divider text="OU" />

// Divider mais escuro
<Divider weight="dark" />

Section

Seção com espaçamento padrão.

import { Section } from '@bencao/ui';

<Section title="Análise de Desempenho">
  {/* Conteúdo da seção */}
</Section>

🎨 Cores Disponíveis (Tailwind)

Cores Principais

bg-bencao-black      // #1a1a1a
bg-bencao-gray-dark  // #333333
bg-bencao-gray-medium // #666666
bg-bencao-gray-light // #e5e5e5
bg-bencao-bg-main    // #fafafa (background padrão)
bg-bencao-bg-card    // #ffffff (background de cards)
bg-bencao-bg-alt     // #f8f9fa (background alternativo)

Cores de Status

text-status-negociacao  // #8b5a87 (roxo acinzentado)
text-status-aguardando  // #4a7c8c (azul esverdeado)
text-status-faturado    // #6b8f71 (verde oliva)
text-status-perdida     // #a0725c (terracota)
text-status-standby     // #7a7a7a (cinza médio)
text-status-anulada     // #999999 (cinza claro)

Cores de Eficiência

text-efficiency-excellent // #27ae60
text-efficiency-good      // #2ecc71
text-efficiency-average   // #f39c12
text-efficiency-poor      // #e74c3c

📐 Tamanhos de Texto (Tailwind)

text-h1        // 2.25rem (36px)
text-h2        // 1.25rem (20px)
text-h3        // 1rem (16px)
text-body      // 1rem
text-subtitle  // 1.1rem
text-label     // 0.875rem (14px)
text-small     // 0.75rem (12px)

📏 Espaçamentos (Tailwind)

p-section   // 32px
p-card      // 24px
p-header    // 32px
p-element   // 16px
p-related   // 20px

🎯 Exemplo de Aplicação Completa

import React, { useState } from 'react';
import {
  Container,
  Section,
  BrandTag,
  Card,
  Button,
  Input,
  MetricCard,
  Table,
  StatusBadge,
  Alert
} from '@odd-prototype/ui';

function App() {
  const [showAlert, setShowAlert] = useState(true);
  
  return (
    <Container>
      {/* Header */}
      <Section>
        <BrandTag.Logo
          title="Sistema de Propostas"
          subtitle="Gestão Comercial"
        />
      </Section>
      
      {/* Alert */}
      {showAlert && (
        <Alert
          variant="success"
          dismissible
          onDismiss={() => setShowAlert(false)}
        >
          Bem-vinda ao sistema!
        </Alert>
      )}
      
      {/* Métricas */}
      <Section title="Dashboard">
        <MetricCard.Grid columns={4}>
          <MetricCard value="45" label="Propostas" />
          <MetricCard value="R$ 2.3M" label="Valor Total" />
          <MetricCard
            value="76"
            suffix="%"
            label="Taxa de Sucesso"
            variant="excellent"
          />
          <MetricCard value="12" label="Em Aberto" />
        </MetricCard.Grid>
      </Section>
      
      {/* Formulário */}
      <Section title="Nova Proposta">
        <Card>
          <div className="grid grid-cols-2 gap-4">
            <Input
              label="Nome do Cliente"
              placeholder="Digite o nome..."
            />
            <Input.Select
              label="Status"
              options={[
                { value: 'negociacao', label: 'Em Negociação' },
                { value: 'faturado', label: 'Faturado' }
              ]}
            />
          </div>
          
          <div className="mt-4">
            <Input.Textarea
              label="Descrição"
              rows={4}
            />
          </div>
          
          <div className="mt-6 flex gap-3">
            <Button>Salvar</Button>
            <Button variant="secondary">Cancelar</Button>
          </div>
        </Card>
      </Section>
      
      {/* Tabela */}
      <Section title="Propostas Recentes">
        <Card noPadding>
          <Table>
            <Table.Header>
              <Table.Row>
                <Table.HeaderCell>Cliente</Table.HeaderCell>
                <Table.HeaderCell align="right">Valor</Table.HeaderCell>
                <Table.HeaderCell>Status</Table.HeaderCell>
              </Table.Row>
            </Table.Header>
            <Table.Body>
              <Table.Row>
                <Table.Cell>Empresa ABC</Table.Cell>
                <Table.Cell align="right" numeric>
                  R$ 50.000
                </Table.Cell>
                <Table.Cell>
                  <StatusBadge status="negociacao" />
                </Table.Cell>
              </Table.Row>
            </Table.Body>
          </Table>
        </Card>
      </Section>
    </Container>
  );
}

export default App;

🎨 Filosofia de Design

A biblioteca Odd Prototype UI segue princípios de design minimalista e profissional:

  • Tipografia limpa: Uso da fonte Inter para interface clara e legível
  • Cores sofisticadas: Paleta dessaturada e profissional
  • Espaçamento generoso: Respiração visual adequada
  • Sombras sutis: Apenas o necessário para profundidade
  • Transições suaves: Interações fluidas de 200ms
  • Uppercase estratégico: Labels e títulos em maiúsculas para hierarquia

📄 Licença

MIT © Odd Prototype Team


🤝 Contribuindo

Contribuições são bem-vindas! Por favor, abra uma issue ou pull request.


Desenvolvido com ❤️ pela equipe Odd Prototype