@tabl.io/ui 0.1.0 → 0.2.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/README.md CHANGED
@@ -1,73 +1,311 @@
1
- # React + TypeScript + Vite
1
+ # 🎨 Tabl UI - Design System Components
2
2
 
3
- This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
3
+ Sistema de componentes React para as aplicações Tabl (PDV, KDS, Manager).
4
4
 
5
- Currently, two official plugins are available:
5
+ ## Storybook
6
+ Acesse a documentação visual dos componentes:
7
+ [README.stories.md](./README.stories.md)
6
8
 
7
- - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
8
- - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9
+ ## 📦 Estrutura dos Arquivos
9
10
 
10
- ## React Compiler
11
+ ```
12
+ src/
13
+ ├── components/
14
+ │ └── app/
15
+ │ ├── layout/ # Componentes de layout
16
+ │ │ ├── app-header.tsx
17
+ │ │ ├── cart-indicator.tsx
18
+ │ │ ├── quantity-stepper.tsx
19
+ │ │ └── index.ts
20
+ │ ├── table/ # Componentes de mesa
21
+ │ │ ├── table-grid.tsx
22
+ │ │ ├── table-card.tsx
23
+ │ │ ├── table-badge.tsx
24
+ │ │ └── index.ts
25
+ │ ├── category/ # Componentes de categoria
26
+ │ │ ├── category-tabs.tsx
27
+ │ │ ├── category-pill.tsx
28
+ │ │ └── index.ts
29
+ │ ├── product/ # Componentes de produto
30
+ │ │ ├── product-grid.tsx
31
+ │ │ ├── product-card.tsx
32
+ │ │ ├── product-price-display.tsx
33
+ │ │ ├── product-detail-modal.tsx
34
+ │ │ ├── ingredient-list.tsx
35
+ │ │ ├── ingredient-checkbox.tsx
36
+ │ │ ├── extra-checkbox.tsx
37
+ │ │ └── index.ts
38
+ │ ├── cart/ # Componentes de carrinho
39
+ │ │ ├── cart-sheet.tsx
40
+ │ │ ├── cart-item.tsx
41
+ │ │ ├── cart-summary.tsx
42
+ │ │ ├── cart-empty-state.tsx
43
+ │ │ └── index.ts
44
+ │ ├── order/ # Componentes de pedido
45
+ │ │ ├── order-confirmation-modal.tsx
46
+ │ │ ├── order-loading-state.tsx
47
+ │ │ └── index.ts
48
+ │ └── index.ts
49
+ ├── lib/
50
+ │ └── format.ts # Helpers de formatação
51
+ └── foundation/
52
+ └── tokens.css # Sistema de tokens modulares
53
+ ```
54
+
55
+ ## 🎯 Instalação dos Componentes Shadcn
56
+
57
+ Execute no terminal do pacote @tabl.io/ui:
58
+
59
+ ```bash
60
+ # Componentes primitivos necessários
61
+ npx shadcn@latest add card
62
+ npx shadcn@latest add badge
63
+ npx shadcn@latest add dialog
64
+ npx shadcn@latest add sheet
65
+ npx shadcn@latest add scroll-area
66
+ npx shadcn@latest add separator
67
+ npx shadcn@latest add skeleton
68
+ npx shadcn@latest add sonner
69
+ npx shadcn@latest add checkbox
70
+ npx shadcn@latest add label
71
+ ```
72
+
73
+ ## 🔧 Configuração
74
+
75
+ ### 1. Substituir `src/foundation/tokens.css`
76
+
77
+ Copie o novo arquivo `tokens.css` para `src/foundation/tokens.css`.
78
+
79
+ Este arquivo adiciona suporte a temas por módulo usando o atributo `data-module`:
80
+ - `data-module="core"` → Verde (Emerald)
81
+ - `data-module="pdv"` → Laranja (Orange)
82
+ - `data-module="kds"` → Azul (Blue)
83
+ - `data-module="manager"` → Roxo (Violet)
84
+ - `data-module="analytics"` → Âmbar (Amber)
85
+
86
+ ### 2. Adicionar `src/lib/format.ts`
87
+
88
+ Copie o arquivo `format.ts` para `src/lib/format.ts`.
11
89
 
