@snksergio/design-system 0.61.0 → 0.62.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/dist-lib/ai/componentes/AlertModal.md +47 -0
- package/dist-lib/ai/componentes/AppShell.md +117 -0
- package/dist-lib/ai/componentes/Breadcrumb.md +187 -0
- package/dist-lib/ai/componentes/Button.md +116 -0
- package/dist-lib/ai/componentes/ButtonGroup.md +162 -0
- package/dist-lib/ai/componentes/CardCheckbox.md +99 -0
- package/dist-lib/ai/componentes/CardOption.md +133 -0
- package/dist-lib/ai/componentes/Chart.md +93 -0
- package/dist-lib/ai/componentes/Chip.md +68 -0
- package/dist-lib/ai/componentes/ChoroplethMap.md +118 -0
- package/dist-lib/ai/componentes/ColorPicker.md +70 -0
- package/dist-lib/ai/componentes/Combobox.md +51 -0
- package/dist-lib/ai/componentes/ConversationListItem.md +90 -0
- package/dist-lib/ai/componentes/DataList.md +111 -0
- package/dist-lib/ai/componentes/DataTable.md +867 -0
- package/dist-lib/ai/componentes/DatePicker.md +84 -0
- package/dist-lib/ai/componentes/DateSeparatorChip.md +59 -0
- package/dist-lib/ai/componentes/EmptyState.md +72 -0
- package/dist-lib/ai/componentes/FileUploadField.md +95 -0
- package/dist-lib/ai/componentes/FloatingPanel.md +118 -0
- package/dist-lib/ai/componentes/FooterTable.md +62 -0
- package/dist-lib/ai/componentes/FormField.md +110 -0
- package/dist-lib/ai/componentes/Gantt.md +552 -0
- package/dist-lib/ai/componentes/Header.md +98 -0
- package/dist-lib/ai/componentes/Icon.md +65 -0
- package/dist-lib/ai/componentes/Kanban.md +343 -0
- package/dist-lib/ai/componentes/Kpi.md +103 -0
- package/dist-lib/ai/componentes/List.md +61 -0
- package/dist-lib/ai/componentes/MarkdownText.md +59 -0
- package/dist-lib/ai/componentes/MenuSidebar.md +128 -0
- package/dist-lib/ai/componentes/MessageAck.md +53 -0
- package/dist-lib/ai/componentes/MessageBubble.md +115 -0
- package/dist-lib/ai/componentes/MessageComposer.md +80 -0
- package/dist-lib/ai/componentes/MessageVariablesPicker.md +104 -0
- package/dist-lib/ai/componentes/Modal.md +88 -0
- package/dist-lib/ai/componentes/MonthYearPicker.md +49 -0
- package/dist-lib/ai/componentes/PageHeader.md +129 -0
- package/dist-lib/ai/componentes/Panel.md +84 -0
- package/dist-lib/ai/componentes/Scheduler.md +421 -0
- package/dist-lib/ai/componentes/ScreenLoader.md +60 -0
- package/dist-lib/ai/componentes/SingleMenuSidebar.md +171 -0
- package/dist-lib/ai/componentes/Spinner.md +52 -0
- package/dist-lib/ai/componentes/Table.md +192 -0
- package/dist-lib/ai/componentes/TableToolbar.md +87 -0
- package/dist-lib/ai/componentes/TabsNavigation.md +152 -0
- package/dist-lib/ai/componentes/Toast.md +49 -0
- package/dist-lib/ai/componentes/_primitivos.md +74 -0
- package/dist-lib/ai/componentes/avatar-ig.md +181 -0
- package/dist-lib/ai/componentes/indice.json +49 -0
- package/dist-lib/ai/exemplos/dashboard/dashboard-brazil-map.ts +33 -0
- package/dist-lib/ai/exemplos/dashboard/dashboard-screen.tsx +1110 -0
- package/dist-lib/ai/exemplos/dashboard/index.ts +1 -0
- package/dist-lib/ai/global/componentes.md +217 -0
- package/dist-lib/ai/global/composicao.md +182 -0
- package/dist-lib/ai/indice.json +177 -0
- package/dist-lib/ai/lint/ds-lint-patterns.mjs +115 -0
- package/dist-lib/ai/manifest.json +16 -0
- package/dist-lib/ai/regras/design.md +88 -0
- package/dist-lib/ai/regras/temas.md +192 -0
- package/dist-lib/ai/regras-por-componente.json +103 -0
- package/dist-lib/ai/roteiros/dashboard/blueprint.md +47 -0
- package/dist-lib/ai/roteiros/dashboard/entrevista.md +62 -0
- package/dist-lib/ai/roteiros/dashboard/geracao.md +88 -0
- package/dist-lib/ai/roteiros/dashboard/roteiro.md +88 -0
- package/package.json +4 -1
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# TabsNavigation
|
|
2
|
+
|
|
3
|
+
<!-- ds:regras
|
|
4
|
+
- aba de NAVEGADOR (sessão que abre/fecha: conversa, chamado, registro) → `<TabsNavigation>`; filtro de conteúdo dentro da tela → `tabs` do shadcn
|
|
5
|
+
- `<TabsNavigation>` é SEMPRE controlado (`value` + `onValueChange`) e NÃO hospeda conteúdo — o painel pode morar fora, e aí a aba leva `panelId`
|
|
6
|
+
- `surface` = a superfície do conteúdo ABAIXO da tira (`surface` num card, `canvas` na página). Errar quebra a união da aba ativa, que é o componente
|
|
7
|
+
- `actions` na aba SUBSTITUI o `⋯`+`×` — é por ele que entram ✓/✗ de aceitar/recusar; sem `actions` e sem `onClose` a aba não tem ação
|
|
8
|
+
-->
|
|
9
|
+
|
|
10
|
+
Tira de abas de **navegação**, estilo navegador: cada aba é uma **sessão aberta** — com
|
|
11
|
+
identidade, status e ações próprias — que o usuário abre, troca e fecha.
|
|
12
|
+
|
|
13
|
+
## Quando usar
|
|
14
|
+
|
|
15
|
+
| Situação | Componente |
|
|
16
|
+
|---|---|
|
|
17
|
+
| Conversas, chamados, registros abertos ao mesmo tempo; o usuário abre e fecha | **`TabsNavigation`** |
|
|
18
|
+
| Alternar seções DENTRO de uma tela (Detalhes / Anexos / Histórico) | `tabs` (shadcn) |
|
|
19
|
+
| Alternar visão de uma mesma lista (Tabela / Kanban) | `toggle-group` ou o `viewMode` do DataTable |
|
|
20
|
+
|
|
21
|
+
Os dois convivem: uma aba de conversa pode conter um `Tabs` de Mensagens/Notas dentro.
|
|
22
|
+
|
|
23
|
+
## Import
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import { TabsNavigation } from "@/components/ui/TabsNavigation";
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Exemplo mínimo
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
const [ativa, setAtiva] = useState("c1");
|
|
33
|
+
|
|
34
|
+
<TabsNavigation value={ativa} onValueChange={setAtiva} aria-label="Conversas abertas" onNewTab={abrir}>
|
|
35
|
+
<TabsNavigation.Tab
|
|
36
|
+
value="c1"
|
|
37
|
+
leading={<Avatar size="sm" colorHex="#2563EB">MS</Avatar>}
|
|
38
|
+
status="success"
|
|
39
|
+
badge={3}
|
|
40
|
+
onClose={() => fechar("c1")}
|
|
41
|
+
>
|
|
42
|
+
<TabsNavigation.Title>Maria Silva</TabsNavigation.Title>
|
|
43
|
+
<TabsNavigation.Subtitle>Fatura de julho</TabsNavigation.Subtitle>
|
|
44
|
+
</TabsNavigation.Tab>
|
|
45
|
+
</TabsNavigation>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## O conteúdo mora onde você quiser
|
|
49
|
+
|
|
50
|
+
O componente é a **tira**, não o roteador: ele diz qual aba está ativa e você troca o que
|
|
51
|
+
quiser, onde quiser.
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
{/* tira aqui… */}
|
|
55
|
+
<TabsNavigation value={id} onValueChange={setId}>
|
|
56
|
+
<TabsNavigation.Tab value="c1" panelId="painel-detalhe">…</TabsNavigation.Tab>
|
|
57
|
+
</TabsNavigation>
|
|
58
|
+
|
|
59
|
+
{/* …e o conteúdo em outra coluna, outra rota, outro componente */}
|
|
60
|
+
<section id="painel-detalhe">{conteudoDe(id)}</section>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- **Painel FORA** → `panelId` na aba (emite `aria-controls`).
|
|
64
|
+
- **Painel DENTRO** → `<TabsNavigation.Panel value="c1">`, que faz o par `role="tabpanel"` +
|
|
65
|
+
`aria-labelledby` e renderiza só a ativa.
|
|
66
|
+
- Sem nenhum dos dois o componente **não inventa** wiring — fica só `role="tab"` +
|
|
67
|
+
`aria-selected`, que é honesto.
|
|
68
|
+
|
|
69
|
+
## Props — `TabsNavigation`
|
|
70
|
+
|
|
71
|
+
| Prop | Tipo | Default | Descrição |
|
|
72
|
+
|---|---|---|---|
|
|
73
|
+
| `value` / `onValueChange` | `string` / `(v) => void` | — | sempre controlado |
|
|
74
|
+
| `surface` | `surface \| canvas` | `surface` | superfície do **conteúdo abaixo** — a aba ativa é pintada com ela |
|
|
75
|
+
| `density` | `comfortable \| compact` | `comfortable` | 48px com subtítulo · 40px sem |
|
|
76
|
+
| `fill` | `boolean` | `false` | aba ocupa a faixa inteira; a tira perde a régua |
|
|
77
|
+
| `actionsMode` | `hover \| persistent` | `hover` | ações reveladas no hover ou sempre visíveis |
|
|
78
|
+
| `chrome` | `boolean` | `true` | pinta o fundo recuado da tira |
|
|
79
|
+
| `onNewTab` | `() => void` | — | rende o `+` fora do trilho |
|
|
80
|
+
| `aria-label` | `string` | — | rótulo do conjunto |
|
|
81
|
+
|
|
82
|
+
## Props — `TabsNavigation.Tab`
|
|
83
|
+
|
|
84
|
+
| Prop | Tipo | Descrição |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| `value` | `string` | volta em `onValueChange` |
|
|
87
|
+
| `leading` | `ReactNode` | Avatar, `Icon`, imagem — qualquer nó |
|
|
88
|
+
| `status` | `success \| warning \| danger \| info \| neutral \| ReactNode` | ponto pronto, ou o seu |
|
|
89
|
+
| `badge` | `number \| ReactNode` | some na aba ativa |
|
|
90
|
+
| `actions` | `ReactNode` | **substitui** as ações padrão |
|
|
91
|
+
| `onClose` | `() => void` | sem `actions`, liga o `⋯` + `×` |
|
|
92
|
+
| `menu` | `ReactNode` | itens extras do `⋯` |
|
|
93
|
+
| `panelId` | `string` | id do container externo |
|
|
94
|
+
| `actionsAlwaysVisible` | `boolean` | ações fixas só nesta aba |
|
|
95
|
+
| `hoverCard` | `ReactNode` | resumo ao pousar o ponteiro (500ms); a aba ATIVA não mostra |
|
|
96
|
+
|
|
97
|
+
Peças: `TabsNavigation.Title` · `TabsNavigation.Subtitle` (some sozinho em `compact`) · `TabsNavigation.Action`
|
|
98
|
+
(botão de 24px, já com `stopPropagation`) · `TabsNavigation.Actions` (ações globais à direita) ·
|
|
99
|
+
`TabsNavigation.Panel`.
|
|
100
|
+
|
|
101
|
+
## Gotchas / cuidados
|
|
102
|
+
|
|
103
|
+
- **`surface` é a cor do que está EMBAIXO, e é o erro clássico.** A aba ativa precisa ser a
|
|
104
|
+
mesma superfície do conteúdo — é isso que as une. Num card `surface`; se o conteúdo for a
|
|
105
|
+
página, `canvas`. Com o token errado a aba parece pousada em cima de outra coisa.
|
|
106
|
+
- **`fill` troca o mecanismo da união, não só a altura.** No modo pousado a aba desce 1px e
|
|
107
|
+
apaga a régua; em `fill` a tira **não tem régua** e a união é por continuidade de cor.
|
|
108
|
+
Medido: manter o truque em `fill` deixava a aba 2px antes da régua — uma fresta, pior que
|
|
109
|
+
linha nenhuma.
|
|
110
|
+
- **O fundo recuado usa dois tokens, um por modo** (`bg-emphasis` no claro, `bg-canvas` no
|
|
111
|
+
escuro) — medido: no claro `canvas` é branco igual à `surface` e `subtle` quase não se lê
|
|
112
|
+
contra a aba branca; no escuro `emphasis` é branco a 12% SOBRE o fundo, mais claro que a
|
|
113
|
+
superfície. Cada modo tem o seu token de recuo; não procure um único.
|
|
114
|
+
- **⛔ Não envolva a tira num wrapper com padding.** O respiro do topo é do componente, e é
|
|
115
|
+
isso que a torna independente da superfície: quando o padding vinha de fora, aquela faixa
|
|
116
|
+
acima das abas ficava com a cor do container enquanto a tira ficava com o recuo — duas cores
|
|
117
|
+
na mesma banda, e a aba inativa parecia um botão de outra cor pousado num fundo diferente.
|
|
118
|
+
**A única coisa com fundo próprio é a aba ativa**, e ela é a superfície do conteúdo. Se o
|
|
119
|
+
container já pinta o recuo, desligue com `chrome={false}` em vez de compensar por fora.
|
|
120
|
+
- **Ação que exige decisão não vai no hover.** `hover` é certo pra `⋯`/`×`; pra aceitar/recusar
|
|
121
|
+
um chamado use `actions` + `actionsAlwaysVisible` — o usuário precisa **ver** pra decidir, e
|
|
122
|
+
recusar por engano tem custo.
|
|
123
|
+
- **As ações não reservam espaço** (coluna de grid `0fr → 1fr`): em repouso o título usa a aba
|
|
124
|
+
inteira. Se você passar `actions`, mantenha-as pequenas — a coluna abre por cima do título.
|
|
125
|
+
- **`density="compact"` é escolha de conteúdo.** Sem subtítulo, duas conversas do mesmo cliente
|
|
126
|
+
ficam idênticas.
|
|
127
|
+
- **As setas de overflow somem, não desabilitam.** Cada uma só existe enquanto houver o que
|
|
128
|
+
rolar naquele sentido; com a fila inteira visível não aparece nenhuma, e a lista `⌄` também
|
|
129
|
+
some. Botão apagado ocupa espaço e ainda lê como "tem algo aqui" — desabilitar faz sentido
|
|
130
|
+
quando a ação volta a valer no mesmo lugar, e aqui o gatilho é a largura da tira.
|
|
131
|
+
- **Teclado:** ←/→/Home/End movem seleção e foco juntos; só a aba ativa fica na ordem de
|
|
132
|
+
tabulação. Não recrie isso por fora.
|
|
133
|
+
- **jsdom não tem `ResizeObserver`** — o componente checa antes de instanciar, então ele não
|
|
134
|
+
derruba a suíte de quem consome. Em teste, os controles de overflow ficam ocultos (não há
|
|
135
|
+
medição de layout); teste o comportamento, não a seta.
|
|
136
|
+
|
|
137
|
+
## Resumo em hover (`hoverCard`) e gesto de arrastar
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
<TabsNavigation.Tab value="c1" hoverCard={<ResumoDoContato item={c} />}>…</TabsNavigation.Tab>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
- **A aba ATIVA não mostra o resumo** — o conteúdo dela já está aberto na tela; um card por
|
|
144
|
+
cima seria ruído justamente pra quem está lendo aquilo.
|
|
145
|
+
- **Abre com 500ms de espera.** Sem isso, percorrer a fila com o mouse dispararia o card de
|
|
146
|
+
todas as abas do caminho.
|
|
147
|
+
- **Não coloque ação nem informação essencial ali** — hover não existe no toque.
|
|
148
|
+
- **A tira rola arrastando** (mouse/pen, limiar de 6px, clique preservado). No celular não há
|
|
149
|
+
hook: o swipe nativo já faz melhor, com inércia.
|
|
150
|
+
- **No celular as setas `‹ ›` somem** e ficam só o `+` e a lista `⌄`: medido em 375px, os três
|
|
151
|
+
controles comiam 204px e sobrava menos de meia aba visível. A aba também encolhe (168px em
|
|
152
|
+
vez de 228px) pra caber mais de uma na tela.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Toast — USAGE
|
|
2
|
+
|
|
3
|
+
**O que é:** card de notificação consistente sobre o Sonner. _Categoria: Feedback._
|
|
4
|
+
Consome o Sonner via `toast.custom` → mantém **nativo**: agrupamento, empilhamento,
|
|
5
|
+
slide, swipe-to-dismiss e posições. Só troca o conteúdo por um card do DS.
|
|
6
|
+
|
|
7
|
+
**Quando usar:** feedback de ação (salvar, excluir, erro), avisos e convites com
|
|
8
|
+
título + subtexto + ações. Pra toast cru sem card, use o Sonner direto.
|
|
9
|
+
|
|
10
|
+
## Setup (1×)
|
|
11
|
+
`<Toaster />` no root (de `@/components/shadcn/sonner`) — já segue o tema do DS.
|
|
12
|
+
|
|
13
|
+
## Disparar
|
|
14
|
+
```tsx
|
|
15
|
+
import { toast } from "@/components/ui/Toast";
|
|
16
|
+
|
|
17
|
+
toast.success({ title: "Alterações salvas", description: "Perfil atualizado." });
|
|
18
|
+
toast.error({ title: "Falha no upload", action: { label: "Tentar de novo", tone: "danger" } });
|
|
19
|
+
toast({ title: "3 mensagens novas", icon: <Mail />, meta: "agora", action: { label: "Ver" } });
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Props (do card)
|
|
23
|
+
| Prop | Tipo | Nota |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| `title` | ReactNode | obrigatório |
|
|
26
|
+
| `description` | ReactNode | subtexto (fg-muted) |
|
|
27
|
+
| `status` | `default\|info\|success\|warning\|danger` | muda **só** o icon-chip; via `toast.success/.error/.warning/.info` |
|
|
28
|
+
| `icon` | ReactNode | override do ícone do chip |
|
|
29
|
+
| `meta` | ReactNode | texto curto à direita do título (ex.: "agora") |
|
|
30
|
+
| `action` | `{ label, onClick, tone?, iconLeft?, iconRight? }` | sozinho = inline à direita |
|
|
31
|
+
| `cancel` | `{ label, onClick }` | com `action` → rodapé (cancel ↔ action) |
|
|
32
|
+
| `onClose` | `() => void` | mostra o X e dá dismiss |
|
|
33
|
+
| `duration`/`position`/`id` | — | passthrough nativo do Sonner |
|
|
34
|
+
|
|
35
|
+
`tone` do action: `brand` (default) · `neutral` · `danger`.
|
|
36
|
+
|
|
37
|
+
## Status (cor)
|
|
38
|
+
Só o **icon-chip** muda: bg fraco (`bg-{status}-muted`) + ícone forte (`fg-{status}`).
|
|
39
|
+
A superfície do card é sempre neutra (`bg-surface`). Decisão de design: o feedback
|
|
40
|
+
vem do ícone, não de tingir o toast inteiro.
|
|
41
|
+
|
|
42
|
+
## Passthrough nativo
|
|
43
|
+
`toast.promise(...)`, `toast.dismiss(id)`, `toast.loading(...)`, `toast.custom(...)`
|
|
44
|
+
seguem disponíveis pelo mesmo `toast`.
|
|
45
|
+
|
|
46
|
+
## Gotchas
|
|
47
|
+
- Precisa do `<Toaster />` montado 1× (senão nada aparece).
|
|
48
|
+
- `action` sozinho fica inline no header; pra 2 botões em rodapé, passe `cancel` também.
|
|
49
|
+
- Pra conteúdo 100% livre (progress bar, avatar grande), use `toast.custom((id) => <…/>)`.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Shadcn — USAGE (índice de gotchas)
|
|
2
|
+
|
|
3
|
+
Atalho IA pros primitivos shadcn tokenizados. **Não há USAGE.md por arquivo**
|
|
4
|
+
aqui (a API é a do shadcn/Radix, padrão e conhecida) — a doc viva por componente
|
|
5
|
+
é o **showcase** (`#/<nome>`, em https://igreen-desingsystem-admin.vercel.app). Este índice lista **só o que NÃO é óbvio**: setup
|
|
6
|
+
obrigatório, dependências extras e pegadinhas DS. Componente que não aparece na
|
|
7
|
+
tabela = API shadcn padrão, sem gotcha → use direto e veja o showcase.
|
|
8
|
+
|
|
9
|
+
> Regra de manutenção — **só pra quem desenvolve o DS** (consumindo, ignore): ao
|
|
10
|
+
> **adicionar/editar** um shadcn, só crie/edite uma linha aqui **se houver gotcha real**
|
|
11
|
+
> (setup, dep, receita, acessibilidade). Sem gotcha → não escrever nada (evita inchar o
|
|
12
|
+
> arquivo e estourar tokens). Detalhe em `.claude/skills/ds-dev/impl-shadcn.md`.
|
|
13
|
+
|
|
14
|
+
| Componente | Gotcha (o não-óbvio) |
|
|
15
|
+
|---|---|
|
|
16
|
+
| `sonner` | Monte `<Toaster/>` **1× no root**. Toast neutro (surface); status só troca o ícone. Self-contained (segue `.dark`, sem next-themes). **Pra card ergonômico (title/description/action/status), use o composto `ui/Toast`** — não estilizar status no Sonner. |
|
|
17
|
+
| `tooltip` | `<Tooltip>` já embrulha o próprio Provider — **não** precisa de um no root. `delayDuration` default = **0** (instantâneo); sobrescreva com `<Tooltip delayDuration={400}>`. ⚠️ Até 2026-08-24 esta linha dizia 200ms e o componente não passava nada, valendo o default do Radix (**700**). |
|
|
18
|
+
| `select` | **Nunca `<SelectItem value="">`.** `""` é a sentinela de "nada selecionado" do Radix (`shouldShowPlaceholder`): o rótulo da opção nunca aparece, e o item **lança** no 2.2.6 ("must have a value prop that is not an empty string") — erro que o 2.3.1 **removeu**, trocando quebra alta por silêncio. **E o valor controlado é ECOADO de volta**: dentro de um `<form>` o `SelectBubbleInput` faz `select.value = <valor>` e dispara `change`; sem `<option>` correspondente o DOM recusa e o eco volta `onValueChange("")` — apagando um valor que ninguém tocou. Morde sempre que as opções chegam DEPOIS do valor (lista assíncrona, ou opções derivadas do próprio formulário). **O `ui/FormField/FormFieldSelect` já trata os dois** (sentinela interna + guarda do eco, com testes em `valor-orfao.test.tsx`) — prefira-o a montar o primitivo na unha. |
|
|
19
|
+
| `hover-card` | `openDelay` default = 200ms. Segue a receita flutuante (L-040). |
|
|
20
|
+
| `context-menu`, `menubar`, `navigation-menu` | Superfície flutuante segue a **receita única** (L-040) — não reverter pros defaults shadcn. |
|
|
21
|
+
| `card` | **`CardHeader` usa `gap-gp-2xs` (2px), não os 6px do shadcn upstream** — título e subtítulo de card são uma unidade de leitura, não dois blocos. Divergência **deliberada** (2026-08-19): ao re-sincronizar o primitivo, não reverter (mesma classe de cuidado da L-040). **`size`** (`sm`/`md`/`lg` = 16/20/24px) escala o padding de TODAS as partes — declare **só no `<Card>`**, chega em Header/Content/Footer por contexto; repetir nas partes é o erro que deixa uma seção com densidade diferente. **`md` (20px) é o default e antes era 24** — card que dependia dos 24 passa `size="lg"`. Não existe 18px na escala de `pad`, então `sm` é 16. Tokens: `p-pad-card-sm|md|lg` — ⚠️ `p-pad-card-base` continua existindo como **alias de `md`** (era 24 até 2026-08-19, virou 20): nada quebra, mas quem já consumia `base` recebe o novo valor. Não usar em código novo. **Subtítulo** (`CardDescription`) é `text-caption-md` (12/400), não `body-md` (14) — entre os dois presets de 12px, `caption-md` mantém o peso 400 e o `body-xs` (12/500) exigiria `font-normal` por cima. **`CardHeader variant="banded"`** = faixa `bg-bg-subtle` + `border-b border-border-subtle`, encostada nas bordas (cancela o `py` do Card com `-mt-*` e usa `rounded-t-*`, não `overflow-hidden` no Card — clipar quebraria o que precisa vazar); ⚠️ **Ação à direita na faixa exige `className="flex …"`, não `flex-row`**: o `CardHeader` é `grid` por padrão e `flex-row` **não troca o display** — os filhos continuam empilhando (o botão cai embaixo do título). Com `flex`, o tailwind-merge substitui o `grid` porque estão no mesmo grupo. ⚠️ No **dark** o `bg-subtle` é 1% de branco sobre surface 0.225: faixa muito discreta **de propósito** — se precisar de presença, `bg-muted` é 3× e no light é idêntico. O `Card` carrega o padding **vertical** e cada parte o **horizontal**, então parte full-bleed (tabela encostando nas bordas) é só zerar o `px` dela. |
|
|
22
|
+
| `carousel` | Usa o **DS `Button`** interno (não o button shadcn). Dep extra: `embla-carousel-react`. `<CarouselDots />` = indicador de posição clicável: um ponto por **parada** (`scrollSnapList`), não por slide — com vários slides visíveis ou `slidesToScroll` os números divergem. Some sozinho quando há 1 parada. |
|
|
23
|
+
| `input-otp` | Dep extra: `input-otp`. **Irmão do `Input`**: mesmos `size` (`xxs`/`xs`/`sm`/`md` → form-xs/sm/md/lg) e `state` (default/error/warning/success), mesma superfície, foco por **borda verde + `shadow-sh-ring`** (não `ring-4`). `variant`: `connected` (default) · `outlined` · `filled` · `underline`. Declare no `<InputOTP>` — os slots herdam por contexto; repetir a prop em cada slot é o erro que deixa um slot de tamanho diferente no meio da fileira. |
|
|
24
|
+
| `drawer` | Dep extra: `vaul`. Mobile dentro de overlay z-50 → wrapper a **z-60** (L-030). |
|
|
25
|
+
| `tabs` | **Duas props no `<Tabs>`, propagadas por contexto — NÃO em List/Trigger.** `variant`: `"segmented"` (default, pill) = trocar conteúdo DENTRO de uma superfície (card, bloco, `Panel`, `FloatingPanel`, `Modal`, drawer) · `"line"` (underline) = navegar seções de uma PÁGINA, ou 2º nível abaixo de um segmented; nunca empilhe a mesma variante em dois níveis. **`fullWidth`**: abas ocupam a largura e se distribuem — use em superfície compacta (`Panel` 560px, `FloatingPanel` 320–720 e redimensionável, `Modal` até `lg`, card, bloco); **não** use em toolbar (o `DataTable` usa hug de propósito), página livre ou `Modal` `xl` (1100px). ⛔ Não escreva `w-full` no List nem `flex-1` nos triggers na mão: `w-full` só no List estica o container e agrupa as abas na esquerda — era o defeito de 6 dos 7 usos manuais do próprio DS. |
|
|
26
|
+
| `alert-dialog` | **ESC FECHA**, ao contrário do que o comentário do componente afirmava (medido no browser). Só o clique fora é bloqueado. Decisão inescapável exige `onEscapeKeyDown={(e) => e.preventDefault()}` — é o que o `ui/AlertModal` faz enquanto `loading`, porque o ESC é o único caminho de dismiss que não passa por um botão e escapava dos `disabled`. Header é **centralizado** (o do Dialog é à esquerda) e o Footer é `col-reverse` no mobile — ação em cima. No `sm+` o Footer **estica os filhos** (`sm:[&>*]:flex-1`): os botões dividem a largura toda, e você **não** precisa de `fullWidth` neles. Antes não esticava, e botão sem `fullWidth` ficava na largura do texto encostado à esquerda — o oposto do desenho; o `AlertModal` compensava passando `fullWidth` em cada Button. Pra confirmação comum use o composto **`ui/AlertModal`**, que já monta tom + ícone + botões. |
|
|
27
|
+
| `input` | **`type="file"`** tem 2 desvios tratados por variante de atributo (`[&[type=file]]:…`): o UA aplica `align-items: baseline` e o conteúdo sobe na caixa de 40px → forçado `items-center`; e o texto do input vinha em `fg-default`, destoando do `placeholder:text-fg-muted` de todo input do DS → forçado `text-fg-muted`. **Efeito colateral aceito:** o CSS não distingue "vazio" de "arquivo escolhido" num file input, então o **nome do arquivo também fica muted**. Pra UX de upload de verdade (nome em destaque, remover, drag-and-drop) use o composto **`ui/FileUploadField`**, não o `<Input type="file">` cru. |
|
|
28
|
+
|
|
29
|
+
**Padrão sem gotcha** (use direto, doc no showcase): `accordion`, `alert`,
|
|
30
|
+
`aspect-ratio`, `badge`, `breadcrumb`, `button`, `calendar`, `checkbox`,
|
|
31
|
+
`collapsible`, `command`, `dialog`, `dropdown-menu`, `label`, `popover`,
|
|
32
|
+
`progress`, `radio-group`, `scroll-area`, `separator`, `sheet`,
|
|
33
|
+
`skeleton`, `slider`, `switch`, `table`, `textarea`, `toggle`,
|
|
34
|
+
`toggle-group`, `combobox`.
|
|
35
|
+
|
|
36
|
+
> ⚠️ Id daqui **não pode** estar na tabela acima. `input` e `select` estavam nos dois
|
|
37
|
+
> (corrigido em 2026-09-15) — quem lesse só esta lista usava direto um `select` cuja
|
|
38
|
+
> sentinela `value=""` apaga valor em silêncio.
|
|
39
|
+
|
|
40
|
+
## Payload de injeção (lido pelo hook, não por você)
|
|
41
|
+
|
|
42
|
+
Os blocos abaixo são o que o `protect-ds.mjs` imprime quando a IA **escreve** aquele
|
|
43
|
+
primitivo. A tabela acima é a doc completa; aqui vai só o que decide, curto de propósito —
|
|
44
|
+
a célula do `tabs` tem 816 chars e não cabe num aviso. Primitivo sem bloco = silêncio.
|
|
45
|
+
|
|
46
|
+
<!-- ds:regras tabs
|
|
47
|
+
- `variant` default (segmented) dentro de superfície (card, bloco, Panel, Modal, drawer); `line` só pra seção de página
|
|
48
|
+
- `fullWidth` em superfície compacta; ⛔ nunca `w-full` no List nem `flex-1` no trigger na mão
|
|
49
|
+
-->
|
|
50
|
+
|
|
51
|
+
<!-- ds:regras drawer
|
|
52
|
+
- é bottom-sheet (vaul): mobile ou gesto de arrastar. Detalhe lateral em desktop → `Panel` (bloqueia) ou `FloatingPanel` (coexiste com a lista)
|
|
53
|
+
- painel de DETALHE → siga o bloco `dsgreen-paneldetail-1` (o **padrão**). `-2` (tarefa com abas) e `-3` (com tabela) só se o usuário citar o ID
|
|
54
|
+
-->
|
|
55
|
+
|
|
56
|
+
<!-- ds:regras select
|
|
57
|
+
- ⛔ nunca `<SelectItem value="">` — é a sentinela do Radix e apaga valor em silêncio
|
|
58
|
+
- em form, prefira `FormFieldSelect` (já trata a sentinela e o eco do valor)
|
|
59
|
+
-->
|
|
60
|
+
|
|
61
|
+
<!-- ds:regras card
|
|
62
|
+
- `size` (`sm`/`md`/`lg`) declare SÓ no `<Card>` — Header/Content/Footer herdam por contexto; repetir nas partes é o que deixa uma seção com densidade diferente
|
|
63
|
+
- `CardHeader variant="banded"` com ação à direita pede `className="flex …"`, NUNCA `flex-row`: o header é `grid` e `flex-row` não troca o display — o botão cai embaixo do título
|
|
64
|
+
-->
|
|
65
|
+
|
|
66
|
+
<!-- ds:regras alert-dialog
|
|
67
|
+
- confirmação comum → use o composto `ui/AlertModal` (já monta tom + ícone + botões); o primitivo cru só pra caso fora do padrão
|
|
68
|
+
- ⚠️ ESC FECHA (só o clique fora é bloqueado). Decisão inescapável exige `onEscapeKeyDown={(e) => e.preventDefault()}`
|
|
69
|
+
-->
|
|
70
|
+
|
|
71
|
+
<!-- ds:regras sonner
|
|
72
|
+
- `<Toaster/>` **1× no root**, senão o toast não aparece e não há erro
|
|
73
|
+
- card ergonômico (title/description/action) → use o composto `ui/Toast`
|
|
74
|
+
-->
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Avatar
|
|
2
|
+
|
|
3
|
+
<!-- ds:regras
|
|
4
|
+
- vários avatares juntos → `<AvatarGroup>`, nunca `-ml-*` + `ring` na mão: ele resolve sobreposição por tamanho, cor do anel e excedente
|
|
5
|
+
- `<AvatarGroup surface="...">` = a superfície ATRÁS do grupo (`table` numa linha de tabela). Errar isso põe um halo claro em volta de cada avatar
|
|
6
|
+
- `max` + `total`: o `+N` conta pelo `total` (o do servidor), senão uma lista paginada mostra `+0` tendo 40 pessoas
|
|
7
|
+
- `colorHex` escolhe a cor do texto por contraste WCAG (L-027) — nunca `text-white` na unha
|
|
8
|
+
- foto de pessoa → `<Avatar src="…">` com as iniciais em `children` (são o fallback da URL que falha), nunca `<img>` solto nem o compound do shadcn dentro do grupo
|
|
9
|
+
-->
|
|
10
|
+
|
|
11
|
+
Circular badge displaying user initials. Supports semantic colors and per-person hex overrides.
|
|
12
|
+
Para **vários avatares juntos**, use `AvatarGroup` (seção no fim).
|
|
13
|
+
|
|
14
|
+
## Basic usage
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
import { Avatar } from "@/components/ui/avatar-ig";
|
|
18
|
+
|
|
19
|
+
// Semantic color (default: muted)
|
|
20
|
+
<Avatar size="md" color="brand">MS</Avatar>
|
|
21
|
+
|
|
22
|
+
// Person-specific hex color
|
|
23
|
+
<Avatar size="sm" colorHex="#8754ec">CO</Avatar>
|
|
24
|
+
|
|
25
|
+
// Foto — as iniciais continuam sendo o FALLBACK
|
|
26
|
+
<Avatar size="lg" src="/fotos/maria.jpg" aria-label="Maria Silva">MS</Avatar>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Foto (`src`, v0.53.0+)
|
|
30
|
+
|
|
31
|
+
A imagem cobre o círculo (`object-cover`, sem distorcer) e escala pelos mesmos `size` das
|
|
32
|
+
iniciais — inclusive dentro do `AvatarGroup`, que propaga o tamanho por contexto.
|
|
33
|
+
|
|
34
|
+
- **Mantenha as iniciais em `children`.** Elas são o fallback quando a URL falha; sem elas,
|
|
35
|
+
uma foto quebrada deixa um buraco na fila. O fallback herda a cor (`color`/`colorHex`).
|
|
36
|
+
- **Trocar a `src` depois de uma falha tenta de novo** — o componente guarda *qual* URL
|
|
37
|
+
falhou, não um booleano.
|
|
38
|
+
- **Não há prop `alt`.** A imagem interna é `alt=""` e o nome mora no `aria-label` do avatar;
|
|
39
|
+
dois rótulos no mesmo elemento fazem o leitor de tela anunciar a pessoa duas vezes.
|
|
40
|
+
- **Quando usar o compound do shadcn** (`avatar`, com `AvatarImage`/`AvatarFallback`): quando
|
|
41
|
+
o fallback não é iniciais (ícone, skeleton) ou você precisa do estado de carregamento. Pra
|
|
42
|
+
foto de pessoa no DS — e sempre dentro de `AvatarGroup` — o certo é este.
|
|
43
|
+
|
|
44
|
+
## Sizes
|
|
45
|
+
|
|
46
|
+
| Size | Pixels | Typography preset |
|
|
47
|
+
|------|--------|-------------------|
|
|
48
|
+
| `xs` | 20px | caption-sm (11px) |
|
|
49
|
+
| `sm` | 24px | caption-sm (11px) |
|
|
50
|
+
| `md` | 28px | caption-sm (11px) |
|
|
51
|
+
| `lg` | 32px | body-sm font-normal (13px) |
|
|
52
|
+
| `xl` | 40px | body-md font-medium (14px) |
|
|
53
|
+
|
|
54
|
+
## Colors
|
|
55
|
+
|
|
56
|
+
| Color | Background | Foreground |
|
|
57
|
+
|------------|--------------------|--------------------|
|
|
58
|
+
| `brand` | `bg-bg-brand` | `fg-on-brand` |
|
|
59
|
+
| `success` | `bg-bg-success` | `fg-on-success` |
|
|
60
|
+
| `warning` | `bg-bg-warning` | `fg-on-warning` |
|
|
61
|
+
| `critical` | `bg-bg-danger` | `fg-on-danger` |
|
|
62
|
+
| `info` | `bg-bg-info` | `fg-on-info` |
|
|
63
|
+
| `muted` | `bg-bg-muted` | `fg-muted` |
|
|
64
|
+
|
|
65
|
+
## colorHex override + auto contrast (v0.7.1+)
|
|
66
|
+
|
|
67
|
+
When `colorHex` is provided (string starting with `#`), the background is set
|
|
68
|
+
via inline style and **a cor de texto é escolhida automaticamente** pra ter
|
|
69
|
+
o maior contraste WCAG entre `white` ou `black`. O prop `color` é ignorado.
|
|
70
|
+
|
|
71
|
+
| Hex bg | Texto auto-pickado | Motivo (WCAG ratio) |
|
|
72
|
+
|----------------------|--------------------|----------------------------------------|
|
|
73
|
+
| `#FAE128` (BB) | `black` | white 1.29 vs black 16.3 → preto vence |
|
|
74
|
+
| `#820AD1` (Nubank) | `white` | white 6.2 vs black 3.4 → branco vence |
|
|
75
|
+
| `#EC7000` (Itaú) | `black` | white 2.7 vs black 7.8 → preto vence |
|
|
76
|
+
| `#CC092F` (Bradesco) | `white` | white 6.5 vs black 3.2 → branco vence |
|
|
77
|
+
| `#FFFFFF` | `black` | óbvio |
|
|
78
|
+
| `#000000` | `white` | óbvio |
|
|
79
|
+
|
|
80
|
+
A escolha vem de `getContrastTextColor()` em `@/utils/color-contrast.ts`
|
|
81
|
+
(WCAG 2.x relative luminance + contrast ratio).
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
<Avatar colorHex="#FAE128">BB</Avatar> // texto preto auto
|
|
85
|
+
<Avatar colorHex="#820AD1">NU</Avatar> // texto branco auto
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Override manual:** se precisar forçar uma cor específica (caso raro de
|
|
89
|
+
brand guideline), passe via `className`:
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
<Avatar colorHex="#FAE128" className="text-white">BB</Avatar>
|
|
93
|
+
// (não recomendado — quebra WCAG AA)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Accessibility
|
|
97
|
+
|
|
98
|
+
- With `aria-label`: renders `role="img"` (semantic avatar).
|
|
99
|
+
- Without `aria-label`: renders `aria-hidden="true"` (decorative).
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
// Semantic — standalone avatar with meaning
|
|
103
|
+
<Avatar aria-label="Maria Silva">MS</Avatar>
|
|
104
|
+
|
|
105
|
+
// Decorative — inside a card/cell that already provides context
|
|
106
|
+
<Avatar colorHex="#8754ec">CO</Avatar>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Props
|
|
110
|
+
|
|
111
|
+
| Prop | Type | Default |
|
|
112
|
+
|--------------|-------------------------------------------------------------|-----------|
|
|
113
|
+
| `size` | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` |
|
|
114
|
+
| `color` | `"brand" \| "success" \| "warning" \| "critical" \| "info" \| "muted"` | `"muted"` |
|
|
115
|
+
| `colorHex` | `string` (hex starting with `#`) | — |
|
|
116
|
+
| `src` | `string` — foto; URL que falha volta pras iniciais | — |
|
|
117
|
+
| `children` | `ReactNode` (initials) — também o fallback da foto | — |
|
|
118
|
+
| `className` | `string` | — |
|
|
119
|
+
| `aria-label` | `string` | — |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
# AvatarGroup
|
|
124
|
+
|
|
125
|
+
Pilha de avatares sobrepostos, com `size` propagado e excedente resumido em `+N`.
|
|
126
|
+
|
|
127
|
+
## Quando usar
|
|
128
|
+
|
|
129
|
+
Conjunto de pessoas onde **o grupo importa mais que cada uma**: responsáveis de uma tarefa,
|
|
130
|
+
participantes, membros de um time. Para 2 avatares que devem ser lidos individualmente, use
|
|
131
|
+
`flex gap-gp-sm` comum — a sobreposição comunica "muitos".
|
|
132
|
+
|
|
133
|
+
## Props
|
|
134
|
+
|
|
135
|
+
| Prop | Tipo | Default | Descrição |
|
|
136
|
+
|------|------|---------|-----------|
|
|
137
|
+
| `size` | `xs \| sm \| md \| lg \| xl` | `md` | **propagado por contexto** a todos os filhos |
|
|
138
|
+
| `max` | `number` | — | acima disso, corta e mostra `+N` |
|
|
139
|
+
| `total` | `number` | nº de filhos | contagem REAL, pro `+N` refletir o servidor |
|
|
140
|
+
| `surface` | `surface \| canvas \| subtle \| muted \| table` | `surface` | superfície **atrás** do grupo — define a cor do anel |
|
|
141
|
+
| `aria-label` | `string` | — | rótulo do grupo, ex.: `"12 responsáveis"` |
|
|
142
|
+
|
|
143
|
+
## Exemplo
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
import { Avatar, AvatarGroup } from "@/components/ui/avatar-ig";
|
|
147
|
+
|
|
148
|
+
{/* foto e iniciais misturadas: o size vem do container, ninguém sai de escala */}
|
|
149
|
+
<AvatarGroup size="sm" max={3} total={12} aria-label="12 responsáveis">
|
|
150
|
+
<Avatar src="/fotos/ana.jpg" aria-label="Ana">AN</Avatar>
|
|
151
|
+
<Avatar src="/fotos/bruno.jpg" aria-label="Bruno">BR</Avatar>
|
|
152
|
+
<Avatar colorHex="#7C3AED" aria-label="Júlia">JS</Avatar>
|
|
153
|
+
<Avatar colorHex="#0891B2" aria-label="Tiago">TK</Avatar>
|
|
154
|
+
</AvatarGroup>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Gotchas / cuidados
|
|
158
|
+
|
|
159
|
+
- **`surface` é a cor do que está ATRÁS, e é o erro clássico.** O anel separa um avatar do
|
|
160
|
+
outro pintando a cor da superfície de trás; com o token errado ele deixa de separar e vira um
|
|
161
|
+
halo. Sobre `bg-bg-muted` ou `bg-bg-canvas`, declare o token correspondente.
|
|
162
|
+
⚠️ **`table` e `surface` resolvem pro mesmo valor hoje** — `oklch(1 0 0)` no claro e
|
|
163
|
+
`oklch(0.225 0 0)` no escuro (medido). Dentro de tabela a escolha é **semântica**, não
|
|
164
|
+
visual: declare `table` mesmo assim, pra que a pilha continue certa se um dia os dois
|
|
165
|
+
divergirem, sem ninguém ter que caçar o call site.
|
|
166
|
+
- **`total` não é opcional quando a lista é paginada.** Sem ele o `+N` conta só o que foi
|
|
167
|
+
renderizado — 4 filhos com `max={2}` mostram `+2`, mesmo que existam 40 pessoas.
|
|
168
|
+
- **`size` no filho vence o do grupo.** É escape hatch pra destacar um avatar; sem passar nada,
|
|
169
|
+
todos herdam o do grupo.
|
|
170
|
+
- **A sobreposição escala com o tamanho** (~25% do diâmetro): `xs` desloca 4px e `xl` desloca
|
|
171
|
+
10px. Não é constante de propósito — 6px num avatar de 20px é 30% de sobreposição e num de
|
|
172
|
+
40px é 15%, que são arranjos visuais diferentes.
|
|
173
|
+
- **O primeiro fica por cima** (z-index decrescente), invertendo o empilhamento natural do DOM.
|
|
174
|
+
A leitura é da esquerda pra direita e o primeiro é o principal.
|
|
175
|
+
- **O grupo fala, os avatares calam.** O container é `role="group"` com `aria-label`; o `+N` é
|
|
176
|
+
`aria-hidden` porque a contagem real já está no rótulo. Sem o `aria-label`, o leitor de tela
|
|
177
|
+
lê N nomes soltos sem dizer que são um conjunto.
|
|
178
|
+
- **Foto e iniciais convivem na mesma pilha.** A foto obedece ao mesmo `size` de contexto, e o
|
|
179
|
+
anel importa mais com foto: sem ele, duas fotos escuras encostadas viram uma mancha só.
|
|
180
|
+
- **O anel mora no wrapper, não no `Avatar`.** `ring` acompanha o `border-radius` do elemento —
|
|
181
|
+
num wrapper quadrado traçaria um quadrado. `Avatar` fora de grupo continua sem anel.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"AlertModal": "componentes/AlertModal.md",
|
|
3
|
+
"AppShell": "componentes/AppShell.md",
|
|
4
|
+
"avatar-ig": "componentes/avatar-ig.md",
|
|
5
|
+
"Breadcrumb": "componentes/Breadcrumb.md",
|
|
6
|
+
"Button": "componentes/Button.md",
|
|
7
|
+
"ButtonGroup": "componentes/ButtonGroup.md",
|
|
8
|
+
"CardCheckbox": "componentes/CardCheckbox.md",
|
|
9
|
+
"CardOption": "componentes/CardOption.md",
|
|
10
|
+
"Chart": "componentes/Chart.md",
|
|
11
|
+
"Chip": "componentes/Chip.md",
|
|
12
|
+
"ChoroplethMap": "componentes/ChoroplethMap.md",
|
|
13
|
+
"ColorPicker": "componentes/ColorPicker.md",
|
|
14
|
+
"Combobox": "componentes/Combobox.md",
|
|
15
|
+
"ConversationListItem": "componentes/ConversationListItem.md",
|
|
16
|
+
"DataList": "componentes/DataList.md",
|
|
17
|
+
"DataTable": "componentes/DataTable.md",
|
|
18
|
+
"DatePicker": "componentes/DatePicker.md",
|
|
19
|
+
"DateSeparatorChip": "componentes/DateSeparatorChip.md",
|
|
20
|
+
"EmptyState": "componentes/EmptyState.md",
|
|
21
|
+
"FileUploadField": "componentes/FileUploadField.md",
|
|
22
|
+
"FloatingPanel": "componentes/FloatingPanel.md",
|
|
23
|
+
"FooterTable": "componentes/FooterTable.md",
|
|
24
|
+
"FormField": "componentes/FormField.md",
|
|
25
|
+
"Gantt": "componentes/Gantt.md",
|
|
26
|
+
"Header": "componentes/Header.md",
|
|
27
|
+
"Icon": "componentes/Icon.md",
|
|
28
|
+
"Kanban": "componentes/Kanban.md",
|
|
29
|
+
"Kpi": "componentes/Kpi.md",
|
|
30
|
+
"List": "componentes/List.md",
|
|
31
|
+
"MarkdownText": "componentes/MarkdownText.md",
|
|
32
|
+
"MenuSidebar": "componentes/MenuSidebar.md",
|
|
33
|
+
"MessageAck": "componentes/MessageAck.md",
|
|
34
|
+
"MessageBubble": "componentes/MessageBubble.md",
|
|
35
|
+
"MessageComposer": "componentes/MessageComposer.md",
|
|
36
|
+
"MessageVariablesPicker": "componentes/MessageVariablesPicker.md",
|
|
37
|
+
"Modal": "componentes/Modal.md",
|
|
38
|
+
"MonthYearPicker": "componentes/MonthYearPicker.md",
|
|
39
|
+
"PageHeader": "componentes/PageHeader.md",
|
|
40
|
+
"Panel": "componentes/Panel.md",
|
|
41
|
+
"Scheduler": "componentes/Scheduler.md",
|
|
42
|
+
"ScreenLoader": "componentes/ScreenLoader.md",
|
|
43
|
+
"SingleMenuSidebar": "componentes/SingleMenuSidebar.md",
|
|
44
|
+
"Spinner": "componentes/Spinner.md",
|
|
45
|
+
"Table": "componentes/Table.md",
|
|
46
|
+
"TableToolbar": "componentes/TableToolbar.md",
|
|
47
|
+
"TabsNavigation": "componentes/TabsNavigation.md",
|
|
48
|
+
"Toast": "componentes/Toast.md"
|
|
49
|
+
}
|