Initial commit
This commit is contained in:
+893
@@ -0,0 +1,893 @@
|
||||
# Padrões de Estilo - Course Platform
|
||||
|
||||
Este documento define os padrões de estilo unificados para todo o sistema, garantindo consistência visual e facilidade de manutenção.
|
||||
|
||||
## Índice
|
||||
|
||||
- [Princípios Fundamentais](#princípios-fundamentais)
|
||||
- [Cores e Tema](#cores-e-tema)
|
||||
- [Tipografia](#tipografia)
|
||||
- [Espaçamento](#espaçamento)
|
||||
- [Badges e Labels](#badges-e-labels)
|
||||
- [Componentes](#componentes)
|
||||
- [Transições e Animações](#transições-e-animações)
|
||||
- [Regras CSS Globais](#regras-css-globais)
|
||||
|
||||
---
|
||||
|
||||
## Princípios Fundamentais
|
||||
|
||||
1. **Usar CSS Variables** para cores, backgrounds e bordas (definidas em `:root` e `.dark`)
|
||||
2. **Padronizar em `neutral-*`** em vez de `gray-*` para consistência
|
||||
3. **Usar `blue-600`** como cor primária para botões de ação principal
|
||||
4. **Manter border-radius de 8px** (`rounded-lg` ou `rounded-xl`)
|
||||
5. **Usar sombras sutis**: `shadow-sm` padrão, `shadow-md` no hover
|
||||
6. **Evitar regras CSS globais com `!important`** que sobrescrevem classes Tailwind
|
||||
|
||||
---
|
||||
|
||||
## Cores e Tema
|
||||
|
||||
### CSS Variables (Definidas em `globals.css`)
|
||||
|
||||
```css
|
||||
/* Tema Claro (:root) */
|
||||
--background: #ffffff;
|
||||
--foreground: #09090b;
|
||||
--card: #ffffff;
|
||||
--card-foreground: #09090b;
|
||||
--primary: #18181b;
|
||||
--primary-foreground: #fafafa;
|
||||
--secondary: #f4f4f5;
|
||||
--secondary-foreground: #18181b;
|
||||
--muted: #f4f4f5;
|
||||
--muted-foreground: #71717a;
|
||||
--accent: #f4f4f5;
|
||||
--accent-foreground: #18181b;
|
||||
--destructive: #ef4444;
|
||||
--destructive-foreground: #fafafa;
|
||||
--border: #e4e4e7;
|
||||
--input: #e4e4e7;
|
||||
--ring: #18181b;
|
||||
--radius: 0.5rem;
|
||||
|
||||
/* Tema Escuro (.dark) */
|
||||
--background: #09090b;
|
||||
--foreground: #fafafa;
|
||||
--card: #09090b;
|
||||
--card-foreground: #fafafa;
|
||||
--primary: #fafafa;
|
||||
--primary-foreground: #18181b;
|
||||
--secondary: #27272a;
|
||||
--secondary-foreground: #fafafa;
|
||||
--muted: #27272a;
|
||||
--muted-foreground: #a1a1aa;
|
||||
--accent: #27272a;
|
||||
--accent-foreground: #fafafa;
|
||||
--destructive: #7f1d1d;
|
||||
--destructive-foreground: #fafafa;
|
||||
--border: #27272a;
|
||||
--input: #27272a;
|
||||
--ring: #d4d4d8;
|
||||
```
|
||||
|
||||
### Cores Semânticas (Tailwind)
|
||||
|
||||
| Propósito | Light Mode | Dark Mode |
|
||||
|-----------|------------|-----------|
|
||||
| Primary (Ação principal) | `blue-600` | `blue-500` |
|
||||
| Primary Hover | `blue-700` | `blue-600` |
|
||||
| Success | `green-600` | `green-500` |
|
||||
| Success Hover | `green-700` | `green-600` |
|
||||
| Warning | `yellow-500` | `yellow-400` |
|
||||
| Warning Hover | `yellow-600` | `yellow-500` |
|
||||
| Error/Destructive | `red-600` | `red-500` |
|
||||
| Error Hover | `red-700` | `red-600` |
|
||||
| Info | `blue-600` | `blue-500` |
|
||||
|
||||
### Cores Neutras (Padrão)
|
||||
|
||||
**Use sempre `neutral-*` em vez de `gray-*` para consistência:**
|
||||
|
||||
| Escala | Light Mode | Dark Mode |
|
||||
|--------|------------|-----------|
|
||||
| 50 | `#fafafa` | `#18181b` |
|
||||
| 100 | `#f5f5f5` | `#27272a` |
|
||||
| 200 | `#e5e5e5` | `#3f3f46` |
|
||||
| 300 | `#d4d4d4` | `#52525b` |
|
||||
| 400 | `#a3a3a3` | `#71717a` |
|
||||
| 500 | `#737373` | `#a1a1aa` |
|
||||
| 600 | `#525252` | `#d4d4d8` |
|
||||
| 700 | `#404040` | `#e4e4e7` |
|
||||
| 800 | `#262626` | `#f4f4f5` |
|
||||
| 900 | `#171717` | `#fafafa` |
|
||||
| 950 | `#0a0a0a` | `#fafafa` |
|
||||
|
||||
---
|
||||
|
||||
## Tipografia
|
||||
|
||||
### Fonte
|
||||
|
||||
- **Fonte Principal**: Geist Sans (Google Fonts)
|
||||
- **Fonte Monospace**: Geist Mono (Google Fonts)
|
||||
|
||||
### Tamanhos e Pesos
|
||||
|
||||
| Elemento | Classe Tailwind | Uso |
|
||||
|----------|-----------------|-----|
|
||||
| Título Principal | `text-2xl md:text-3xl font-semibold` | Títulos de página |
|
||||
| Título de Seção | `text-lg font-semibold` | Títulos de seção |
|
||||
| Subtítulo | `text-base font-medium` | Subtítulos |
|
||||
| Texto Normal | `text-sm` | Texto de conteúdo |
|
||||
| Texto Secundário | `text-sm text-muted-foreground` | Texto de apoio |
|
||||
| Label | `text-sm font-medium` | Labels de formulário |
|
||||
| Caption/Small | `text-xs` | Textos pequenos |
|
||||
|
||||
### Exemplos
|
||||
|
||||
```jsx
|
||||
// Título de Página
|
||||
<h1 className="text-2xl md:text-3xl font-semibold text-foreground">
|
||||
Título da Página
|
||||
</h1>
|
||||
|
||||
// Título de Seção
|
||||
<h2 className="text-lg font-semibold text-foreground">
|
||||
Título da Seção
|
||||
</h2>
|
||||
|
||||
// Subtítulo
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Descrição ou subtítulo
|
||||
</p>
|
||||
|
||||
// Label
|
||||
<label className="text-sm font-medium leading-none">
|
||||
Nome do Campo
|
||||
</label>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Espaçamento
|
||||
|
||||
### Padrões de Padding
|
||||
|
||||
| Elemento | Padding/Margin |
|
||||
|----------|----------------|
|
||||
| Card padding | `p-5` |
|
||||
| Card padding (compacto) | `p-4` |
|
||||
| Button padding | `px-4 py-2` |
|
||||
| Input padding | `px-3 py-2` |
|
||||
| Table cell padding | `px-6 py-4` |
|
||||
| Section gap | `gap-3` ou `gap-4` |
|
||||
| Vertical spacing entre elementos | `space-y-4` |
|
||||
| Horizontal spacing entre elementos | `space-x-3` |
|
||||
|
||||
### Exemplos
|
||||
|
||||
```jsx
|
||||
// Card
|
||||
<div className="border rounded-xl p-5 shadow-sm bg-card">
|
||||
{/* conteúdo */}
|
||||
</div>
|
||||
|
||||
// Formulário com espaçamento vertical
|
||||
<form className="space-y-4">
|
||||
{/* campos */}
|
||||
</form>
|
||||
|
||||
// Botões com espaçamento horizontal
|
||||
<div className="flex gap-3">
|
||||
<button>Cancelar</button>
|
||||
<button>Salvar</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Badges e Labels
|
||||
|
||||
Badges são pequenos labels coloridos usados para indicar status, categorias ou outros metadados. Devem ser usados consistentemente em toda a aplicação.
|
||||
|
||||
### Estrutura Base
|
||||
|
||||
```jsx
|
||||
<span className="text-xs px-2 py-1 rounded-full border [badge-classes]">
|
||||
Label Text
|
||||
</span>
|
||||
```
|
||||
|
||||
### Padrões de Cores
|
||||
|
||||
#### Success/Green (Disponível, Pago, Ativo, Presente)
|
||||
|
||||
**Tema Claro:** `bg-emerald-100 text-emerald-700 border-emerald-200`
|
||||
**Tema Escuro:** `dark:bg-emerald-900/20 dark:text-emerald-300 dark:border-emerald-800`
|
||||
|
||||
```jsx
|
||||
<span className="text-xs px-2 py-1 rounded-full border bg-emerald-100 text-emerald-700 border-emerald-200 dark:bg-emerald-900/20 dark:text-emerald-300 dark:border-emerald-800">
|
||||
Disponível
|
||||
</span>
|
||||
```
|
||||
|
||||
**Casos de Uso:**
|
||||
- "Disponível" (Available)
|
||||
- "Pago" (Paid)
|
||||
- "Ativa" (Active)
|
||||
- "Presente" (Present)
|
||||
- Status "Verified"
|
||||
|
||||
---
|
||||
|
||||
#### Info/Blue (Em breve, Aguardando Verificação, Justificado)
|
||||
|
||||
**Tema Claro:** `bg-blue-100 text-blue-700 border-blue-200`
|
||||
**Tema Escuro:** `dark:bg-blue-900/20 dark:text-blue-300 dark:border-blue-800`
|
||||
|
||||
```jsx
|
||||
<span className="text-xs px-2 py-1 rounded-full border bg-blue-100 text-blue-700 border-blue-200 dark:bg-blue-900/20 dark:text-blue-300 dark:border-blue-800">
|
||||
Em breve
|
||||
</span>
|
||||
```
|
||||
|
||||
**Casos de Uso:**
|
||||
- "Em breve" (Upcoming)
|
||||
- "Aguardando Verificação" (Pending Verification)
|
||||
- "Justificado" (Excused)
|
||||
- Templates "Public"
|
||||
|
||||
---
|
||||
|
||||
#### Danger/Red (Encerrada, Rejeitado, Ausente)
|
||||
|
||||
**Tema Claro:** `bg-red-100 text-red-700 border-red-200`
|
||||
**Tema Escuro:** `dark:bg-red-900/20 dark:text-red-300 dark:border-red-800`
|
||||
|
||||
```jsx
|
||||
<span className="text-xs px-2 py-1 rounded-full border bg-red-100 text-red-700 border-red-200 dark:bg-red-900/20 dark:text-red-300 dark:border-red-800">
|
||||
Encerrada
|
||||
</span>
|
||||
```
|
||||
|
||||
**Casos de Uso:**
|
||||
- "Encerrada" (Expired)
|
||||
- "Rejeitado" (Rejected)
|
||||
- "Ausente" (Absent)
|
||||
- Status "Rejected"
|
||||
|
||||
---
|
||||
|
||||
#### Warning/Amber (Aguardando Pagamento, Atrasado, Arquivada)
|
||||
|
||||
**Tema Claro:** `bg-amber-100 text-amber-700 border-amber-200`
|
||||
**Tema Escuro:** `dark:bg-amber-900/20 dark:text-amber-300 dark:border-amber-800`
|
||||
|
||||
```jsx
|
||||
<span className="text-xs px-2 py-1 rounded-full border bg-amber-100 text-amber-700 border-amber-200 dark:bg-amber-900/20 dark:text-amber-300 dark:border-amber-800">
|
||||
Aguardando Pagamento
|
||||
</span>
|
||||
```
|
||||
|
||||
**Casos de Uso:**
|
||||
- "Aguardando Pagamento" (Pending Payment)
|
||||
- "Atrasado" (Late)
|
||||
- "Arquivada" (Archived)
|
||||
- Status "Pending"
|
||||
|
||||
---
|
||||
|
||||
#### Warning/Yellow (Obrigações)
|
||||
|
||||
**Tema Claro:** `bg-yellow-100 text-yellow-800 border-yellow-300`
|
||||
**Tema Escuro:** `dark:bg-yellow-900/50 dark:text-yellow-200 dark:border-yellow-700`
|
||||
|
||||
```jsx
|
||||
<span className="text-xs px-2 py-1 rounded-full border bg-yellow-100 text-yellow-800 border-yellow-300 dark:bg-yellow-900/50 dark:text-yellow-200 dark:border-yellow-700">
|
||||
Obrigação
|
||||
</span>
|
||||
```
|
||||
|
||||
**Casos de Uso:**
|
||||
- Obrigações de pagamento
|
||||
- "Obrigação" (Obligation)
|
||||
|
||||
---
|
||||
|
||||
#### Purple (Leitura)
|
||||
|
||||
**Tema Claro:** `bg-purple-100 text-purple-700 border-purple-200`
|
||||
**Tema Escuro:** `dark:bg-purple-900/20 dark:text-purple-300 dark:border-purple-800`
|
||||
|
||||
```jsx
|
||||
<span className="text-xs px-2 py-1 rounded-full border bg-purple-100 text-purple-700 border-purple-200 dark:bg-purple-900/20 dark:text-purple-300 dark:border-purple-800">
|
||||
Leitura
|
||||
</span>
|
||||
```
|
||||
|
||||
**Casos de Uso:**
|
||||
- "Leitura" (Reading)
|
||||
- Categoria "Indigo"
|
||||
|
||||
---
|
||||
|
||||
#### Indigo (Trabalhos)
|
||||
|
||||
**Tema Claro:** `bg-indigo-100 text-indigo-700 border-indigo-200`
|
||||
**Tema Escuro:** `dark:bg-indigo-900/20 dark:text-indigo-300 dark:border-indigo-800`
|
||||
|
||||
```jsx
|
||||
<span className="text-xs px-2 py-1 rounded-full border bg-indigo-100 text-indigo-700 border-indigo-200 dark:bg-indigo-900/20 dark:text-indigo-300 dark:border-indigo-800">
|
||||
Trabalhos
|
||||
</span>
|
||||
```
|
||||
|
||||
**Casos de Uso:**
|
||||
- "Trabalhos" (Homework)
|
||||
- Itens relacionados a assignments
|
||||
|
||||
---
|
||||
|
||||
#### Neutral/Gray (Outros, Padrão)
|
||||
|
||||
**Tema Claro:** `bg-gray-100 text-gray-700 border-gray-200`
|
||||
**Tema Escuro:** `dark:bg-gray-800 dark:text-gray-300 dark:border-gray-700`
|
||||
|
||||
```jsx
|
||||
<span className="text-xs px-2 py-1 rounded-full border bg-gray-100 text-gray-700 border-gray-200 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-700">
|
||||
Outros
|
||||
</span>
|
||||
```
|
||||
|
||||
**Casos de Uso:**
|
||||
- "Outros" (Other)
|
||||
- Categorias padrão/desconhecidas
|
||||
- Status neutro
|
||||
|
||||
### Badges por Categoria
|
||||
|
||||
#### Categorias de Arquivos
|
||||
|
||||
| Categoria | Cor |
|
||||
|-----------|-----|
|
||||
| Slides | Blue |
|
||||
| Exercícios | Green |
|
||||
| Leitura | Purple |
|
||||
| Vídeos | Red |
|
||||
| Áudio | Yellow |
|
||||
| Trabalhos | Indigo |
|
||||
| Outros | Gray |
|
||||
|
||||
#### Status de Presença
|
||||
|
||||
| Status | Cor |
|
||||
|--------|-----|
|
||||
| Presente | Green |
|
||||
| Ausente | Red |
|
||||
| Atrasado | Amber |
|
||||
| Justificado | Blue |
|
||||
|
||||
#### Status de Pagamento
|
||||
|
||||
| Status | Cor |
|
||||
|--------|-----|
|
||||
| Pago | Green |
|
||||
| Aguardando Verificação | Blue |
|
||||
| Rejeitado | Red |
|
||||
| Aguardando Pagamento | Amber |
|
||||
| Obrigação | Yellow |
|
||||
|
||||
#### Status de Provas
|
||||
|
||||
| Status | Cor |
|
||||
|--------|-----|
|
||||
| Disponível | Green |
|
||||
| Em breve | Blue |
|
||||
| Encerrada | Red |
|
||||
|
||||
#### Status de Turma
|
||||
|
||||
| Status | Cor |
|
||||
|--------|-----|
|
||||
| Ativa | Green |
|
||||
| Arquivada | Amber |
|
||||
|
||||
### Exemplo de Implementação
|
||||
|
||||
```jsx
|
||||
const categoryColors = {
|
||||
'Slides': 'text-xs px-2 py-1 rounded-full border bg-blue-100 text-blue-700 border-blue-200 dark:bg-blue-900/20 dark:text-blue-300 dark:border-blue-800',
|
||||
'Exercícios': 'text-xs px-2 py-1 rounded-full border bg-green-100 text-green-700 border-green-200 dark:bg-green-900/20 dark:text-green-300 dark:border-green-800',
|
||||
'Leitura': 'text-xs px-2 py-1 rounded-full border bg-purple-100 text-purple-700 border-purple-200 dark:bg-purple-900/20 dark:text-purple-300 dark:border-purple-800',
|
||||
'Vídeos': 'text-xs px-2 py-1 rounded-full border bg-red-100 text-red-700 border-red-200 dark:bg-red-900/20 dark:text-red-300 dark:border-red-800',
|
||||
'Áudio': 'text-xs px-2 py-1 rounded-full border bg-yellow-100 text-yellow-700 border-yellow-200 dark:bg-yellow-900/20 dark:text-yellow-300 dark:border-yellow-800',
|
||||
'Trabalhos': 'text-xs px-2 py-1 rounded-full border bg-indigo-100 text-indigo-700 border-indigo-200 dark:bg-indigo-900/20 dark:text-indigo-300 dark:border-indigo-800',
|
||||
'Outros': 'text-xs px-2 py-1 rounded-full border bg-gray-100 text-gray-700 border-gray-200 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-700'
|
||||
};
|
||||
|
||||
<span className={categoryColors[category] || categoryColors['Outros']}>
|
||||
{category}
|
||||
</span>
|
||||
```
|
||||
|
||||
### Notas Importantes
|
||||
|
||||
1. **Consistência**: Sempre use a string de classes completa incluindo variantes de tema claro e escuro
|
||||
2. **Acessibilidade**: As combinações de cores fornecem contraste suficiente para ambos os temas
|
||||
3. **Opacidade**: O tema escuro usa `/20` de opacidade para a maioria das cores (exceto yellow que usa `/50`)
|
||||
4. **Borda**: Sempre inclua borda para melhor separação visual
|
||||
5. **Arredondamento**: Use `rounded-full` para badges em formato de pílula
|
||||
6. **Tamanho**: Use `text-xs` para badges pequenos, `text-sm` para badges maiores se necessário
|
||||
|
||||
---
|
||||
|
||||
## Componentes
|
||||
|
||||
### Cards
|
||||
|
||||
**Padrão Unificado:**
|
||||
|
||||
```jsx
|
||||
<div className="border rounded-xl p-5 shadow-sm bg-card dark:bg-card dark:border-border hover:shadow-md hover:border-neutral-300 dark:hover:border-neutral-700 transition-all">
|
||||
{/* conteúdo */}
|
||||
</div>
|
||||
```
|
||||
|
||||
**Card com Link:**
|
||||
|
||||
```jsx
|
||||
<Link href="/path" className="block no-underline">
|
||||
<div className="border rounded-xl p-5 shadow-sm bg-card hover:shadow-md transition-all">
|
||||
{/* conteúdo */}
|
||||
</div>
|
||||
</Link>
|
||||
```
|
||||
|
||||
### Botões
|
||||
|
||||
**Primary (Ação Principal):**
|
||||
|
||||
```jsx
|
||||
<button
|
||||
type="submit"
|
||||
className="inline-flex items-center justify-center whitespace-nowrap rounded-lg text-sm font-medium bg-blue-600 hover:bg-blue-700 text-white h-10 px-4 py-2 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
|
||||
>
|
||||
Salvar
|
||||
</button>
|
||||
```
|
||||
|
||||
**Secondary (Ação Secundária):**
|
||||
|
||||
```jsx
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center whitespace-nowrap rounded-lg text-sm font-medium border border-input bg-background hover:bg-accent hover:text-accent-foreground h-10 px-4 py-2 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
|
||||
>
|
||||
Cancelar
|
||||
</button>
|
||||
```
|
||||
|
||||
**Destructive (Ação de Exclusão):**
|
||||
|
||||
```jsx
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center whitespace-nowrap rounded-lg text-sm font-medium bg-red-600 hover:bg-red-700 text-white h-10 px-4 py-2 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
|
||||
>
|
||||
Excluir
|
||||
</button>
|
||||
```
|
||||
|
||||
**Botão com Ícone:**
|
||||
|
||||
```jsx
|
||||
<button className="inline-flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium shadow-sm hover:shadow transition-shadow">
|
||||
<Icon className="w-4 h-4" />
|
||||
<span>Texto do Botão</span>
|
||||
</button>
|
||||
```
|
||||
|
||||
### Inputs
|
||||
|
||||
**Input de Texto:**
|
||||
|
||||
```jsx
|
||||
<input
|
||||
type="text"
|
||||
className="flex h-10 w-full rounded-lg border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
placeholder="Digite aqui..."
|
||||
/>
|
||||
```
|
||||
|
||||
**Select:**
|
||||
|
||||
```jsx
|
||||
<div className="relative">
|
||||
<select
|
||||
className="flex h-10 w-full rounded-lg border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 appearance-none"
|
||||
>
|
||||
<option value="">Selecione...</option>
|
||||
{/* opções */}
|
||||
</select>
|
||||
<svg className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 h-5 w-5 text-muted-foreground">
|
||||
{/* ícone de seta */}
|
||||
</svg>
|
||||
</div>
|
||||
```
|
||||
|
||||
**Textarea:**
|
||||
|
||||
```jsx
|
||||
<textarea
|
||||
className="flex min-h-[80px] w-full rounded-lg border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
placeholder="Digite sua mensagem..."
|
||||
rows={4}
|
||||
/>
|
||||
```
|
||||
|
||||
### Tabelas
|
||||
|
||||
**Tabela Padrão:**
|
||||
|
||||
```jsx
|
||||
<div className="w-full overflow-x-auto rounded-xl border border-border bg-card shadow-sm">
|
||||
<table className="w-full text-sm text-left">
|
||||
<thead className="bg-muted text-muted-foreground font-semibold uppercase text-xs">
|
||||
<tr>
|
||||
<th className="px-6 py-4 border-b border-border">Coluna 1</th>
|
||||
<th className="px-6 py-4 border-b border-border">Coluna 2</th>
|
||||
<th className="px-6 py-4 border-b border-border text-right">Ações</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-border">
|
||||
<tr className="hover:bg-accent transition-colors">
|
||||
<td className="px-6 py-4 text-foreground">Valor 1</td>
|
||||
<td className="px-6 py-4 text-foreground">Valor 2</td>
|
||||
<td className="px-6 py-4 text-right">
|
||||
{/* ações */}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Badges
|
||||
|
||||
**Status Badges:**
|
||||
|
||||
```jsx
|
||||
// Success (Pago)
|
||||
<span className="px-2 py-1 rounded-full text-xs font-medium border bg-green-100 dark:bg-green-900/50 text-green-800 dark:text-green-200 border-green-300 dark:border-green-700">
|
||||
Pago
|
||||
</span>
|
||||
|
||||
// Warning (Pendente)
|
||||
<span className="px-2 py-1 rounded-full text-xs font-medium border bg-yellow-100 dark:bg-yellow-900/50 text-yellow-800 dark:text-yellow-200 border-yellow-300 dark:border-yellow-700">
|
||||
Pendente
|
||||
</span>
|
||||
|
||||
// Error (Rejeitado)
|
||||
<span className="px-2 py-1 rounded-full text-xs font-medium border bg-red-100 dark:bg-red-900/50 text-red-800 dark:text-red-200 border-red-300 dark:border-red-700">
|
||||
Rejeitado
|
||||
</span>
|
||||
|
||||
// Info (Aguardando Verificação)
|
||||
<span className="px-2 py-1 rounded-full text-xs font-medium border bg-blue-100 dark:bg-blue-900/50 text-blue-800 dark:text-blue-200 border-blue-300 dark:border-blue-700">
|
||||
Aguardando Verificação
|
||||
</span>
|
||||
|
||||
// Neutral (Não Pago)
|
||||
<span className="px-2 py-1 rounded-full text-xs font-medium border bg-neutral-100 dark:bg-neutral-700 text-neutral-800 dark:text-neutral-200 border-neutral-300 dark:border-neutral-600">
|
||||
Não Pago
|
||||
</span>
|
||||
```
|
||||
|
||||
### Flash Messages
|
||||
|
||||
```jsx
|
||||
// Success
|
||||
<div className="px-4 py-3 rounded relative mb-4 text-green-700 dark:text-green-300 bg-green-100 dark:bg-green-900/50 border border-green-400 dark:border-green-700">
|
||||
<div className="flex items-center">
|
||||
<strong className="font-bold mr-1">Sucesso:</strong>
|
||||
<span className="block sm:inline">Mensagem de sucesso</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
// Error
|
||||
<div className="px-4 py-3 rounded relative mb-4 text-red-700 dark:text-red-300 bg-red-100 dark:bg-red-900/50 border border-red-400 dark:border-red-700">
|
||||
<div className="flex items-center">
|
||||
<strong className="font-bold mr-1">Erro:</strong>
|
||||
<span className="block sm:inline">Mensagem de erro</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
// Warning
|
||||
<div className="px-4 py-3 rounded relative mb-4 text-yellow-700 dark:text-yellow-300 bg-yellow-100 dark:bg-yellow-900/50 border border-yellow-400 dark:border-yellow-700">
|
||||
<div className="flex items-center">
|
||||
<strong className="font-bold mr-1">Aviso:</strong>
|
||||
<span className="block sm:inline">Mensagem de aviso</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
// Info
|
||||
<div className="px-4 py-3 rounded relative mb-4 text-blue-700 dark:text-blue-300 bg-blue-100 dark:bg-blue-900/50 border border-blue-400 dark:border-blue-700">
|
||||
<div className="flex items-center">
|
||||
<strong className="font-bold mr-1">Info:</strong>
|
||||
<span className="block sm:inline">Mensagem informativa</span>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Sidebar Navigation
|
||||
|
||||
```jsx
|
||||
<aside className="w-64 flex-shrink-0 border-r border-neutral-200 dark:border-neutral-800 p-4 bg-white dark:bg-neutral-950">
|
||||
<nav className="mt-2">
|
||||
<ul className="space-y-1">
|
||||
{/* itens de navegação */}
|
||||
</ul>
|
||||
</nav>
|
||||
</aside>
|
||||
```
|
||||
|
||||
### Stats Cards
|
||||
|
||||
```jsx
|
||||
<div className="rounded-lg border border-neutral-200 dark:border-neutral-800 p-3 bg-neutral-50 dark:bg-neutral-800/40">
|
||||
<p className="text-xs text-neutral-700 dark:text-neutral-300 font-medium">Label</p>
|
||||
<p className="mt-1 text-lg font-semibold text-neutral-900 dark:text-neutral-100">Valor</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Transições e Animações
|
||||
|
||||
### Padrões de Transição
|
||||
|
||||
```jsx
|
||||
// Transição suave para todas as propriedades
|
||||
className="transition-all duration-200"
|
||||
|
||||
// Transição apenas para cores
|
||||
className="transition-colors"
|
||||
|
||||
// Transição para sombra
|
||||
className="transition-shadow"
|
||||
|
||||
// Transição para transformações
|
||||
className="transition-transform"
|
||||
```
|
||||
|
||||
### Hover Effects
|
||||
|
||||
```jsx
|
||||
// Card hover
|
||||
<div className="hover:shadow-md hover:border-neutral-300 dark:hover:border-neutral-700 transition-all">
|
||||
|
||||
// Button hover
|
||||
<button className="hover:bg-blue-700 transition-colors">
|
||||
|
||||
// Link hover
|
||||
<a className="hover:text-blue-600 transition-colors">
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Regras CSS Globais
|
||||
|
||||
### Importante: Evitar `!important` em regras globais
|
||||
|
||||
**NÃO FAÇA:**
|
||||
|
||||
```css
|
||||
button[type="submit"] {
|
||||
background-color: var(--primary) !important;
|
||||
color: var(--primary-foreground) !important;
|
||||
}
|
||||
```
|
||||
|
||||
Isso sobrescreve todas as classes Tailwind e causa problemas de manutenção.
|
||||
|
||||
**FAÇA:**
|
||||
|
||||
Deixe cada componente definir seu próprio estilo usando classes Tailwind ou CSS variables sem `!important`.
|
||||
|
||||
### Estilos Base (Definidos em `globals.css`)
|
||||
|
||||
```css
|
||||
/* Form elements */
|
||||
input, select, textarea {
|
||||
border: 1px solid var(--input);
|
||||
background-color: var(--background);
|
||||
border-radius: var(--radius);
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--foreground);
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
input:focus, select:focus, textarea:focus {
|
||||
outline: none;
|
||||
border-color: var(--ring);
|
||||
box-shadow: 0 0 0 2px var(--background), 0 0 0 4px var(--ring);
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
thead {
|
||||
background-color: var(--muted);
|
||||
}
|
||||
|
||||
tbody tr {
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
tbody tr:hover {
|
||||
background-color: var(--accent);
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
font-weight: 500;
|
||||
color: var(--muted-foreground);
|
||||
padding: 0.75rem 1rem;
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 1rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Cards */
|
||||
.card {
|
||||
background-color: var(--card);
|
||||
color: var(--card-foreground);
|
||||
border-radius: var(--radius);
|
||||
border: 1px solid var(--border);
|
||||
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
|
||||
}
|
||||
|
||||
/* Badges */
|
||||
.badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
border-radius: 9999px;
|
||||
padding: 0.125rem 0.625rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Links */
|
||||
a {
|
||||
color: var(--primary);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus,
|
||||
a:active {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Checklist de Implementação
|
||||
|
||||
Ao criar ou modificar componentes, verifique:
|
||||
|
||||
- [ ] Usar CSS variables (`bg-card`, `text-foreground`, `border-border`)
|
||||
- [ ] Usar `neutral-*` em vez de `gray-*`
|
||||
- [ ] Usar `blue-600` para botões primary
|
||||
- [ ] Usar `rounded-lg` ou `rounded-xl` para border-radius
|
||||
- [ ] Adicionar `transition-colors` ou `transition-all` para elementos interativos
|
||||
- [ ] Testar em tema claro e escuro
|
||||
- [ ] Verificar contraste de cores
|
||||
- [ ] Usar classes Tailwind em vez de CSS customizado quando possível
|
||||
- [ ] Evitar `!important` em regras CSS
|
||||
|
||||
---
|
||||
|
||||
## Exemplos de Componentes Completos
|
||||
|
||||
### Formulário Padrão
|
||||
|
||||
```jsx
|
||||
function StandardForm({ onSubmit, onCancel }) {
|
||||
return (
|
||||
<form onSubmit={onSubmit} className="bg-card text-card-foreground rounded-xl border shadow-sm p-6 max-w-lg mx-auto space-y-4">
|
||||
<div className="space-y-2">
|
||||
<label htmlFor="name" className="text-sm font-medium leading-none">
|
||||
Nome
|
||||
</label>
|
||||
<input
|
||||
id="name"
|
||||
name="name"
|
||||
className="flex h-10 w-full rounded-lg border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
||||
placeholder="Digite o nome"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<label htmlFor="email" className="text-sm font-medium leading-none">
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
type="email"
|
||||
className="flex h-10 w-full rounded-lg border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
||||
placeholder="Digite o email"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-3 mt-6">
|
||||
<button
|
||||
type="submit"
|
||||
className="inline-flex items-center justify-center whitespace-nowrap rounded-lg text-sm font-medium bg-blue-600 hover:bg-blue-700 text-white h-10 px-4 py-2 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 flex-1"
|
||||
>
|
||||
Salvar
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onCancel}
|
||||
className="inline-flex items-center justify-center whitespace-nowrap rounded-lg text-sm font-medium border border-input bg-background hover:bg-accent hover:text-accent-foreground h-10 px-4 py-2 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 flex-1"
|
||||
>
|
||||
Cancelar
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Card de Dashboard
|
||||
|
||||
```jsx
|
||||
function DashboardCard({ title, description, buttonText, link, icon: Icon }) {
|
||||
return (
|
||||
<Link href={link} className="block no-underline">
|
||||
<div className="h-full border rounded-xl p-5 shadow-sm bg-card dark:bg-card dark:border-border hover:shadow-md hover:border-neutral-300 dark:hover:border-neutral-700 transition-all">
|
||||
<div className="flex items-start gap-4">
|
||||
{Icon && (
|
||||
<div className="p-2.5 rounded-lg bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300">
|
||||
<Icon className="w-5 h-5" />
|
||||
</div>
|
||||
)}
|
||||
<div className="flex-1">
|
||||
<h3 className="text-lg font-semibold text-foreground mb-2">{title}</h3>
|
||||
<p className="text-sm text-muted-foreground mb-4">{description}</p>
|
||||
<span className="inline-flex justify-center text-white text-sm font-medium py-2 px-6 rounded-lg transition-colors bg-blue-600 hover:bg-blue-700">
|
||||
{buttonText}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Conclusão
|
||||
|
||||
Seguir estes padrões garantirá:
|
||||
|
||||
✅ **Consistência visual** em todo o sistema
|
||||
✅ **Manutenção mais fácil** com código previsível
|
||||
✅ **Melhor suporte** a tema claro/escuro
|
||||
✅ **Código mais limpo** e organizado
|
||||
✅ **Experiência do usuário** mais coesa
|
||||
|
||||
Para dúvidas ou sugestões de melhoria, consulte a equipe de desenvolvimento.
|
||||
Reference in New Issue
Block a user