12
- The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
90
+ Contém helpers de formatação:
91
+ - `formatCurrency(value)` → "R$ 1.234,56"
92
+ - `formatTime(seconds)` → "01:30"
93
+ - `formatDuration(seconds)` → "1h 30min"
94
+ - `formatPhone(phone)` → "(11) 98765-4321"
95
+ - `truncate(text, maxLength)` → "Lorem ipsu..."
96
+ - `pluralize(count, singular, plural?)` → "2 itens"
13
97
 
14
- ## Expanding the ESLint configuration
98
+ ### 3. Copiar componentes para `src/components/app/`
15
99
 
16
- If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
100
+ Copie toda a estrutura de pastas `components/app/` mantendo a hierarquia.
17
101
 
18
- ```js
19
- export default defineConfig([
20
- globalIgnores(['dist']),
21
- {
22
- files: ['**/*.{ts,tsx}'],
23
- extends: [
24
- // Other configs...
102
+ ### 4. Atualizar `src/lib/utils.ts`
25
103
 
26
- // Remove tseslint.configs.recommended and replace with this
27
- tseslint.configs.recommendedTypeChecked,
28
- // Alternatively, use this for stricter rules
29
- tseslint.configs.strictTypeChecked,
30
- // Optionally, add this for stylistic rules
31
- tseslint.configs.stylisticTypeChecked,
104
+ Adicione o export do format.ts:
32
105
 
33
- // Other configs...
34
- ],
35
- languageOptions: {
36
- parserOptions: {
37
- project: ['./tsconfig.node.json', './tsconfig.app.json'],
38
- tsconfigRootDir: import.meta.dirname,
39
- },
40
- // other options...
41
- },
42
- },
43
- ])
106
+ ```typescript
107
+ export * from "./format"
44
108
  ```
45
109
 
46
- You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
47
-
48
- ```js
49
- // eslint.config.js
50
- import reactX from 'eslint-plugin-react-x'
51
- import reactDom from 'eslint-plugin-react-dom'
52
-
53
- export default defineConfig([
54
- globalIgnores(['dist']),
55
- {
56
- files: ['**/*.{ts,tsx}'],
57
- extends: [
58
- // Other configs...
59
- // Enable lint rules for React
60
- reactX.configs['recommended-typescript'],
61
- // Enable lint rules for React DOM
62
- reactDom.configs.recommended,
63
- ],
64
- languageOptions: {
65
- parserOptions: {
66
- project: ['./tsconfig.node.json', './tsconfig.app.json'],
67
- tsconfigRootDir: import.meta.dirname,
68
- },
69
- // other options...
70
- },
71
- },
72
- ])
110
+ ### 5. Atualizar `src/components/index.ts`
111
+
112
+ Já deve estar correto:
113
+
114
+ ```typescript
115
+ export * from "./ui"
116
+ export * from "./app"
117
+ ```
118
+
119
+ ## 🚀 Uso no PDV
120
+
121
+ ### Configuração do Módulo
122
+
123
+ No HTML root ou componente principal do PDV, adicione o atributo `data-module`:
124
+
125
+ ```tsx
126
+ // pdv/src/App.tsx ou index.html
127
+ <html data-module="pdv">
128
+ {/* ... */}
129
+ </html>
130
+ ```
131
+
132
+ Ou via React:
133
+
134
+ ```tsx
135
+ useEffect(() => {
136
+ document.documentElement.setAttribute('data-module', 'pdv')
137
+ }, [])
73
138
  ```
