xertica-ui 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.ts +81 -0
- package/components/ui/google-maps-loader.tsx +31 -26
- package/components/ui/map.tsx +11 -11
- package/components/ui/route-map.tsx +13 -13
- package/components/ui/xertica-assistant.tsx +127 -124
- package/dist/cli.js +103 -20812
- package/guidelines/Guidelines.md +643 -46
- package/package.json +2 -2
package/guidelines/Guidelines.md
CHANGED
|
@@ -1,61 +1,658 @@
|
|
|
1
|
-
|
|
2
|
-
<!--
|
|
1
|
+
# Xertica UI - Project Guidelines
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
## 📋 Visão Geral do Projeto
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
This template outlines a few examples of things you can add. You can add your own sections and format it to suit your needs
|
|
5
|
+
O **Xertica UI** é um Design System completo construído com React e Tailwind CSS v4.0, seguindo uma arquitetura **CLI-first** (modelo shadcn/ui). O sistema está 100% pronto para publicação no NPM e todos os componentes são portáveis, independentes e reutilizáveis.
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
---
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
## 🎨 Design System - Princípios Fundamentais
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
For example:
|
|
11
|
+
### Variáveis CSS Semânticas
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
* Refactor code as you go to keep code clean
|
|
18
|
-
* Keep file sizes small and put helper functions and components in their own files.
|
|
13
|
+
**REGRA CRÍTICA**: Todos os componentes e páginas DEVEM usar exclusivamente as variáveis CSS definidas em `/styles/xertica/tokens.css`.
|
|
19
14
|
|
|
20
|
-
|
|
15
|
+
#### Cores
|
|
16
|
+
```css
|
|
17
|
+
/* Sempre use as variáveis semânticas */
|
|
18
|
+
var(--background)
|
|
19
|
+
var(--foreground)
|
|
20
|
+
var(--card)
|
|
21
|
+
var(--card-foreground)
|
|
22
|
+
var(--primary)
|
|
23
|
+
var(--primary-foreground)
|
|
24
|
+
var(--secondary)
|
|
25
|
+
var(--secondary-foreground)
|
|
26
|
+
var(--muted)
|
|
27
|
+
var(--muted-foreground)
|
|
28
|
+
var(--accent)
|
|
29
|
+
var(--accent-foreground)
|
|
30
|
+
var(--destructive)
|
|
31
|
+
var(--destructive-foreground)
|
|
32
|
+
var(--border)
|
|
33
|
+
var(--input)
|
|
34
|
+
var(--ring)
|
|
35
|
+
var(--chart-1) até var(--chart-5)
|
|
36
|
+
```
|
|
21
37
|
|
|
22
|
-
|
|
23
|
-
|
|
38
|
+
#### Espaçamentos
|
|
39
|
+
```css
|
|
40
|
+
/* Use os tokens de spacing */
|
|
41
|
+
var(--spacing-xs) /* 4px */
|
|
42
|
+
var(--spacing-sm) /* 8px */
|
|
43
|
+
var(--spacing-md) /* 16px */
|
|
44
|
+
var(--spacing-lg) /* 24px */
|
|
45
|
+
var(--spacing-xl) /* 32px */
|
|
46
|
+
var(--spacing-2xl) /* 48px */
|
|
47
|
+
var(--spacing-3xl) /* 64px */
|
|
48
|
+
```
|
|
24
49
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
50
|
+
#### Bordas e Raios
|
|
51
|
+
```css
|
|
52
|
+
var(--radius) /* Border radius padrão */
|
|
53
|
+
var(--radius-sm) /* Border radius pequeno */
|
|
54
|
+
var(--radius-lg) /* Border radius grande */
|
|
55
|
+
var(--radius-full) /* Border radius circular */
|
|
56
|
+
```
|
|
28
57
|
|
|
29
|
-
|
|
30
|
-
* Date formats should always be in the format “Jun 10”
|
|
31
|
-
* The bottom toolbar should only ever have a maximum of 4 items
|
|
32
|
-
* Never use the floating action button with the bottom toolbar
|
|
33
|
-
* Chips should always come in sets of 3 or more
|
|
34
|
-
* Don't use a dropdown if there are 2 or fewer options
|
|
58
|
+
#### Tipografia
|
|
35
59
|
|
|
36
|
-
|
|
37
|
-
For example:
|
|
60
|
+
**REGRA CRÍTICA**: Apenas a fonte **Roboto** pode ser utilizada (definida em `/styles/globals.css`).
|
|
38
61
|
|
|
62
|
+
```css
|
|
63
|
+
/* Importado no globals.css */
|
|
64
|
+
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;600;700;800&display=swap');
|
|
39
65
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
66
|
+
/* Font weights disponíveis */
|
|
67
|
+
font-weight: 400; /* Regular */
|
|
68
|
+
font-weight: 500; /* Medium */
|
|
69
|
+
font-weight: 600; /* Semibold */
|
|
70
|
+
font-weight: 700; /* Bold */
|
|
71
|
+
font-weight: 800; /* Extra Bold */
|
|
72
|
+
```
|
|
43
73
|
|
|
44
|
-
|
|
45
|
-
Buttons should be used for important actions that users need to take, such as form submissions, confirming choices,
|
|
46
|
-
or initiating processes. They communicate interactivity and should have clear, action-oriented labels.
|
|
74
|
+
**NÃO use** classes Tailwind para font-size, font-weight ou line-height, **A MENOS** que o usuário solicite explicitamente.
|
|
47
75
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 🧩 Componentes do Design System
|
|
79
|
+
|
|
80
|
+
### Localização
|
|
81
|
+
Todos os componentes do Design System estão em `/components/ui/` (156 componentes disponíveis).
|
|
82
|
+
|
|
83
|
+
### Regra de Ouro: REUTILIZE, NÃO RECRIE
|
|
84
|
+
|
|
85
|
+
**SEMPRE**:
|
|
86
|
+
1. ✅ Use componentes existentes em `/components/ui/`
|
|
87
|
+
2. ✅ Consulte os componentes disponíveis antes de criar novos
|
|
88
|
+
3. ✅ Combine componentes existentes para criar funcionalidades complexas
|
|
89
|
+
4. ✅ Estenda componentes existentes com props adicionais se necessário
|
|
90
|
+
|
|
91
|
+
**NUNCA**:
|
|
92
|
+
1. ❌ Crie versões personalizadas de componentes que já existem
|
|
93
|
+
2. ❌ Crie componentes inline que duplicam funcionalidades existentes
|
|
94
|
+
3. ❌ Ignore os componentes do design system
|
|
95
|
+
|
|
96
|
+
### Componentes Principais Disponíveis
|
|
97
|
+
|
|
98
|
+
#### Layout & Estrutura
|
|
99
|
+
- `Card`, `CardHeader`, `CardTitle`, `CardContent`, `CardFooter`
|
|
100
|
+
- `Separator`
|
|
101
|
+
- `ScrollArea`
|
|
102
|
+
- `Sheet`
|
|
103
|
+
- `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent`
|
|
104
|
+
- `Accordion`, `AccordionItem`, `AccordionTrigger`, `AccordionContent`
|
|
105
|
+
- `Collapsible`
|
|
106
|
+
- `Resizable`, `ResizablePanel`, `ResizablePanelGroup`, `ResizableHandle`
|
|
107
|
+
|
|
108
|
+
#### Navegação
|
|
109
|
+
- `Breadcrumb`
|
|
110
|
+
- `NavigationMenu`
|
|
111
|
+
- `Menubar`
|
|
112
|
+
- `Sidebar` (componente especializado do Xertica)
|
|
113
|
+
- `PageHeader` (componente especializado do Xertica)
|
|
114
|
+
|
|
115
|
+
#### Formulários
|
|
116
|
+
- `Input`
|
|
117
|
+
- `Textarea`
|
|
118
|
+
- `Select`, `SelectTrigger`, `SelectValue`, `SelectContent`, `SelectItem`
|
|
119
|
+
- `Checkbox`
|
|
120
|
+
- `RadioGroup`, `RadioGroupItem`
|
|
121
|
+
- `Switch`
|
|
122
|
+
- `Slider`
|
|
123
|
+
- `Calendar`
|
|
124
|
+
- `Form`, `FormField`, `FormItem`, `FormLabel`, `FormControl`, `FormMessage`
|
|
125
|
+
- `Label`
|
|
126
|
+
- `InputOTP`
|
|
127
|
+
- `FileUpload`
|
|
128
|
+
- `Search`
|
|
129
|
+
|
|
130
|
+
#### Botões & Ações
|
|
131
|
+
- `Button` (variants: default, destructive, outline, secondary, ghost, link)
|
|
132
|
+
- `Toggle`, `ToggleGroup`
|
|
133
|
+
- `DropdownMenu`
|
|
134
|
+
- `ContextMenu`
|
|
135
|
+
|
|
136
|
+
#### Feedback
|
|
137
|
+
- `Alert`, `AlertTitle`, `AlertDescription`
|
|
138
|
+
- `AlertDialog`
|
|
139
|
+
- `Dialog`, `DialogTrigger`, `DialogContent`, `DialogHeader`, `DialogTitle`, `DialogDescription`, `DialogFooter`
|
|
140
|
+
- `Drawer`
|
|
141
|
+
- `toast` (Sonner)
|
|
142
|
+
- `Progress`
|
|
143
|
+
- `Skeleton`
|
|
144
|
+
- `Badge`
|
|
145
|
+
- `NotificationBadge`
|
|
146
|
+
|
|
147
|
+
#### Dados & Visualização
|
|
148
|
+
- `Table`, `TableHeader`, `TableBody`, `TableRow`, `TableCell`
|
|
149
|
+
- `Chart` (Recharts integration)
|
|
150
|
+
- `StatsCard`
|
|
151
|
+
- `Avatar`, `AvatarImage`, `AvatarFallback`
|
|
152
|
+
- `Empty`
|
|
153
|
+
- `Rating`
|
|
154
|
+
- `Timeline`
|
|
155
|
+
- `TreeView`
|
|
156
|
+
|
|
157
|
+
#### Navegação & Tour
|
|
158
|
+
- `Stepper`, `StepperItem`
|
|
159
|
+
- `Pagination`
|
|
160
|
+
- `Command`, `CommandInput`, `CommandList`, `CommandItem`, `CommandGroup`
|
|
161
|
+
|
|
162
|
+
#### Overlays
|
|
163
|
+
- `Tooltip`, `TooltipTrigger`, `TooltipContent`, `TooltipProvider`
|
|
164
|
+
- `Popover`, `PopoverTrigger`, `PopoverContent`
|
|
165
|
+
- `HoverCard`, `HoverCardTrigger`, `HoverCardContent`
|
|
166
|
+
|
|
167
|
+
#### Especialidades Xertica
|
|
168
|
+
- `Map`, `SimpleMap`, `RouteMap` (Google Maps integration)
|
|
169
|
+
- `XerticaAssistant` (Assistente IA integrado)
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 🎯 Ícones
|
|
174
|
+
|
|
175
|
+
**REGRA CRÍTICA**: Apenas ícones do **lucide-react** podem ser utilizados.
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
import { Home, User, Settings, FileText, ChevronRight, Menu } from 'lucide-react';
|
|
179
|
+
|
|
180
|
+
// Uso
|
|
181
|
+
<Home className="w-5 h-5" />
|
|
182
|
+
<Settings className="w-6 h-6 text-primary" />
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**NÃO use**:
|
|
186
|
+
- ❌ Font Awesome
|
|
187
|
+
- ❌ Material Icons
|
|
188
|
+
- ❌ SVGs customizados (a menos que absolutamente necessário)
|
|
189
|
+
- ❌ Qualquer outra biblioteca de ícones
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 📄 Estrutura de Páginas
|
|
194
|
+
|
|
195
|
+
### Anatomia de uma Página Padrão
|
|
196
|
+
|
|
197
|
+
Todas as páginas devem seguir esta estrutura:
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
import React from 'react';
|
|
201
|
+
import { Card, CardContent, CardHeader, CardTitle } from './ui/card';
|
|
202
|
+
import { Button } from './ui/button';
|
|
203
|
+
import { ScrollArea } from './ui/scroll-area';
|
|
204
|
+
import { ChevronRight, Menu, IconName } from 'lucide-react';
|
|
205
|
+
import { useLocation, useNavigate } from 'react-router';
|
|
206
|
+
import { getRouteByPath } from '../routes';
|
|
207
|
+
import { ThemeToggle } from './ThemeToggle';
|
|
208
|
+
import { LanguageSelector } from './LanguageSelector';
|
|
209
|
+
|
|
210
|
+
interface PageContentProps {
|
|
211
|
+
sidebarExpanded: boolean;
|
|
212
|
+
assistenteExpanded?: boolean;
|
|
213
|
+
onToggleSidebar?: () => void;
|
|
214
|
+
onToggleAssistente?: () => void;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export function PageContent({
|
|
218
|
+
sidebarExpanded,
|
|
219
|
+
assistenteExpanded = false,
|
|
220
|
+
onToggleSidebar,
|
|
221
|
+
onToggleAssistente
|
|
222
|
+
}: PageContentProps) {
|
|
223
|
+
const location = useLocation();
|
|
224
|
+
const navigate = useNavigate();
|
|
225
|
+
|
|
226
|
+
const currentRoute = getRouteByPath(location.pathname);
|
|
227
|
+
const breadcrumbLabel = currentRoute?.label || 'Página';
|
|
228
|
+
|
|
229
|
+
return (
|
|
230
|
+
<div
|
|
231
|
+
className={`flex-1 flex flex-col overflow-hidden transition-all duration-300 ${
|
|
232
|
+
sidebarExpanded ? 'md:pl-64' : 'md:pl-20'
|
|
233
|
+
} ${
|
|
234
|
+
assistenteExpanded ? 'md:pr-[420px]' : 'md:pr-20'
|
|
235
|
+
}`}
|
|
236
|
+
>
|
|
237
|
+
{/* Header fixo */}
|
|
238
|
+
<header className="bg-card shadow-sm border-b border-border px-[24px] py-[14px] flex-shrink-0">
|
|
239
|
+
<div className="flex items-center justify-between p-[0px]">
|
|
240
|
+
<div className="flex items-center gap-2 text-muted-foreground">
|
|
241
|
+
<Button
|
|
242
|
+
variant="ghost"
|
|
243
|
+
size="sm"
|
|
244
|
+
onClick={onToggleSidebar}
|
|
245
|
+
className="md:hidden mr-2 p-2"
|
|
246
|
+
>
|
|
247
|
+
<Menu className="w-5 h-5" />
|
|
248
|
+
</Button>
|
|
249
|
+
<span className="text-primary font-medium">Xertica.ai</span>
|
|
250
|
+
<ChevronRight className="w-4 h-4" />
|
|
251
|
+
<span className="text-foreground font-medium">{breadcrumbLabel}</span>
|
|
252
|
+
</div>
|
|
253
|
+
|
|
254
|
+
<div className="flex items-center gap-3">
|
|
255
|
+
<LanguageSelector variant="minimal" showIcon={false} className="hidden sm:flex" />
|
|
256
|
+
<ThemeToggle className="hover:bg-accent" />
|
|
257
|
+
</div>
|
|
258
|
+
</div>
|
|
259
|
+
</header>
|
|
260
|
+
|
|
261
|
+
{/* Área de conteúdo */}
|
|
262
|
+
<main className="flex-1 overflow-hidden bg-muted">
|
|
263
|
+
<ScrollArea className="h-full">
|
|
264
|
+
<div className="p-2 sm:p-4 md:p-6">
|
|
265
|
+
<div className="max-w-6xl mx-auto space-y-8">
|
|
266
|
+
{/* Cabeçalho da página */}
|
|
267
|
+
<div className="space-y-2">
|
|
268
|
+
<h2>Título da Página</h2>
|
|
269
|
+
<p className="text-muted-foreground">
|
|
270
|
+
Descrição da página
|
|
271
|
+
</p>
|
|
272
|
+
</div>
|
|
273
|
+
|
|
274
|
+
{/* Conteúdo principal */}
|
|
275
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
276
|
+
{/* Cards e conteúdo aqui */}
|
|
277
|
+
</div>
|
|
278
|
+
</div>
|
|
279
|
+
</div>
|
|
280
|
+
</ScrollArea>
|
|
281
|
+
</main>
|
|
282
|
+
</div>
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Componentes Obrigatórios de uma Página
|
|
288
|
+
|
|
289
|
+
1. **Header** com breadcrumb
|
|
290
|
+
2. **Menu toggle** para mobile
|
|
291
|
+
3. **ThemeToggle** e **LanguageSelector**
|
|
292
|
+
4. **ScrollArea** para conteúdo scrollável
|
|
293
|
+
5. **Responsividade** para sidebar e assistente
|
|
294
|
+
6. **Espaçamento padronizado** (`p-2 sm:p-4 md:p-6`)
|
|
295
|
+
7. **Container centralizado** (`max-w-6xl mx-auto`)
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## 🗂️ Hierarquia e Navegação
|
|
300
|
+
|
|
301
|
+
### Páginas Primárias (Top-Level)
|
|
302
|
+
|
|
303
|
+
Quando criar uma **nova página primária**:
|
|
304
|
+
|
|
305
|
+
#### 1. Criar o arquivo da página
|
|
306
|
+
```
|
|
307
|
+
/components/MinhaNovaPage.tsx
|
|
308
|
+
/components/MinhaNovaContent.tsx
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
#### 2. Adicionar rota em `/routes.tsx`
|
|
312
|
+
```tsx
|
|
313
|
+
import { MinhaIcon } from 'lucide-react';
|
|
314
|
+
|
|
315
|
+
export const routes: RouteConfig[] = [
|
|
316
|
+
{
|
|
317
|
+
path: '/home',
|
|
318
|
+
label: 'Home',
|
|
319
|
+
icon: Home,
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
path: '/minha-nova-pagina',
|
|
323
|
+
label: 'Minha Nova Página',
|
|
324
|
+
icon: MinhaIcon,
|
|
325
|
+
},
|
|
326
|
+
// ... outras rotas
|
|
327
|
+
];
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
#### 3. Adicionar ao Sidebar (`/components/Sidebar.tsx`)
|
|
331
|
+
O Sidebar lê automaticamente de `routes.tsx`, mas verifique se está sendo renderizado corretamente.
|
|
332
|
+
|
|
333
|
+
#### 4. Adicionar card na Home (`/components/HomeContent.tsx`)
|
|
334
|
+
```tsx
|
|
335
|
+
<Card className="hover:shadow-xl transition-shadow duration-200 flex flex-col h-full">
|
|
336
|
+
<CardHeader>
|
|
337
|
+
<div className="flex items-center gap-3">
|
|
338
|
+
<div className="p-2 bg-[var(--chart-2)]/20 rounded-[var(--radius)]">
|
|
339
|
+
<MinhaIcon className="w-6 h-6 text-[var(--chart-2)]" />
|
|
340
|
+
</div>
|
|
341
|
+
<CardTitle className="text-sm">Minha Nova Página</CardTitle>
|
|
342
|
+
</div>
|
|
343
|
+
</CardHeader>
|
|
344
|
+
<CardContent className="flex-1">
|
|
345
|
+
<p className="text-muted-foreground">
|
|
346
|
+
Descrição da funcionalidade
|
|
347
|
+
</p>
|
|
348
|
+
</CardContent>
|
|
349
|
+
<CardFooter>
|
|
350
|
+
<Button
|
|
351
|
+
variant="outline"
|
|
352
|
+
className="w-full"
|
|
353
|
+
onClick={() => navigate('/minha-nova-pagina')}
|
|
354
|
+
>
|
|
355
|
+
Acessar
|
|
356
|
+
</Button>
|
|
357
|
+
</CardFooter>
|
|
358
|
+
</Card>
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
#### 5. Adicionar roteamento em `/App.tsx`
|
|
362
|
+
```tsx
|
|
363
|
+
import { MinhaNovaPage } from './components/MinhaNovaPage';
|
|
364
|
+
|
|
365
|
+
// No componente App
|
|
366
|
+
{location.pathname === '/minha-nova-pagina' && (
|
|
367
|
+
<MinhaNovaPage
|
|
368
|
+
sidebarExpanded={sidebarExpanded}
|
|
369
|
+
assistenteExpanded={assistenteExpanded}
|
|
370
|
+
onToggleSidebar={toggleSidebar}
|
|
371
|
+
onToggleAssistente={toggleAssistente}
|
|
372
|
+
/>
|
|
373
|
+
)}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Sub-Páginas (Nested Routes)
|
|
377
|
+
|
|
378
|
+
Quando criar uma **sub-página**:
|
|
379
|
+
|
|
380
|
+
#### 1. Estrutura de arquivos
|
|
381
|
+
```
|
|
382
|
+
/components/PaginaPrincipal.tsx
|
|
383
|
+
/components/PaginaPrincipalContent.tsx
|
|
384
|
+
/components/SubPagina.tsx (se necessário página separada)
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
#### 2. Adicionar ao routes.tsx com hierarquia
|
|
388
|
+
```tsx
|
|
389
|
+
export const routes: RouteConfig[] = [
|
|
390
|
+
{
|
|
391
|
+
path: '/pagina-principal',
|
|
392
|
+
label: 'Página Principal',
|
|
393
|
+
icon: MainIcon,
|
|
394
|
+
children: [
|
|
395
|
+
{
|
|
396
|
+
path: '/pagina-principal/sub-pagina',
|
|
397
|
+
label: 'Sub Página',
|
|
398
|
+
icon: SubIcon,
|
|
399
|
+
}
|
|
400
|
+
]
|
|
401
|
+
},
|
|
402
|
+
];
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
#### 3. Renderizar sub-navegação na página pai
|
|
406
|
+
```tsx
|
|
407
|
+
// Na PaginaPrincipalContent.tsx
|
|
408
|
+
<Tabs defaultValue="overview">
|
|
409
|
+
<TabsList>
|
|
410
|
+
<TabsTrigger value="overview">Visão Geral</TabsTrigger>
|
|
411
|
+
<TabsTrigger value="sub-pagina">Sub Página</TabsTrigger>
|
|
412
|
+
</TabsList>
|
|
413
|
+
|
|
414
|
+
<TabsContent value="overview">
|
|
415
|
+
{/* Conteúdo principal */}
|
|
416
|
+
</TabsContent>
|
|
417
|
+
|
|
418
|
+
<TabsContent value="sub-pagina">
|
|
419
|
+
{/* Conteúdo da sub-página */}
|
|
420
|
+
</TabsContent>
|
|
421
|
+
</Tabs>
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
#### 4. Ou usar navegação tradicional
|
|
425
|
+
```tsx
|
|
426
|
+
<Button onClick={() => navigate('/pagina-principal/sub-pagina')}>
|
|
427
|
+
Ir para Sub Página
|
|
428
|
+
</Button>
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## 🎨 Tailwind CSS v4.0
|
|
434
|
+
|
|
435
|
+
### Uso Correto
|
|
436
|
+
|
|
437
|
+
**SEMPRE**:
|
|
438
|
+
- ✅ Use classes utilitárias do Tailwind
|
|
439
|
+
- ✅ Use arbitrary values quando necessário: `bg-[var(--primary)]`
|
|
440
|
+
- ✅ Use variáveis CSS: `text-[var(--foreground)]`
|
|
441
|
+
- ✅ Use classes responsivas: `md:grid-cols-2 lg:grid-cols-3`
|
|
442
|
+
|
|
443
|
+
**NUNCA**:
|
|
444
|
+
- ❌ Crie classes CSS customizadas (exceto em casos extremos)
|
|
445
|
+
- ❌ Use inline styles (use classes Tailwind)
|
|
446
|
+
- ❌ Modifique `/styles/xertica/tokens.css` sem aprovação
|
|
447
|
+
- ❌ Crie `tailwind.config.js` (estamos usando v4.0)
|
|
448
|
+
|
|
449
|
+
### Classes Proibidas (a menos que solicitado)
|
|
450
|
+
```css
|
|
451
|
+
/* NÃO use sem solicitação explícita */
|
|
452
|
+
text-xl, text-2xl, text-3xl /* Font sizes */
|
|
453
|
+
font-bold, font-semibold /* Font weights */
|
|
454
|
+
leading-tight, leading-relaxed /* Line heights */
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
---
|
|
458
|
+
|
|
459
|
+
## 📦 Bibliotecas e Imports
|
|
460
|
+
|
|
461
|
+
### Bibliotecas Aprovadas
|
|
462
|
+
|
|
463
|
+
#### Ícones (OBRIGATÓRIO)
|
|
464
|
+
```tsx
|
|
465
|
+
import { IconName } from 'lucide-react';
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
#### Gráficos
|
|
469
|
+
```tsx
|
|
470
|
+
import { ... } from 'recharts';
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
#### Animações
|
|
474
|
+
```tsx
|
|
475
|
+
import { motion } from 'motion/react'; // Nome atualizado (não Framer Motion)
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
#### Carrosséis
|
|
479
|
+
```tsx
|
|
480
|
+
import { ... } from 'react-slick';
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
#### Drag & Drop
|
|
484
|
+
```tsx
|
|
485
|
+
import { ... } from 'react-dnd';
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
#### Formulários
|
|
489
|
+
```tsx
|
|
490
|
+
import { ... } from 'react-hook-form@7.55.0'; // Versão específica obrigatória
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
#### Toast
|
|
494
|
+
```tsx
|
|
495
|
+
import { toast } from 'sonner@2.0.3'; // Versão específica obrigatória
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### Bibliotecas Proibidas
|
|
499
|
+
- ❌ `konva` / `react-konva` (não suportado)
|
|
500
|
+
- ❌ `react-resizable` (use `re-resizable` ao invés)
|
|
501
|
+
- ❌ Qualquer biblioteca de ícones além do `lucide-react`
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
## 🔄 Temas e Troca de Tema
|
|
506
|
+
|
|
507
|
+
O sistema suporta troca de temas via atributo `data-theme` no root:
|
|
508
|
+
|
|
509
|
+
```tsx
|
|
510
|
+
// Uso do ThemeToggle
|
|
511
|
+
import { ThemeToggle } from './ThemeToggle';
|
|
512
|
+
|
|
513
|
+
<ThemeToggle />
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
Temas disponíveis são gerenciados em `/styles/xertica/theme-map.css`.
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
## 🌐 Internacionalização
|
|
521
|
+
|
|
522
|
+
O sistema possui suporte a múltiplos idiomas:
|
|
523
|
+
|
|
524
|
+
```tsx
|
|
525
|
+
import { LanguageSelector } from './LanguageSelector';
|
|
526
|
+
|
|
527
|
+
<LanguageSelector variant="minimal" showIcon={false} />
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
## 📝 Boas Práticas Gerais
|
|
533
|
+
|
|
534
|
+
### Estrutura de Arquivos
|
|
535
|
+
```
|
|
536
|
+
/components/
|
|
537
|
+
/ui/ ← Componentes do Design System (NÃO MODIFICAR)
|
|
538
|
+
/examples/ ← Exemplos de uso
|
|
539
|
+
/media/ ← Componentes de mídia
|
|
540
|
+
MinhaPage.tsx ← Página wrapper
|
|
541
|
+
MinhaPageContent.tsx ← Conteúdo da página
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### Nomenclatura
|
|
545
|
+
- **Páginas**: `NomePage.tsx` e `NomePageContent.tsx`
|
|
546
|
+
- **Componentes**: `PascalCase.tsx`
|
|
547
|
+
- **Utilitários**: `camelCase.ts`
|
|
548
|
+
- **Rotas**: `kebab-case` (`/minha-pagina`)
|
|
549
|
+
|
|
550
|
+
### Imports
|
|
551
|
+
```tsx
|
|
552
|
+
// Componentes UI (sempre de /ui/)
|
|
553
|
+
import { Button } from './ui/button';
|
|
554
|
+
import { Card, CardHeader } from './ui/card';
|
|
555
|
+
|
|
556
|
+
// Ícones (sempre lucide-react)
|
|
557
|
+
import { Home, Settings } from 'lucide-react';
|
|
558
|
+
|
|
559
|
+
// Contextos
|
|
560
|
+
import { useTheme } from '../contexts/ThemeContext';
|
|
561
|
+
|
|
562
|
+
// Router
|
|
563
|
+
import { useNavigate, useLocation } from 'react-router';
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
### Responsividade
|
|
567
|
+
Sempre use breakpoints mobile-first:
|
|
568
|
+
```tsx
|
|
569
|
+
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
|
|
570
|
+
className="p-2 sm:p-4 md:p-6"
|
|
571
|
+
className="text-sm md:text-base"
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
### Acessibilidade
|
|
575
|
+
- Use labels em inputs
|
|
576
|
+
- Use aria-labels quando necessário
|
|
577
|
+
- Mantenha contraste adequado (use variáveis do design system)
|
|
578
|
+
- Suporte navegação por teclado
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
## 🚀 CLI-Ready e Portabilidade
|
|
583
|
+
|
|
584
|
+
### Princípios CLI-First
|
|
585
|
+
|
|
586
|
+
Todos os componentes devem:
|
|
587
|
+
1. ✅ Ser independentes e não depender de CSS global oculto
|
|
588
|
+
2. ✅ Usar apenas variáveis CSS semânticas de `tokens.css`
|
|
589
|
+
3. ✅ Funcionar quando copiados para outro projeto
|
|
590
|
+
4. ✅ Ter zero dependências de arquivos externos (exceto tokens.css)
|
|
591
|
+
5. ✅ Ser publicáveis no NPM sem modificações
|
|
592
|
+
|
|
593
|
+
### Overrides Opt-in
|
|
594
|
+
|
|
595
|
+
Componentes podem ter overrides específicos usando atributos `data-*`:
|
|
596
|
+
|
|
597
|
+
```tsx
|
|
598
|
+
<div data-xertica-chat="true">
|
|
599
|
+
{/* Componente com estilo específico de chat */}
|
|
600
|
+
</div>
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
Esses overrides são definidos em `/styles/xertica/app-overrides/`.
|
|
604
|
+
|
|
605
|
+
---
|
|
606
|
+
|
|
607
|
+
## ✅ Checklist: Antes de Criar Algo Novo
|
|
608
|
+
|
|
609
|
+
Antes de criar qualquer componente ou página:
|
|
610
|
+
|
|
611
|
+
- [ ] Consultei `/components/ui/` para ver se já existe?
|
|
612
|
+
- [ ] Posso combinar componentes existentes ao invés de criar novo?
|
|
613
|
+
- [ ] Estou usando APENAS variáveis CSS de `tokens.css`?
|
|
614
|
+
- [ ] Estou usando APENAS ícones do `lucide-react`?
|
|
615
|
+
- [ ] Estou usando a fonte Roboto (definida em globals.css)?
|
|
616
|
+
- [ ] Segui a estrutura padrão de página (header, sidebar, conteúdo)?
|
|
617
|
+
- [ ] Adicionei a rota em `routes.tsx`?
|
|
618
|
+
- [ ] Adicionei card na Home (se página primária)?
|
|
619
|
+
- [ ] Adicionei roteamento em `App.tsx`?
|
|
620
|
+
- [ ] Testei responsividade (mobile, tablet, desktop)?
|
|
621
|
+
- [ ] O componente é portável e CLI-ready?
|
|
622
|
+
|
|
623
|
+
---
|
|
624
|
+
|
|
625
|
+
## 🎓 Exemplos de Referência
|
|
626
|
+
|
|
627
|
+
### Páginas Exemplo
|
|
628
|
+
- `/components/HomePage.tsx` e `/components/HomeContent.tsx`
|
|
629
|
+
- `/components/TemplatePage.tsx` e `/components/TemplateContent.tsx`
|
|
630
|
+
- `/components/LoginPage.tsx`
|
|
631
|
+
|
|
632
|
+
### Componentes Complexos
|
|
633
|
+
- `/components/Sidebar.tsx` (navegação com subitens)
|
|
634
|
+
- `/components/AssistenteXertica.tsx` (painel lateral)
|
|
635
|
+
- `/components/ui/xertica-assistant.tsx` (componente especializado)
|
|
636
|
+
|
|
637
|
+
### Uso de Componentes UI
|
|
638
|
+
- `/components/examples/` (diversos exemplos de componentes)
|
|
639
|
+
|
|
640
|
+
---
|
|
641
|
+
|
|
642
|
+
## 📌 Notas Finais
|
|
643
|
+
|
|
644
|
+
Este Design System foi construído para ser:
|
|
645
|
+
- **Consistente**: Todos usam as mesmas variáveis e componentes
|
|
646
|
+
- **Escalável**: Fácil adicionar novas páginas e funcionalidades
|
|
647
|
+
- **Portável**: Componentes funcionam em qualquer projeto React
|
|
648
|
+
- **Profissional**: Pronto para publicação no NPM
|
|
649
|
+
- **Manutenível**: Estrutura clara e bem documentada
|
|
650
|
+
|
|
651
|
+
**Lembre-se**: Quando em dúvida, consulte os componentes existentes e siga os padrões estabelecidos. A consistência é a chave para um Design System de sucesso.
|
|
652
|
+
|
|
653
|
+
---
|
|
654
|
+
|
|
655
|
+
**Última atualização**: Janeiro 2025
|
|
656
|
+
**Versão**: 1.1.0
|
|
657
|
+
**Arquitetura**: CLI-First (modelo shadcn/ui)
|
|
658
|
+
**Status**: 100% CLI-Ready | Pronto para NPM
|