- Setup NestJS with TypeScript, ConfigModule, JWT authentication - Implemented Auth Module with signup, login, logout endpoints - Created DTOs with validation (SignupDto, LoginDto) - JWT Strategy with Passport integration for token validation - JwtAuthGuard for route protection with Bearer tokens - CurrentUser decorator for dependency injection - Supabase integration for user management and auth - Complete API documentation (API.md) with all endpoints - Design System for Web (Next.js + Tailwind) and Mobile (Flutter) - Comprehensive project documentation and roadmap - Environment configuration with Joi schema validation - Ready for Tasks Module and RLS implementation
774 lines
19 KiB
Markdown
774 lines
19 KiB
Markdown
# 🎨 TASK MANAGER - Design System & Guia de Interface
|
||
|
||
## 🌈 Paleta de Cores
|
||
|
||
### Cores Principais
|
||
- **Primary (Azul)**: `#2563EB` - Ações principais, links, seleção
|
||
- **Primary Dark**: `#1D4ED8` - Estados hover/ativo
|
||
- **Primary Light**: `#DBEAFE` - Backgrounds, estados desabilitados
|
||
- **White**: `#FFFFFF` - Backgrounds principal
|
||
- **Black**: `#000000` - Texto principal, contrastes fortes
|
||
- **Gray 50**: `#F9FAFB` - Backgrounds secundários
|
||
- **Gray 100**: `#F3F4F6` - Borders leves
|
||
- **Gray 200**: `#E5E7EB` - Borders padrão
|
||
- **Gray 400**: `#9CA3AF` - Texto secundário, placeholders
|
||
- **Gray 600**: `#4B5563` - Texto terciário
|
||
|
||
### Cores de Status
|
||
- **Success**: `#10B981` - Tarefas concluídas
|
||
- **Warning**: `#F59E0B` - Alertas
|
||
- **Error**: `#EF4444` - Erros, deletar
|
||
- **Info**: `#06B6D4` - Informações
|
||
|
||
---
|
||
|
||
## 🔤 Tipografia (Google Fonts)
|
||
|
||
### Fonte Principal: **Inter**
|
||
- Link: https://fonts.google.com/specimen/Inter
|
||
- Uso: Corpo de texto, UI, labels
|
||
|
||
### Fonte Secundária: **Poppins**
|
||
- Link: https://fonts.google.com/specimen/Poppins
|
||
- Uso: Títulos, headings, destaque
|
||
|
||
### Escala Tipográfica
|
||
|
||
| Nome | Tamanho | Weight | Line Height | Letra-espaçamento | Uso |
|
||
|------|---------|--------|-------------|------------------|-----|
|
||
| **H1** | 32px | 700 (Bold) | 40px | -0.5px | Títulos principais |
|
||
| **H2** | 24px | 700 (Bold) | 32px | -0.3px | Subtítulos |
|
||
| **H3** | 18px | 600 (SemiBold) | 28px | -0.2px | Seções |
|
||
| **Body Large** | 16px | 400 (Regular) | 24px | 0px | Texto principal |
|
||
| **Body Normal** | 14px | 400 (Regular) | 22px | 0px | Descrições |
|
||
| **Body Small** | 12px | 400 (Regular) | 18px | 0.2px | Ajuda, captions |
|
||
| **Label** | 12px | 600 (SemiBold) | 18px | 0.5px | Labels de campos |
|
||
| **Button** | 14px | 600 (SemiBold) | 20px | 0.5px | Texto de botões |
|
||
|
||
### Importação no CSS/Next.js
|
||
```css
|
||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@600;700&display=swap');
|
||
|
||
:root {
|
||
--font-inter: 'Inter', sans-serif;
|
||
--font-poppins: 'Poppins', sans-serif;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 Espaçamento (8px Base)
|
||
|
||
Seguindo o padrão Material Design + Tailwind, usando múltiplos de 8px:
|
||
|
||
| Token | Valor | Uso |
|
||
|-------|-------|-----|
|
||
| **xs** | 4px | Micro-espaçamentos |
|
||
| **sm** | 8px | Padding pequeno |
|
||
| **md** | 12px | Padding padrão |
|
||
| **lg** | 16px | Espaçamento interno |
|
||
| **xl** | 24px | Separação entre elementos |
|
||
| **2xl** | 32px | Separação entre seções |
|
||
| **3xl** | 48px | Grandes divisores |
|
||
| **4xl** | 64px | Muito grandes |
|
||
|
||
### Exemplos de Aplicação
|
||
- **Padding de Botão**: 12px (vertical) × 16px (horizontal)
|
||
- **Padding de Card**: 24px
|
||
- **Gap entre inputs**: 16px
|
||
- **Margin entre seções**: 32px
|
||
|
||
---
|
||
|
||
## 🎨 Componentes - Design System
|
||
|
||
### 1️⃣ **BOTÕES**
|
||
|
||
#### Botão Primary (Padrão)
|
||
```
|
||
Tamanho: 48px altura
|
||
Padding: 12px vertical × 16px horizontal
|
||
Background: #2563EB
|
||
Text: White, 14px Bold
|
||
Border Radius: 8px
|
||
Font Weight: 600
|
||
```
|
||
|
||
**Estados:**
|
||
- **Default**: Background #2563EB
|
||
- **Hover**: Background #1D4ED8, Sombra leve
|
||
- **Active**: Background #1D4ED8, sem sombra
|
||
- **Disabled**: Background #E5E7EB, Text #9CA3AF, sem cursor
|
||
|
||
#### Botão Secondary
|
||
```
|
||
Background: #F3F4F6
|
||
Text: #000000, 14px Bold
|
||
Border: 1px #E5E7EB
|
||
Border Radius: 8px
|
||
```
|
||
|
||
#### Botão Tertiary (Text only)
|
||
```
|
||
Background: transparent
|
||
Text: #2563EB, 14px Bold
|
||
Padding: 12px 16px
|
||
```
|
||
|
||
#### Botão Danger
|
||
```
|
||
Background: #EF4444
|
||
Text: White, 14px Bold
|
||
Sombra: 0px 4px 12px rgba(239, 68, 68, 0.2)
|
||
```
|
||
|
||
#### Botão com Ícone
|
||
```
|
||
Spacing entre ícone e texto: 8px
|
||
Ícone tamanho: 20px × 20px
|
||
```
|
||
|
||
---
|
||
|
||
### 2️⃣ **CAMPOS DE ENTRADA (Inputs)**
|
||
|
||
#### Input Padrão
|
||
```
|
||
Altura: 44px
|
||
Padding: 12px 16px
|
||
Border: 1px #E5E7EB
|
||
Border Radius: 8px
|
||
Font: Inter 14px
|
||
Background: #FFFFFF
|
||
```
|
||
|
||
**Estados:**
|
||
- **Default**: Border #E5E7EB, Background #FFFFFF
|
||
- **Focus**: Border #2563EB (2px), Background #FFFFFF, Box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1)
|
||
- **Filled**: Border #2563EB
|
||
- **Error**: Border #EF4444, Background #FEF2F2
|
||
- **Disabled**: Border #E5E7EB, Background #F9FAFB, Text #9CA3AF
|
||
|
||
#### Placeholder
|
||
```
|
||
Color: #9CA3AF
|
||
Font Style: Regular
|
||
```
|
||
|
||
#### Label
|
||
```
|
||
Font: Poppins 12px SemiBold
|
||
Color: #000000
|
||
Margin Bottom: 8px
|
||
Required indicator (*): Color #EF4444
|
||
```
|
||
|
||
#### Help Text
|
||
```
|
||
Font: Inter 12px Regular
|
||
Color: #6B7280
|
||
Margin Top: 4px
|
||
```
|
||
|
||
#### Error Message
|
||
```
|
||
Font: Inter 12px Regular
|
||
Color: #EF4444
|
||
Icon: 16px × 16px (⚠️)
|
||
Margin Top: 4px
|
||
```
|
||
|
||
---
|
||
|
||
### 3️⃣ **CARDS**
|
||
|
||
```
|
||
Background: #FFFFFF
|
||
Border: 1px #E5E7EB
|
||
Border Radius: 12px
|
||
Padding: 24px
|
||
Box Shadow: 0px 1px 3px rgba(0, 0, 0, 0.1)
|
||
```
|
||
|
||
**Hover (Interactive):**
|
||
```
|
||
Box Shadow: 0px 4px 12px rgba(0, 0, 0, 0.08)
|
||
Transition: 150ms
|
||
```
|
||
|
||
#### Task Card
|
||
```
|
||
Padding: 16px
|
||
Border Radius: 12px
|
||
Background: #FFFFFF
|
||
Border: 1px #E5E7EB
|
||
|
||
Estrutura:
|
||
├── Checkbox (20px × 20px)
|
||
├── Conteúdo (Flex: 1)
|
||
│ ├── Título: 14px Bold, #000000
|
||
│ └── Descrição: 13px Regular, #6B7280
|
||
└── Menu/Delete: 24px × 24px (Right)
|
||
|
||
Spacing: 12px entre elementos
|
||
```
|
||
|
||
---
|
||
|
||
### 4️⃣ **CHECKBOX & RADIO**
|
||
|
||
#### Checkbox
|
||
```
|
||
Tamanho: 20px × 20px
|
||
Border: 2px #E5E7EB
|
||
Border Radius: 4px
|
||
Background: #FFFFFF
|
||
Padding: 2px (interno)
|
||
```
|
||
|
||
**Estados:**
|
||
- **Unchecked**: Border #E5E7EB, Background #FFFFFF
|
||
- **Checked**: Border #2563EB, Background #2563EB, Ícone ✓ branco
|
||
- **Focus**: Box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1)
|
||
- **Disabled**: Border #E5E7EB, Background #F3F4F6
|
||
|
||
---
|
||
|
||
### 5️⃣ **TABS**
|
||
|
||
```
|
||
Height: 48px
|
||
Font: Inter 14px SemiBold
|
||
Color: #6B7280 (inactive), #2563EB (active)
|
||
Border Bottom: 2px #2563EB (active)
|
||
Padding: 16px horizontal
|
||
```
|
||
|
||
---
|
||
|
||
### 6️⃣ **MODALS/DIALOGS**
|
||
|
||
```
|
||
Background: #FFFFFF
|
||
Border Radius: 16px
|
||
Padding: 32px
|
||
Width: 90% (mobile), 520px (desktop)
|
||
Max Height: 90vh
|
||
Box Shadow: 0px 20px 25px rgba(0, 0, 0, 0.15)
|
||
Overlay: rgba(0, 0, 0, 0.5)
|
||
```
|
||
|
||
**Estrutura:**
|
||
```
|
||
├── Header
|
||
│ ├── Título: H2
|
||
│ └── Close button: 24px (top right)
|
||
├── Content
|
||
│ └── Padding: 24px 0
|
||
└── Footer (Actions)
|
||
├── Button Secondary (Cancel): Left
|
||
└── Button Primary (Confirm): Right
|
||
└── Spacing: 12px entre botões
|
||
```
|
||
|
||
---
|
||
|
||
### 7️⃣ **ÍCONES (Google Icons)**
|
||
|
||
Link: https://fonts.google.com/icons
|
||
|
||
**Tamanhos Padrão:**
|
||
- **Small**: 16px - Lado de inputs, help text
|
||
- **Normal**: 20px - Ícones em botões, menus
|
||
- **Large**: 24px - Ícones principais, headers
|
||
- **XL**: 32px - Ícones de estado vazio, sucesso
|
||
|
||
**Cor Principal**: #2563EB
|
||
**Cor Secundária**: #6B7280
|
||
**Cor Erro**: #EF4444
|
||
|
||
**Ícones Recomendados:**
|
||
- check_circle (Concluído)
|
||
- radio_button_unchecked (Não concluído)
|
||
- delete (Deletar)
|
||
- edit (Editar)
|
||
- close (Fechar)
|
||
- menu (Menu)
|
||
- search (Buscar)
|
||
- add (Adicionar)
|
||
- logout (Sair)
|
||
- login (Entrar)
|
||
- person (Perfil)
|
||
- error (Erro)
|
||
- warning (Aviso)
|
||
- info (Info)
|
||
|
||
---
|
||
|
||
## 📱 **NEXT.JS - Estrutura de Componentes**
|
||
|
||
### Diretório
|
||
```
|
||
frontend-next/
|
||
├── src/
|
||
│ ├── components/
|
||
│ │ ├── ui/
|
||
│ │ │ ├── Button.tsx
|
||
│ │ │ ├── Input.tsx
|
||
│ │ │ ├── Card.tsx
|
||
│ │ │ ├── Checkbox.tsx
|
||
│ │ │ ├── Modal.tsx
|
||
│ │ │ ├── Toast.tsx
|
||
│ │ │ └── Spinner.tsx
|
||
│ │ ├── forms/
|
||
│ │ │ ├── TaskForm.tsx
|
||
│ │ │ ├── LoginForm.tsx
|
||
│ │ │ └── SignupForm.tsx
|
||
│ │ ├── tasks/
|
||
│ │ │ ├── TaskItem.tsx
|
||
│ │ │ ├── TaskList.tsx
|
||
│ │ │ └── TaskFilters.tsx
|
||
│ │ ├── layout/
|
||
│ │ │ ├── Header.tsx
|
||
│ │ │ ├── Sidebar.tsx
|
||
│ │ │ └── Footer.tsx
|
||
│ │ └── common/
|
||
│ │ ├── EmptyState.tsx
|
||
│ │ └── LoadingState.tsx
|
||
│ ├── lib/
|
||
│ │ ├── styles/
|
||
│ │ │ ├── colors.ts
|
||
│ │ │ ├── spacing.ts
|
||
│ │ │ ├── typography.ts
|
||
│ │ │ └── shadows.ts
|
||
│ │ └── utils.ts
|
||
│ ├── app/
|
||
│ │ ├── globals.css
|
||
│ │ ├── layout.tsx
|
||
│ │ ├── page.tsx
|
||
│ │ ├── (auth)/
|
||
│ │ │ ├── login/page.tsx
|
||
│ │ │ └── signup/page.tsx
|
||
│ │ └── (dashboard)/
|
||
│ │ └── tasks/page.tsx
|
||
│ └── styles/
|
||
│ └── tailwind.config.ts
|
||
```
|
||
|
||
### Configuração Tailwind (tailwind.config.ts)
|
||
```typescript
|
||
import type { Config } from 'tailwindcss'
|
||
|
||
export default {
|
||
content: [
|
||
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
|
||
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
|
||
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
|
||
],
|
||
theme: {
|
||
extend: {
|
||
colors: {
|
||
primary: {
|
||
DEFAULT: '#2563EB',
|
||
dark: '#1D4ED8',
|
||
light: '#DBEAFE',
|
||
},
|
||
gray: {
|
||
50: '#F9FAFB',
|
||
100: '#F3F4F6',
|
||
200: '#E5E7EB',
|
||
400: '#9CA3AF',
|
||
600: '#4B5563',
|
||
},
|
||
status: {
|
||
success: '#10B981',
|
||
warning: '#F59E0B',
|
||
error: '#EF4444',
|
||
info: '#06B6D4',
|
||
},
|
||
},
|
||
fontFamily: {
|
||
inter: ['var(--font-inter)', 'sans-serif'],
|
||
poppins: ['var(--font-poppins)', 'sans-serif'],
|
||
},
|
||
fontSize: {
|
||
'h1': ['32px', { lineHeight: '40px', fontWeight: '700', letterSpacing: '-0.5px' }],
|
||
'h2': ['24px', { lineHeight: '32px', fontWeight: '700', letterSpacing: '-0.3px' }],
|
||
'h3': ['18px', { lineHeight: '28px', fontWeight: '600', letterSpacing: '-0.2px' }],
|
||
'body-lg': ['16px', { lineHeight: '24px', fontWeight: '400' }],
|
||
'body': ['14px', { lineHeight: '22px', fontWeight: '400' }],
|
||
'body-sm': ['12px', { lineHeight: '18px', fontWeight: '400', letterSpacing: '0.2px' }],
|
||
'label': ['12px', { lineHeight: '18px', fontWeight: '600', letterSpacing: '0.5px' }],
|
||
'btn': ['14px', { lineHeight: '20px', fontWeight: '600', letterSpacing: '0.5px' }],
|
||
},
|
||
spacing: {
|
||
'xs': '4px',
|
||
'sm': '8px',
|
||
'md': '12px',
|
||
'lg': '16px',
|
||
'xl': '24px',
|
||
'2xl': '32px',
|
||
'3xl': '48px',
|
||
'4xl': '64px',
|
||
},
|
||
borderRadius: {
|
||
'sm': '4px',
|
||
'md': '8px',
|
||
'lg': '12px',
|
||
'xl': '16px',
|
||
},
|
||
boxShadow: {
|
||
'sm': '0px 1px 3px rgba(0, 0, 0, 0.1)',
|
||
'md': '0px 4px 12px rgba(0, 0, 0, 0.08)',
|
||
'lg': '0px 20px 25px rgba(0, 0, 0, 0.15)',
|
||
'focus': '0 0 0 3px rgba(37, 99, 235, 0.1)',
|
||
},
|
||
},
|
||
},
|
||
plugins: [],
|
||
} satisfies Config
|
||
```
|
||
|
||
---
|
||
|
||
## 🚀 **FLUTTER - Design System**
|
||
|
||
### Diretório
|
||
```
|
||
mobile/
|
||
├── lib/
|
||
│ ├── config/
|
||
│ │ ├── theme.dart
|
||
│ │ ├── colors.dart
|
||
│ │ ├── typography.dart
|
||
│ │ └── spacing.dart
|
||
│ ├── widgets/
|
||
│ │ ├── buttons/
|
||
│ │ │ ├── primary_button.dart
|
||
│ │ │ ├── secondary_button.dart
|
||
│ │ │ └── tertiary_button.dart
|
||
│ │ ├── inputs/
|
||
│ │ │ ├── text_input.dart
|
||
│ │ │ ├── checkbox_input.dart
|
||
│ │ │ └── form_field.dart
|
||
│ │ ├── cards/
|
||
│ │ │ ├── task_card.dart
|
||
│ │ │ └── card.dart
|
||
│ │ ├── common/
|
||
│ │ │ ├── modal.dart
|
||
│ │ │ ├── empty_state.dart
|
||
│ │ │ └── loading_state.dart
|
||
│ │ └── app/
|
||
│ │ ├── app_bar.dart
|
||
│ │ └── bottom_nav.dart
|
||
│ ├── screens/
|
||
│ │ ├── auth/
|
||
│ │ │ ├── login_screen.dart
|
||
│ │ │ └── signup_screen.dart
|
||
│ │ ├── tasks/
|
||
│ │ │ ├── tasks_screen.dart
|
||
│ │ │ ├── task_detail_screen.dart
|
||
│ │ │ └── create_task_screen.dart
|
||
│ │ └── profile/
|
||
│ │ └── profile_screen.dart
|
||
│ └── main.dart
|
||
```
|
||
|
||
### Colors (colors.dart)
|
||
```dart
|
||
abstract class AppColors {
|
||
// Primary
|
||
static const Color primary = Color(0xFF2563EB);
|
||
static const Color primaryDark = Color(0xFF1D4ED8);
|
||
static const Color primaryLight = Color(0xFFDBEAFE);
|
||
|
||
// Base
|
||
static const Color white = Color(0xFFFFFFFF);
|
||
static const Color black = Color(0xFF000000);
|
||
|
||
// Gray
|
||
static const Color gray50 = Color(0xFFF9FAFB);
|
||
static const Color gray100 = Color(0xFFF3F4F6);
|
||
static const Color gray200 = Color(0xFFE5E7EB);
|
||
static const Color gray400 = Color(0xFF9CA3AF);
|
||
static const Color gray600 = Color(0xFF4B5563);
|
||
|
||
// Status
|
||
static const Color success = Color(0xFF10B981);
|
||
static const Color warning = Color(0xFFF59E0B);
|
||
static const Color error = Color(0xFFEF4444);
|
||
static const Color info = Color(0xFF06B6D4);
|
||
}
|
||
```
|
||
|
||
### Theme (theme.dart)
|
||
```dart
|
||
import 'package:flutter/material.dart';
|
||
import 'colors.dart';
|
||
|
||
final ThemeData appTheme = ThemeData(
|
||
useMaterial3: true,
|
||
colorScheme: ColorScheme(
|
||
brightness: Brightness.light,
|
||
primary: AppColors.primary,
|
||
onPrimary: AppColors.white,
|
||
secondary: AppColors.gray600,
|
||
onSecondary: AppColors.white,
|
||
error: AppColors.error,
|
||
onError: AppColors.white,
|
||
background: AppColors.white,
|
||
onBackground: AppColors.black,
|
||
surface: AppColors.white,
|
||
onSurface: AppColors.black,
|
||
),
|
||
fontFamily: 'Inter',
|
||
textTheme: TextTheme(
|
||
displayLarge: TextStyle(
|
||
fontSize: 32,
|
||
fontWeight: FontWeight.w700,
|
||
letterSpacing: -0.5,
|
||
fontFamily: 'Poppins',
|
||
),
|
||
displayMedium: TextStyle(
|
||
fontSize: 24,
|
||
fontWeight: FontWeight.w700,
|
||
letterSpacing: -0.3,
|
||
fontFamily: 'Poppins',
|
||
),
|
||
headlineSmall: TextStyle(
|
||
fontSize: 18,
|
||
fontWeight: FontWeight.w600,
|
||
letterSpacing: -0.2,
|
||
fontFamily: 'Poppins',
|
||
),
|
||
bodyLarge: TextStyle(
|
||
fontSize: 16,
|
||
fontWeight: FontWeight.w400,
|
||
height: 1.5,
|
||
),
|
||
bodyMedium: TextStyle(
|
||
fontSize: 14,
|
||
fontWeight: FontWeight.w400,
|
||
height: 1.57,
|
||
),
|
||
bodySmall: TextStyle(
|
||
fontSize: 12,
|
||
fontWeight: FontWeight.w400,
|
||
letterSpacing: 0.2,
|
||
height: 1.5,
|
||
),
|
||
labelMedium: TextStyle(
|
||
fontSize: 12,
|
||
fontWeight: FontWeight.w600,
|
||
letterSpacing: 0.5,
|
||
),
|
||
),
|
||
);
|
||
```
|
||
|
||
### Spacing (spacing.dart)
|
||
```dart
|
||
abstract class AppSpacing {
|
||
static const double xs = 4.0;
|
||
static const double sm = 8.0;
|
||
static const double md = 12.0;
|
||
static const double lg = 16.0;
|
||
static const double xl = 24.0;
|
||
static const double xxl = 32.0;
|
||
static const double xxxl = 48.0;
|
||
static const double xxxxl = 64.0;
|
||
}
|
||
```
|
||
|
||
### Exemplo de Componente - Primary Button
|
||
```dart
|
||
class PrimaryButton extends StatelessWidget {
|
||
final String label;
|
||
final VoidCallback onPressed;
|
||
final bool isLoading;
|
||
final bool isEnabled;
|
||
final IconData? icon;
|
||
|
||
const PrimaryButton({
|
||
required this.label,
|
||
required this.onPressed,
|
||
this.isLoading = false,
|
||
this.isEnabled = true,
|
||
this.icon,
|
||
});
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return ElevatedButton(
|
||
onPressed: isEnabled && !isLoading ? onPressed : null,
|
||
style: ElevatedButton.styleFrom(
|
||
backgroundColor: AppColors.primary,
|
||
disabledBackgroundColor: AppColors.gray200,
|
||
padding: EdgeInsets.symmetric(
|
||
vertical: AppSpacing.md,
|
||
horizontal: AppSpacing.lg,
|
||
),
|
||
shape: RoundedRectangleBorder(
|
||
borderRadius: BorderRadius.circular(8),
|
||
),
|
||
elevation: 0,
|
||
),
|
||
child: isLoading
|
||
? SizedBox(
|
||
height: 20,
|
||
width: 20,
|
||
child: CircularProgressIndicator(
|
||
strokeWidth: 2,
|
||
valueColor: AlwaysStoppedAnimation<Color>(
|
||
isEnabled ? AppColors.white : AppColors.gray400,
|
||
),
|
||
),
|
||
)
|
||
: Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
if (icon != null) ...[
|
||
Icon(icon, size: 20),
|
||
SizedBox(width: AppSpacing.sm),
|
||
],
|
||
Text(label),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 **PADRÕES DE LAYOUT**
|
||
|
||
### Responsividade Next.js
|
||
|
||
```
|
||
Mobile: < 640px (default)
|
||
Tablet: 640px - 1024px
|
||
Desktop: > 1024px
|
||
```
|
||
|
||
### Breakpoints (Tailwind)
|
||
```typescript
|
||
sm: '640px'
|
||
md: '768px'
|
||
lg: '1024px'
|
||
xl: '1280px'
|
||
2xl: '1536px'
|
||
```
|
||
|
||
### Safe Area (Flutter)
|
||
```dart
|
||
Scaffold(
|
||
body: SafeArea(
|
||
child: SingleChildScrollView(
|
||
padding: EdgeInsets.all(AppSpacing.lg),
|
||
child: YourContent(),
|
||
),
|
||
),
|
||
)
|
||
```
|
||
|
||
---
|
||
|
||
## 📐 **ANIMAÇÕES & TRANSIÇÕES**
|
||
|
||
### Next.js (Tailwind)
|
||
```
|
||
Duration padrão: 150ms
|
||
Easing: cubic-bezier(0.4, 0, 0.2, 1)
|
||
Propriedades: transform, opacity, color, box-shadow
|
||
```
|
||
|
||
**Exemplo:**
|
||
```css
|
||
.button {
|
||
@apply transition-all duration-150 ease-in-out;
|
||
}
|
||
|
||
.button:hover {
|
||
@apply scale-105 shadow-md;
|
||
}
|
||
```
|
||
|
||
### Flutter
|
||
```dart
|
||
Duration animationDuration = Duration(milliseconds: 150);
|
||
Curve animationCurve = Curves.easeInOut;
|
||
```
|
||
|
||
---
|
||
|
||
## ✅ **ACESSIBILIDADE**
|
||
|
||
### Contraste de Cores (WCAG AA)
|
||
- Ratio mínimo: 4.5:1 para textos normais
|
||
- Ratio mínimo: 3:1 para textos grandes
|
||
|
||
### Next.js
|
||
- Usar `<label htmlFor="">` para inputs
|
||
- Alt text em imagens
|
||
- Semantic HTML (button, form, etc)
|
||
|
||
### Flutter
|
||
- Semantics widget para leitura de tela
|
||
- Sufficient touch targets (mínimo 48x48 dp)
|
||
|
||
---
|
||
|
||
## 📋 **CHECKLIST DE DESIGN**
|
||
|
||
- [ ] Cores aplicadas conforme paleta
|
||
- [ ] Tipografia usando Inter e Poppins
|
||
- [ ] Espaçamento em múltiplos de 8px
|
||
- [ ] Componentes com 4 estados (default, hover, active, disabled)
|
||
- [ ] Ícones do Google Icons (20px padrão)
|
||
- [ ] Botões com altura mínima de 48px
|
||
- [ ] Inputs com altura de 44px
|
||
- [ ] Cards com border-radius 12px
|
||
- [ ] Box shadows consistentes
|
||
- [ ] Responsive design funcional
|
||
- [ ] Acessibilidade testada
|
||
- [ ] Loading states em todas as ações
|
||
- [ ] Error states claros
|
||
- [ ] Empty states amigáveis
|
||
|
||
---
|
||
|
||
## 🔗 **REFERÊNCIAS & RECURSOS**
|
||
|
||
### Ferramentas
|
||
- **Figma**: Para prototipar (opcional)
|
||
- **Google Fonts**: https://fonts.google.com
|
||
- **Google Icons**: https://fonts.google.com/icons
|
||
- **Color Checker**: https://webaim.org/resources/contrastchecker/
|
||
|
||
### Documentação
|
||
- **Tailwind CSS**: https://tailwindcss.com/docs
|
||
- **Next.js**: https://nextjs.org/docs
|
||
- **Flutter**: https://flutter.dev/docs
|
||
- **Material Design 3**: https://m3.material.io/
|
||
|
||
---
|
||
|
||
## 💾 **IMPLEMENTAÇÃO IMEDIATA**
|
||
|
||
### Next.js - Setup Inicial
|
||
1. Configurar Tailwind config com tokens
|
||
2. Criar componentes base (Button, Input, Card)
|
||
3. Importar Google Fonts em globals.css
|
||
4. Testar componentes em storybook (opcional)
|
||
|
||
### Flutter - Setup Inicial
|
||
1. Adicionar Google Fonts package
|
||
2. Criar arquivos de theme
|
||
3. Implementar componentes customizados
|
||
4. Testar em multiple devices
|
||
|
||
---
|
||
|
||
**Mantém Fidelidade ao Design em TODAS as screens! 🎯**
|