139
+
140
+ ### Exemplo: Página de Mesas
141
+
142
+ ```tsx
143
+ import { AppHeader, TableGrid, TableCard } from "@tabl.io/ui"
144
+
145
+ function TablesPage() {
146
+ return (
147
+ <div className="h-screen flex flex-col">
148
+ <AppHeader title="Mesas" />
149
+
150
+ <TableGrid>
151
+ {tables.map(table => (
152
+ <TableCard
153
+ key={table.id}
154
+ number={table.number}
155
+ status={table.status}
156
+ onClick={() => handleSelectTable(table)}
157
+ />
158
+ ))}
159
+ </TableGrid>
160
+ </div>
161
+ )
162
+ }
163
+ ```
164
+
165
+ ### Exemplo: Página de Produtos
166
+
167
+ ```tsx
168
+ import {
169
+ AppHeader,
170
+ CartIndicator,
171
+ CategoryTabs,
172
+ ProductGrid,
173
+ ProductCard,
174
+ ProductDetailModal,
175
+ CartSheet,
176
+ } from "@tabl.io/ui"
177
+
178
+ function ProductsPage() {
179
+ const [selectedProduct, setSelectedProduct] = useState(null)
180
+ const [isCartOpen, setIsCartOpen] = useState(false)
181
+
182
+ return (
183
+ <div className="h-screen flex flex-col">
184
+ <AppHeader
185
+ title={`Mesa ${tableNumber}`}
186
+ showBack
187
+ onBack={() => navigate('/tables')}
188
+ actions={
189
+ <CartIndicator
190
+ count={cartItems.length}
191
+ total={cartTotal}
192
+ onClick={() => setIsCartOpen(true)}
193
+ />
194
+ }
195
+ />
196
+
197
+ <CategoryTabs
198
+ categories={categories}
199
+ activeCategory={activeCategory}
200
+ onSelectCategory={setActiveCategory}
201
+ />
202
+
203
+ <ProductGrid>
204
+ {products.map(product => (
205
+ <ProductCard
206
+ key={product.id}
207
+ product={product}
208
+ onClick={() => setSelectedProduct(product)}
209
+ />
210
+ ))}
211
+ </ProductGrid>
212
+
213
+ <ProductDetailModal
214
+ open={!!selectedProduct}
215
+ onOpenChange={(open) => !open && setSelectedProduct(null)}
216
+ product={selectedProduct}
217
+ removableIngredients={removableIngredients}
218
+ availableExtras={availableExtras}
219
+ onAddToCart={handleAddToCart}
220
+ />
221
+
222
+ <CartSheet
223
+ open={isCartOpen}
224
+ onOpenChange={setIsCartOpen}
225
+ items={cartItems}
226
+ onQuantityChange={handleUpdateQuantity}
227
+ onRemoveItem={handleRemoveItem}
228
+ onConfirmOrder={handleConfirmOrder}
229
+ loading={isSubmitting}
230
+ />
231
+ </div>
232
+ )
233
+ }
234
+ ```
235
+
236
+ ## 📚 Componentes Disponíveis
237
+
238
+ ### Layout
239
+ - `AppHeader` - Cabeçalho padrão com título, voltar e actions
240
+ - `CartIndicator` - Badge flutuante de carrinho
241
+ - `QuantityStepper` - Controle de quantidade
242
+
243
+ ### Table
244
+ - `TableGrid` - Grid responsivo de mesas
245
+ - `TableCard` - Card individual de mesa
246
+ - `TableBadge` - Badge de status
247
+
248
+ ### Category
249
+ - `CategoryTabs` - Navegação horizontal de categorias
250
+ - `CategoryPill` - Pill individual de categoria
251
+
252
+ ### Product
253
+ - `ProductGrid` - Grid responsivo de produtos
254
+ - `ProductCard` - Card de produto com imagem e preço
255
+ - `ProductPriceDisplay` - Exibe cálculo de preço
256
+ - `ProductDetailModal` - Modal de customização
257
+ - `IngredientList` - Wrapper de lista de ingredientes
258
+ - `IngredientCheckbox` - Checkbox de ingrediente removível
259
+ - `ExtraCheckbox` - Checkbox de extra pago
260
+
261
+ ### Cart
262
+ - `CartSheet` - Sheet lateral completo
263
+ - `CartItem` - Item individual no carrinho
264
+ - `CartSummary` - Resumo e botão de confirmar
265
+ - `CartEmptyState` - Estado vazio
266
+
267
+ ### Order
268
+ - `OrderConfirmationModal` - Modal de sucesso
269
+ - `OrderLoadingState` - Estado de loading
270
+
271
+ ## 🎨 Sistema de Cores por Módulo
272
+
273
+ | Módulo | Cor | Uso |
274
+ |--------|-----|-----|
275
+ | Core | Emerald (#10B981) | Base, configurações, sync |
276
+ | PDV | Orange (#F97316) | Ponto de venda, vendas |
277
+ | KDS | Blue (#3B82F6) | Cozinha, produção |
278
+ | Manager | Violet (#8B5CF6) | Backoffice, cadastros |
279
+ | Analytics | Amber (#F59E0B) | IA, insights (futuro) |
280
+
281
+ ## 🔄 Próximos Passos
282
+
283
+ 1. ✅ Instalar componentes Shadcn
284
+ 2. ✅ Copiar arquivos para o pacote
285
+ 3. ✅ Configurar `data-module="pdv"` no PDV
286
+ 4. 🚧 Implementar páginas do PDV
287
+ 5. 🚧 Criar hooks customizados (useCart, useOrder, etc)
288
+ 6. 🚧 Adicionar testes
289
+ 7. 🚧 Documentar no Storybook
290
+
291
+ ## 📝 Notas Importantes
292
+
293
+ - Todos os componentes suportam dark mode automático via `prefers-color-scheme`
294
+ - Use `data-module` para trocar entre temas de módulos
295
+ - Componentes são totalmente tipados com TypeScript
296
+ - Helpers de formatação estão em `@tabl.io/ui/lib/format`
297
+ - Siga o padrão de imports: `import { Component } from "@tabl.io/ui"`
298
+
299
+ ## 🐛 Troubleshooting
300
+
301
+ **Componentes não encontrados?**
302
+ - Verifique se os exports estão corretos nos `index.ts`
303
+ - Confira o `package.json` do @tabl.io/ui
304
+
305
+ **Cores não mudando?**
306
+ - Verifique se `data-module` está no elemento raiz
307
+ - Confirme que `tokens.css` foi substituído
308
+
309
+ **Helpers não disponíveis?**
310
+ - Certifique-se que `format.ts` está em `src/lib/`
311
+ - Verifique export em `src/lib/utils.ts`
@@ -0,0 +1,226 @@
1
+ # 📚 Storybook Stories - Tabl UI
2
+
3
+ Documentação interativa de todos os componentes do design system Tabl.
4
+
5
+ ## 📂 Estrutura dos Arquivos
6
+
7
+ Copie todos os arquivos `.stories.tsx` para `/.storybook/stories/` mantendo a estrutura de pastas:
8
+
9
+ ```
10
+ /.storybook/stories/
11
+ ├── layout/
12
+ │ ├── app-header.stories.tsx
13
+ │ └── cart-indicator.stories.tsx
14
+ ├── table/
15
+ │ ├── table-badge.stories.tsx
16
+ │ ├── table-card.stories.tsx
17
+ │ └── table-grid.stories.tsx
18
+ ├── category/
19
+ │ ├── category-pill.stories.tsx
20
+ │ └── category-tabs.stories.tsx
21
+ ├── product/
22
+ │ ├── product-card.stories.tsx
23
+ │ ├── product-grid.stories.tsx
24
+ │ ├── product-price-display.stories.tsx
25
+ │ ├── product-detail-modal.stories.tsx
26
+ │ └── ingredients.stories.tsx
27
+ ├── cart/
28
+ │ ├── cart-item.stories.tsx
29
+ │ ├── cart-states.stories.tsx (CartEmptyState + CartSummary)
30
+ │ └── cart-sheet.stories.tsx
31
+ ├── order/
32
+ │ ├── order-loading-state.stories.tsx
33
+ │ └── order-confirmation-modal.stories.tsx
34
+ ├── shared/
35
+ │ └── quantity-stepper.stories.tsx
36
+ └── complete-flow.stories.tsx (Exemplo de fluxo completo)
37
+ ```
38
+
39
+ ## 🚀 Como Usar
40
+
41
+ ### 1. Copiar arquivos
42
+
43
+ ```bash
44
+ # Na raiz do @tabl.io/ui
45
+ cp -r /path/to/storybook-stories/* ./.storybook/stories/
46
+ ```
47
+
48
+ ### 2. Iniciar Storybook
49
+
50
+ ```bash
51
+ npm run storybook
52
+ ```
53
+
54
+ ### 3. Acessar
55
+
56
+ Abra o navegador em `http://localhost:6006`
57
+
58
+ ## 📖 Estrutura das Stories
59
+
60
+ Todas as stories seguem o padrão Storybook CSF 3.0:
61
+
62
+ ```typescript
63
+ import type { Meta, StoryObj } from "@storybook/react"
64
+ import { Component } from "@/components/..."
65
+
66
+ const meta = {
67
+ title: "App/Category/Component",
68
+ component: Component,
69
+ tags: ["autodocs"],
70
+ argTypes: {
71
+ onClick: { action: "clicked" },
72
+ },
73
+ } satisfies Meta<typeof Component>
74
+
75
+ export default meta
76
+ type Story = StoryObj<typeof meta>
77
+
78
+ export const Default: Story = {
79
+ args: {
80
+ // props aqui
81
+ },
82
+ }
83
+ ```
84
+
85
+ ## 🎨 Stories Criadas (19 arquivos)
86
+
87
+ ### Layout (2)
88
+ - ✅ AppHeader - 5 variações (default, com subtitle, com back, com cart, completo)
89
+ - ✅ CartIndicator - 4 variações (vazio, 1 item, múltiplos, grande)
90
+
91
+ ### Table (3)
92
+ - ✅ TableBadge - 4 variações (available, occupied, reserved, todos)
93
+ - ✅ TableCard - 4 variações (available, occupied, reserved, todos)
94
+ - ✅ TableGrid - 3 variações (default, poucas mesas, muitas mesas)
95
+
96
+ ### Category (2)
97
+ - ✅ CategoryPill - 4 variações (default, ativo, nome longo, múltiplos)
98
+ - ✅ CategoryTabs - 4 variações (default, sem seleção, muitas categorias, interativo)
99
+
100
+ ### Product (5)
101
+ - ✅ ProductCard - 6 variações (default, com imagem, longo, inativo, sem descrição, preço alto)
102
+ - ✅ ProductGrid - 3 variações (default, poucos, muitos)
103
+ - ✅ ProductPriceDisplay - 6 variações (base, com extras, muitos extras, baixo, alto, todas)
104
+ - ✅ Ingredients - 3 variações (remover, adicionar, ambos)
105
+ - ✅ ProductDetailModal - 6 variações (default, sem imagem, só ingredientes, só extras, simples, interativo)
106
+
107
+ ### Cart (3)
108
+ - ✅ CartItem - 7 variações (simples, com extras, removidos, notas, completo, múltipla qtd, alto preço)
109
+ - ✅ CartStates - 6 variações (empty, small, medium, large, loading, empty cart)
110
+ - ✅ CartSheet - 6 variações (com itens, vazio, loading, um item, muitos, interativo)
111
+
112
+ ### Order (2)
113
+ - ✅ OrderLoadingState - 3 variações (default, custom message, long message)
114
+ - ✅ OrderConfirmationModal - 5 variações (default, small, large, sem ID, interativo)
115
+
116
+ ### Shared (1)
117
+ - ✅ QuantityStepper - 8 variações (default, min, max, at max, small, large, interativo, all sizes)
118
+
119
+ ### Examples (1)
120
+ - ✅ Complete PDV Flow - Exemplo de fluxo completo integrado
121
+
122
+ ## 🎯 Funcionalidades
123
+
124
+ ### Documentação Automática
125
+ Todas as stories têm `tags: ["autodocs"]` que gera documentação automática das props.
126
+
127
+ ### Actions
128
+ Componentes com callbacks têm actions configuradas para visualizar eventos no painel Actions do Storybook.
129
+
130
+ ### Interatividade
131
+ Stories marcadas como "Interactive" permitem interação real com estado gerenciado pelo React.
132
+
133
+ ## 📝 Próximos Passos
134
+
135
+ 1. ✅ Copiar arquivos de stories
136
+ 2. ✅ Iniciar Storybook
137
+ 3. 🚧 Personalizar stories conforme necessário
138
+ 4. 🚧 Adicionar mais variações específicas do seu contexto
139
+ 5. 🚧 Documentar padrões de uso nos comentários
140
+
141
+ ## 💡 Dicas
142
+
143
+ ### Adicionar Nova Story
144
+
145
+ ```typescript
146
+ export const MinhaNovaVariacao: Story = {
147
+ args: {
148
+ // suas props aqui
149
+ },
150
+ }
151
+ ```
152
+
153
+ ### Story com Render Customizado
154
+
155
+ ```typescript
156
+ export const CustomRender: Story = {
157
+ render: () => {
158
+ const [state, setState] = useState(...)
159
+ return <Component {...} />
160
+ },
161
+ }
162
+ ```
163
+
164
+ ### Adicionar Controls Personalizados
165
+
166
+ ```typescript
167
+ const meta = {
168
+ // ...
169
+ argTypes: {
170
+ variant: {
171
+ control: 'select',
172
+ options: ['default', 'primary', 'secondary'],
173
+ },
174
+ },
175
+ }
176
+ ```
177
+
178
+ ## 🐛 Troubleshooting
179
+
180
+ **Imports não encontrados?**
181
+ - Verifique se os paths do `@/components` estão corretos no tsconfig
182
+
183
+ **Componentes não renderizam?**
184
+ - Certifique-se que todos os componentes shadcn estão instalados
185
+ - Verifique se o `index.css` está sendo importado
186
+
187
+ **Estilos não aplicados?**
188
+ - Confirme que o Tailwind está configurado no Storybook preview
189
+ - Verifique se `data-module` está sendo aplicado quando necessário
190
+
191
+ ## 🎨 Temas no Storybook
192
+
193
+ Para testar os diferentes módulos, adicione no `.storybook/preview.tsx`:
194
+
195
+ ```typescript
196
+ export const decorators = [
197
+ (Story, context) => {
198
+ const module = context.parameters.module || 'pdv'
199
+ return (
200
+ <div data-module={module}>
201
+ <Story />
202
+ </div>
203
+ )
204
+ },
205
+ ]
206
+
207
+ export const globalTypes = {
208
+ module: {
209
+ name: 'Module',
210
+ description: 'Tabl module theme',
211
+ defaultValue: 'pdv',
212
+ toolbar: {
213
+ icon: 'paintbrush',
214
+ items: [
215
+ { value: 'core', title: 'Core (Verde)' },
216
+ { value: 'pdv', title: 'PDV (Laranja)' },
217
+ { value: 'kds', title: 'KDS (Azul)' },
218
+ { value: 'manager', title: 'Manager (Roxo)' },
219
+ { value: 'analytics', title: 'Analytics (Âmbar)' },
220
+ ],
221
+ },
222
+ },
223
+ }
224
+ ```
225
+
226
+ Isso adiciona um seletor de módulo na toolbar do Storybook! 🎨