@softize/opus 13.1.0 → 15.0.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/CHANGELOG.md +97 -0
- package/bin/cli.mjs +2 -0
- package/bin/lib/check.mjs +33 -5
- package/bin/lib/cli-shared.mjs +30 -1
- package/bin/lib/copy.mjs +279 -6
- package/bin/lib/db.mjs +2 -0
- package/docs/adr/0004-page-content-state-is-composed.md +39 -5
- package/docs/adr/0005-structural-surfaces-share-an-explicit-anatomy.md +9 -3
- package/docs/adr/0009-page-title-does-not-carry-a-counter.md +57 -0
- package/docs/adr/0010-page-header-owns-page-chrome.md +73 -0
- package/docs/code-style.md +4 -1
- package/docs/data-layer.md +9 -0
- package/package.json +1 -1
- package/registry/instructions/opus.md +3 -3
- package/registry/skills/build-opus-ui/SKILL.md +3 -2
- package/registry/skills/build-opus-ui/references/ui-patterns.md +17 -6
- package/registry/templates/app/src/App.tsx +11 -6
- package/src/core/types.ts +3 -4
- package/src/ui/components/patterns/action-list-dialog.tsx +10 -3
- package/src/ui/components/patterns/confirm.tsx +2 -31
- package/src/ui/components/patterns/content-header.tsx +42 -141
- package/src/ui/components/patterns/data-state.tsx +42 -68
- package/src/ui/components/patterns/form.tsx +15 -15
- package/src/ui/components/patterns/list.tsx +55 -34
- package/src/ui/components/patterns/page-state.tsx +81 -51
- package/src/ui/components/patterns/page.tsx +228 -97
- package/src/ui/components/patterns/state-surface.tsx +262 -0
- package/src/ui/components/patterns/surface-header.tsx +204 -0
- package/src/ui/components/patterns/trigger.tsx +9 -10
- package/src/ui/components/patterns/view.tsx +14 -16
- package/src/ui/components/primitives/alert.tsx +1 -33
- package/src/ui/components/primitives/avatar.tsx +15 -5
- package/src/ui/components/primitives/badge.tsx +2 -43
- package/src/ui/components/primitives/button-group.tsx +34 -8
- package/src/ui/components/primitives/button.tsx +31 -35
- package/src/ui/components/primitives/control.ts +69 -0
- package/src/ui/components/primitives/dot.tsx +1 -30
- package/src/ui/components/primitives/input-group.tsx +11 -8
- package/src/ui/components/primitives/item.tsx +3 -1
- package/src/ui/components/primitives/menu.tsx +1 -7
- package/src/ui/components/primitives/pagination.tsx +16 -8
- package/src/ui/components/primitives/select.tsx +2 -2
- package/src/ui/components/primitives/spinner.tsx +13 -16
- package/src/ui/components/primitives/switch.tsx +4 -1
- package/src/ui/components/primitives/tabs.tsx +5 -3
- package/src/ui/components/primitives/toggle.tsx +9 -4
- package/src/ui/docs/content/action-form.md +26 -0
- package/src/ui/docs/content/action-list-dialog.md +2 -2
- package/src/ui/docs/content/action-list.md +35 -2
- package/src/ui/docs/content/action-trigger.md +5 -4
- package/src/ui/docs/content/action-view.md +3 -2
- package/src/ui/docs/content/alert.md +16 -4
- package/src/ui/docs/content/avatar.md +7 -3
- package/src/ui/docs/content/button.md +48 -17
- package/src/ui/docs/content/communication.md +36 -0
- package/src/ui/docs/content/content.md +5 -4
- package/src/ui/docs/content/data-state.md +17 -13
- package/src/ui/docs/content/dialog.md +1 -4
- package/src/ui/docs/content/input.md +1 -1
- package/src/ui/docs/content/item.md +1 -1
- package/src/ui/docs/content/page.md +160 -37
- package/src/ui/docs/content/pagination.md +11 -9
- package/src/ui/docs/content/semantic-context.md +3 -2
- package/src/ui/docs/content/sidebar.md +2 -42
- package/src/ui/docs/content/spinner.md +9 -6
- package/src/ui/docs/content/switch.md +1 -1
- package/src/ui/docs/content/tabs.md +1 -1
- package/src/ui/docs/content/toggle.md +1 -1
- package/src/ui/drivers/react.tsx +1 -6
- package/src/ui/meta.ts +8 -8
- package/src/ui/react.tsx +16 -18
- package/src/ui/components/patterns/shell-nav.tsx +0 -154
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
## Esqueleto de página
|
|
2
2
|
|
|
3
|
-
Use `Page` para manter
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
Use `Page` para manter navegação contextual, título, ações e conteúdo na mesma anatomia. O
|
|
4
|
+
`PageHeader` padrão acompanha o conteúdo dentro do container; `variant="bar"` transforma o mesmo
|
|
5
|
+
cabeçalho em uma faixa compacta no topo. Não monte um chrome paralelo para repetir essas regiões.
|
|
6
|
+
|
|
7
|
+
Em larguras amplas, as ações ficam no extremo oposto e acompanham a base do título e da descrição;
|
|
8
|
+
em larguras estreitas, passam para uma linha abaixo. O container é centralizado e ocupa a largura
|
|
9
|
+
disponível até `80rem` (`max-w-7xl`). Use `className` somente quando a composição pedir outro teto
|
|
10
|
+
ou largura total.
|
|
9
11
|
|
|
10
12
|
A forma curta é o padrão para páginas comuns. Ela cria internamente `PageHeader` e `PageBody`;
|
|
11
|
-
portanto, não produz uma estrutura visual ou semântica diferente da forma explícita.
|
|
13
|
+
portanto, não produz uma estrutura visual ou semântica diferente da forma explícita. O cabeçalho é a
|
|
14
|
+
mesma base estrutural de `Content`, mas reconhece somente título, descrição e ações. Contadores e
|
|
15
|
+
outros indicadores pertencem ao conteúdo que os explica.
|
|
12
16
|
|
|
13
|
-
`Page`
|
|
14
|
-
de um shell com sidebar; a navegação lateral não exige remover o teto nem reconstruir o cabeçalho.
|
|
15
|
-
Uma navegação contextual para outra página pode ocupar `actions`, e tabs ficam reservados a
|
|
17
|
+
`Page` também pode ocupar o painel principal de um shell com sidebar. Tabs ficam reservados a
|
|
16
18
|
recortes da mesma superfície. Canvas e outros workspaces espaciais imersivos podem usar um shell
|
|
17
|
-
próprio quando o cabeçalho reduzir a área útil ou duplicar controles persistentes
|
|
19
|
+
próprio quando o cabeçalho reduzir a área útil ou duplicar controles persistentes.
|
|
18
20
|
|
|
19
21
|
Estados integrais de carregamento, falha ou ausência são compostos no body com `PageState`,
|
|
20
22
|
detalhado abaixo. `Page` não recebe flags de dados: uma página pode agregar fontes independentes e
|
|
@@ -25,7 +27,6 @@ render(
|
|
|
25
27
|
<div className="w-full overflow-hidden rounded-lg border border-border">
|
|
26
28
|
<Page
|
|
27
29
|
title="Workspaces"
|
|
28
|
-
count={3}
|
|
29
30
|
description="Ambientes compartilhados pela equipe."
|
|
30
31
|
actions={
|
|
31
32
|
<Button>
|
|
@@ -38,16 +39,58 @@ render(
|
|
|
38
39
|
</div>
|
|
39
40
|
</Page>
|
|
40
41
|
</div>,
|
|
41
|
-
)
|
|
42
|
+
);
|
|
42
43
|
```
|
|
43
44
|
|
|
44
|
-
##
|
|
45
|
+
## Retorno para a página pai
|
|
46
|
+
|
|
47
|
+
Use `PageBack` em uma subpágina simples. O destino é explícito para continuar correto após refresh ou
|
|
48
|
+
acesso por link direto; não derive esse retorno do histórico do navegador. No header padrão, o
|
|
49
|
+
controle aparece acima do título com ícone e rótulo.
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
```tsx preview col
|
|
52
|
+
<Page>
|
|
53
|
+
<PageHeader>
|
|
54
|
+
<PageBack href="/customers">Clientes</PageBack>
|
|
55
|
+
<PageTitle>Qualidade da base</PageTitle>
|
|
56
|
+
<PageDescription>Revise conflitos e canais de contato.</PageDescription>
|
|
57
|
+
</PageHeader>
|
|
58
|
+
<PageBody>Conteúdo da análise.</PageBody>
|
|
59
|
+
</Page>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Não combine `PageBack` com breadcrumb. Use o retorno para um único pai conhecido. Quando houver
|
|
63
|
+
mais de um ancestral relevante, envolva o `Breadcrumb` em `PageNavigation`; ele ocupa a mesma
|
|
64
|
+
posição introdutória sem transformar a trilha em ação.
|
|
65
|
+
|
|
66
|
+
## Cabeçalho em barra
|
|
67
|
+
|
|
68
|
+
Use `variant="bar"` quando título, retorno e ações precisarem formar uma faixa compacta e persistente
|
|
69
|
+
no topo da página. `Page` estende a borda por toda a largura e mantém o conteúdo da barra alinhado ao
|
|
70
|
+
mesmo teto do body. Nesse modo, `PageBack` vira icon-only e recebe tooltip e nome acessível “Voltar
|
|
71
|
+
para {destino}”. Mantenha também as ações compactas: use `sm` em botões com texto e `icon-sm` em
|
|
72
|
+
botões que exibem somente um ícone.
|
|
73
|
+
|
|
74
|
+
```tsx preview col
|
|
75
|
+
<Page className="max-w-none">
|
|
76
|
+
<PageHeader variant="bar">
|
|
77
|
+
<PageBack href="/customers">Clientes</PageBack>
|
|
78
|
+
<PageTitle>Qualidade da base</PageTitle>
|
|
79
|
+
<PageActions>
|
|
80
|
+
<Button variant="ghost" size="icon-sm" aria-label="Mais ações">
|
|
81
|
+
<Ellipsis />
|
|
82
|
+
</Button>
|
|
83
|
+
</PageActions>
|
|
84
|
+
</PageHeader>
|
|
85
|
+
<PageBody>Conteúdo da análise.</PageBody>
|
|
86
|
+
</Page>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Uma página comum não ganha a barra apenas por estar dentro de um shell. Escolha essa variante quando
|
|
90
|
+
a faixa acrescentar contexto ou ações persistentes; sem isso, mantenha o header padrão.
|
|
91
|
+
|
|
92
|
+
`PageActionsTarget` continua disponível para um workspace imersivo que já possua um chrome próprio.
|
|
93
|
+
Ele projeta somente `PageActions` no elemento informado; não cria uma segunda região de cabeçalho.
|
|
51
94
|
|
|
52
95
|
## Composição explícita
|
|
53
96
|
|
|
@@ -59,9 +102,12 @@ render(
|
|
|
59
102
|
<Page>
|
|
60
103
|
<PageHeader>
|
|
61
104
|
<PageTitle>Workspaces</PageTitle>
|
|
62
|
-
<PageMeta>3</PageMeta>
|
|
63
105
|
<PageDescription>Ambientes compartilhados pela equipe.</PageDescription>
|
|
64
|
-
<PageActions
|
|
106
|
+
<PageActions>
|
|
107
|
+
<Button>
|
|
108
|
+
<Plus /> Novo workspace
|
|
109
|
+
</Button>
|
|
110
|
+
</PageActions>
|
|
65
111
|
</PageHeader>
|
|
66
112
|
<PageBody>
|
|
67
113
|
<div className="rounded-lg border border-dashed border-border p-10 text-center">
|
|
@@ -69,15 +115,18 @@ render(
|
|
|
69
115
|
</div>
|
|
70
116
|
</PageBody>
|
|
71
117
|
</Page>,
|
|
72
|
-
)
|
|
118
|
+
);
|
|
73
119
|
```
|
|
74
120
|
|
|
75
121
|
## Estados integrais
|
|
76
122
|
|
|
77
123
|
Use `PageState` quando carregamento, falha ou ausência substituírem todo o conteúdo principal. Na
|
|
78
124
|
forma curta ele pode ser escrito como filho direto de `Page`, que cria o `PageBody`; na forma
|
|
79
|
-
explícita, coloque-o dentro de `PageBody`.
|
|
80
|
-
|
|
125
|
+
explícita, coloque-o sozinho dentro de `PageBody`. Enquanto `status` for `loading`, `error` ou
|
|
126
|
+
`empty`, `Page` oculta o cabeçalho e o estado ocupa a altura disponível. O título do estado assume o
|
|
127
|
+
heading principal. Esse registro também funciona quando um componente intermediário decide qual
|
|
128
|
+
`PageState` renderizar. Em `ready`, o cabeçalho e o conteúdo voltam à composição normal. O cabeçalho some inteiro, incluindo o `PageBack`: uma subpágina que dependa desse retorno
|
|
129
|
+
oferece a saída pelo `action` do próprio `PageState` (ADR 0004, adendo).
|
|
81
130
|
|
|
82
131
|
```tsx preview col
|
|
83
132
|
<Page title="Relatório">
|
|
@@ -85,13 +134,18 @@ altura e semântica acessível consistentes.
|
|
|
85
134
|
status="error"
|
|
86
135
|
title="Não foi possível carregar o relatório"
|
|
87
136
|
description="Tente novamente. Se o problema continuar, volte mais tarde."
|
|
88
|
-
|
|
137
|
+
onRetry={() => {}}
|
|
138
|
+
retryLabel="Tentar novamente"
|
|
89
139
|
/>
|
|
90
140
|
</Page>
|
|
91
141
|
```
|
|
92
142
|
|
|
93
|
-
`loading` centraliza o `Spinner
|
|
94
|
-
|
|
143
|
+
`loading` centraliza o `Spinner` num contêiner `role="status"`; `error` usa a mesma anatomia visual
|
|
144
|
+
centralizada dos outros estados, conserva `role="alert"` e oferece uma ação `outline` textual quando
|
|
145
|
+
há `onRetry`; `empty` centraliza `Empty` sem moldura; e `ready` entrega os filhos sem
|
|
146
|
+
acrescentar uma superfície. A moldura tracejada continua reservada ao `Empty` usado diretamente para
|
|
147
|
+
representar uma região disponível para criar ou vincular. `title` e `description` nomeiam a situação
|
|
148
|
+
e, sem `title`, valem `errorMessage` e `emptyMessage`.
|
|
95
149
|
|
|
96
150
|
```tsx preview col
|
|
97
151
|
<Page title="Relatórios">
|
|
@@ -111,20 +165,89 @@ estado na própria seção com `DataState`, `ActionView`, `ActionList` ou `Alert
|
|
|
111
165
|
|
|
112
166
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
113
167
|
| ------------- | ----------- | ----------- | ----------------------------------------------------------------------------------------------- |
|
|
114
|
-
| `title` | `
|
|
115
|
-
| `count` | `number` | | Total de itens ao lado do título (mono, esmaecido). |
|
|
168
|
+
| `title` | `ReactNode` | | O h1 da página. |
|
|
116
169
|
| `description` | `ReactNode` | | Linha de contexto sob o título (ex.: "N no total · X ativos"). |
|
|
117
170
|
| `actions` | `ReactNode` | | Ações contextuais no extremo oposto do cabeçalho; em telas estreitas, ficam abaixo do contexto. |
|
|
118
171
|
| `className` | `string` | `max-w-7xl` | Classes do container para substituir o teto padrão de `80rem`. |
|
|
119
172
|
| `children` | `ReactNode` | | O body da página — espaçamento e diagramação são seus. |
|
|
120
173
|
|
|
174
|
+
## Propriedades de PageHeader
|
|
175
|
+
|
|
176
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
177
|
+
| ----------- | ---------------------- | ----------- | ---------------------------------------------------------------- |
|
|
178
|
+
| `variant` | `'default' \| 'bar'` | `'default'` | Apresentação no container ou como faixa compacta no topo. |
|
|
179
|
+
| `className` | `string` | | Classes adicionais da região externa do cabeçalho. |
|
|
180
|
+
| `children` | `ReactNode` | | Um `PageTitle` e, opcionalmente, `PageBack` ou `PageNavigation`, descrição e ações. |
|
|
181
|
+
|
|
182
|
+
## Propriedades de PageBack
|
|
183
|
+
|
|
184
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
185
|
+
| ------------ | ---------------------------- | ------------------------- | ----------------------------------------------------------------------- |
|
|
186
|
+
| `href` | `string` | obrigatório | Destino explícito da página pai. Sem ele o retorno não é tabulável nem tem nome acessível. |
|
|
187
|
+
| `children` | `ReactNode` | | Nome visível do destino no header padrão e conteúdo do tooltip na barra. |
|
|
188
|
+
| `aria-label` | `string` | `Voltar para {children}` | Nome acessível; informe-o quando `children` não for texto simples. |
|
|
189
|
+
| `onClick` | `MouseEventHandler<HTMLAnchorElement>` | | Integração opcional com o roteador do consumidor, junto do `href`, nunca no lugar dele. |
|
|
190
|
+
| `className` | `string` | | Classes adicionais do link renderizado como botão `ghost`. |
|
|
191
|
+
|
|
192
|
+
## Propriedades de PageNavigation
|
|
193
|
+
|
|
194
|
+
| Propriedade | Tipo | Descrição |
|
|
195
|
+
| ----------- | ----------------------------- | ----------------------------------------------- |
|
|
196
|
+
| `children` | `ReactNode` | Trilha estrutural, normalmente um `Breadcrumb`. |
|
|
197
|
+
| `className` | `string` | Classes adicionais do container introdutório. |
|
|
198
|
+
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao container. |
|
|
199
|
+
|
|
200
|
+
## Propriedades de PageTitle
|
|
201
|
+
|
|
202
|
+
| Propriedade | Tipo | Descrição |
|
|
203
|
+
| ----------- | --------------------------------- | ------------------------------------------------------ |
|
|
204
|
+
| `children` | `ReactNode` | Título principal `h1`; compacto na variante `bar`. |
|
|
205
|
+
| `className` | `string` | Classes adicionais do título. |
|
|
206
|
+
| demais | Atributos de `HTMLHeadingElement` | Atributos nativos repassados ao heading. |
|
|
207
|
+
|
|
208
|
+
## Propriedades de PageDescription
|
|
209
|
+
|
|
210
|
+
| Propriedade | Tipo | Descrição |
|
|
211
|
+
| ----------- | ----------------------------------- | ---------------------------------------- |
|
|
212
|
+
| `children` | `ReactNode` | Contexto apresentado abaixo do título. |
|
|
213
|
+
| `className` | `string` | Classes adicionais da descrição. |
|
|
214
|
+
| demais | Atributos de `HTMLParagraphElement` | Atributos nativos repassados ao parágrafo. |
|
|
215
|
+
|
|
216
|
+
## Propriedades de PageActions
|
|
217
|
+
|
|
218
|
+
| Propriedade | Tipo | Descrição |
|
|
219
|
+
| ----------- | ------------------------------ | -------------------------------------------- |
|
|
220
|
+
| `children` | `ReactNode` | Ações no extremo oposto do cabeçalho. |
|
|
221
|
+
| `className` | `string` | Classes adicionais da região de ações. |
|
|
222
|
+
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao container. |
|
|
223
|
+
|
|
224
|
+
## Propriedades de PageBody
|
|
225
|
+
|
|
226
|
+
| Propriedade | Tipo | Descrição |
|
|
227
|
+
| ----------- | ----------------------------- | ----------------------------------------------------- |
|
|
228
|
+
| `children` | `ReactNode` | Conteúdo principal; recebe o container na barra. |
|
|
229
|
+
| `className` | `string` | Classes adicionais da região principal. |
|
|
230
|
+
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao container. |
|
|
231
|
+
|
|
232
|
+
## Propriedades de PageActionsTarget
|
|
233
|
+
|
|
234
|
+
| Propriedade | Tipo | Descrição |
|
|
235
|
+
| ----------- | -------------------- | ----------------------------------------------------------------------- |
|
|
236
|
+
| `target` | `HTMLElement \| null` | Destino externo das ações; `null` mantém as ações no header. |
|
|
237
|
+
| `children` | `ReactNode` | Árvore de página que poderá declarar `PageActions`. |
|
|
238
|
+
|
|
121
239
|
## Propriedades de PageState
|
|
122
240
|
|
|
123
|
-
| Propriedade
|
|
124
|
-
|
|
125
|
-
| `status`
|
|
126
|
-
| `title`
|
|
127
|
-
| `description`
|
|
128
|
-
| `icon`
|
|
129
|
-
| `action`
|
|
130
|
-
| `
|
|
241
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
242
|
+
| -------------- | -------------------------------------------- | ----------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
243
|
+
| `status` | `'loading' \| 'error' \| 'empty' \| 'ready'` | | Estado integral do conteúdo. |
|
|
244
|
+
| `title` | `ReactNode` | Texto seguro por estado | Situação reconhecível pela pessoa. |
|
|
245
|
+
| `description` | `ReactNode` | | Impacto ou próximo passo aplicável. |
|
|
246
|
+
| `icon` | `ReactNode` | Alerta no erro | Ícone decorativo do estado. |
|
|
247
|
+
| `action` | `ReactNode` | | Seleção ou criação aplicável ao estado. |
|
|
248
|
+
| `emptyMessage` | `string` | `'Nada por aqui'` | Título do vazio quando `title` não é informado. |
|
|
249
|
+
| `errorMessage` | `string` | `'Não foi possível carregar esta página'` | Título do erro quando `title` não é informado. |
|
|
250
|
+
| `onRetry` | `() => void \| Promise<void>` | | Recuperação do erro: acrescenta um botão `outline` textual ao lado de `action`. |
|
|
251
|
+
| `retryLabel` | `string` | `'Tentar de novo'` | Texto do botão de recuperação. |
|
|
252
|
+
| `children` | `ReactNode` | | Conteúdo renderizado somente em `ready`. |
|
|
253
|
+
| `className` | `string` | | Classes da superfície de estado. |
|
|
@@ -29,21 +29,21 @@ rodapé.
|
|
|
29
29
|
|
|
30
30
|
## Números longos
|
|
31
31
|
|
|
32
|
-
A largura mínima é quadrada e cresce conforme o conteúdo. Na escala densa de um rodapé,
|
|
33
|
-
`
|
|
34
|
-
|
|
32
|
+
A largura mínima é quadrada e cresce conforme o conteúdo. Na escala densa de um rodapé, as setas e a
|
|
33
|
+
elipse usam `size="icon-sm"` (o quadrado de 1.75rem da escala única, com o glifo de 0.875rem); os
|
|
34
|
+
números, que não têm um degrau de 1.75rem na escala, ajustam por `className` (`h-7 min-w-7 text-xs`).
|
|
35
35
|
|
|
36
36
|
```tsx preview
|
|
37
37
|
<Pagination>
|
|
38
38
|
<PaginationContent className="gap-0.5">
|
|
39
39
|
<PaginationItem>
|
|
40
|
-
<PaginationPrevious href="#" iconOnly
|
|
40
|
+
<PaginationPrevious href="#" iconOnly size="icon-sm" />
|
|
41
41
|
</PaginationItem>
|
|
42
42
|
<PaginationItem>
|
|
43
43
|
<PaginationLink href="#" page={1} className="h-7 min-w-7 text-xs" />
|
|
44
44
|
</PaginationItem>
|
|
45
45
|
<PaginationItem>
|
|
46
|
-
<PaginationEllipsis
|
|
46
|
+
<PaginationEllipsis size="icon-sm" />
|
|
47
47
|
</PaginationItem>
|
|
48
48
|
<PaginationItem>
|
|
49
49
|
<PaginationLink href="#" page={5726} className="h-7 min-w-7 text-xs" />
|
|
@@ -52,7 +52,7 @@ setas com `iconOnly`).
|
|
|
52
52
|
<PaginationLink href="#" page={5727} isActive className="h-7 min-w-7 text-xs" />
|
|
53
53
|
</PaginationItem>
|
|
54
54
|
<PaginationItem>
|
|
55
|
-
<PaginationNext href="#" iconOnly
|
|
55
|
+
<PaginationNext href="#" iconOnly size="icon-sm" />
|
|
56
56
|
</PaginationItem>
|
|
57
57
|
</PaginationContent>
|
|
58
58
|
</Pagination>
|
|
@@ -61,7 +61,8 @@ setas com `iconOnly`).
|
|
|
61
61
|
## Com elipse
|
|
62
62
|
|
|
63
63
|
`PaginationEllipsis` marca, de forma decorativa e com `aria-hidden`, uma sequência de páginas que
|
|
64
|
-
não cabe na barra.
|
|
64
|
+
não cabe na barra. `size` aceita os quadrados da escala (`icon-xs`, `icon-sm`, `icon`, `icon-lg`) para
|
|
65
|
+
parear com as setas.
|
|
65
66
|
|
|
66
67
|
```tsx preview
|
|
67
68
|
<Pagination>
|
|
@@ -130,7 +131,7 @@ render(
|
|
|
130
131
|
| `page` | `number` | | Número usado como conteúdo, quando `children` não é informado, e no nome acessível “Página N”. |
|
|
131
132
|
| `isActive` | `boolean` | `false` | Marca a página atual com `aria-current="page"` e tratamento `outline`. |
|
|
132
133
|
| `href` | `string` | | Renderiza um `<a>`. Sem `href`, o componente usa `<button>` e aceita `onClick` e `disabled`. |
|
|
133
|
-
| `size` | `'
|
|
134
|
+
| `size` | `ButtonProps['size']` | `'default'` | A escala única, via `Button`. A largura mínima cresce para acomodar números longos; os `icon-*` são quadrados. |
|
|
134
135
|
|
|
135
136
|
## Propriedades de PaginationPrevious e PaginationNext
|
|
136
137
|
|
|
@@ -138,4 +139,5 @@ render(
|
|
|
138
139
|
|---|---|---|---|
|
|
139
140
|
| `label` | `string` | `'Página anterior'` ou `'Próxima página'` | Nome acessível e texto visível da ação. |
|
|
140
141
|
| `iconOnly` | `boolean` | `false` | Exibe somente a seta; `label` continua disponível para leitura assistiva. |
|
|
141
|
-
| `
|
|
142
|
+
| `size` | `ButtonProps['size']` | `'default'`; `'icon'` com `iconOnly` | A escala única; `icon-sm` para o rodapé denso. |
|
|
143
|
+
| `iconClassName` | `string` | | Classes aplicadas ao ícone da seta, quando o glifo da escala não servir. |
|
|
@@ -59,5 +59,6 @@ const status = t.dict(
|
|
|
59
59
|
|
|
60
60
|
## Compatibilidade
|
|
61
61
|
|
|
62
|
-
`tone` em dicionários
|
|
63
|
-
|
|
62
|
+
`tone` em dicionários continua aceito durante a migração; código novo usa `context`. As variantes
|
|
63
|
+
semânticas antigas dos componentes (`default`, `secondary`, `destructive`, `success`, `warning`,
|
|
64
|
+
`info`) saíram na 14.0.0: `variant` só descreve tratamento visual e o significado é sempre `context`.
|
|
@@ -61,7 +61,7 @@ uma sidebar fixa, redimensionável ou recolhida.
|
|
|
61
61
|
| `PaneHeader` | Mantém identidade, contexto ou ações no topo. |
|
|
62
62
|
| `PaneBody` | Ocupa o espaço restante e concentra a rolagem vertical. |
|
|
63
63
|
| `PaneFooter` | Mantém ações persistentes no rodapé. |
|
|
64
|
-
| `SidebarNav`
|
|
64
|
+
| `SidebarNav` | Apresenta e controla os destinos de navegação. |
|
|
65
65
|
|
|
66
66
|
`PaneContent` permanece como alias temporário de `PaneBody` durante a versão 12. Código novo usa
|
|
67
67
|
`PaneBody`.
|
|
@@ -134,26 +134,9 @@ render(
|
|
|
134
134
|
Esse é o padrão usado pelo `DocBrowser`: seções são rótulos, grupos nomeados são nós expansíveis e
|
|
135
135
|
páginas são folhas. Um grupo começa aberto e volta a abrir quando contém a página ativa.
|
|
136
136
|
|
|
137
|
-
`ShellNav` continua disponível para uma navegação plana com cabeçalho próprio e grupos ancorados no
|
|
138
|
-
rodapé, mas está descontinuado: código novo usa `SidebarNav`, que cobre o mesmo caso integrado à
|
|
139
|
-
`Sidebar`. Ele gerencia a rolagem internamente e se adapta quando estiver dentro de uma `Sidebar`
|
|
140
|
-
recolhida.
|
|
141
|
-
|
|
142
|
-
```tsx
|
|
143
|
-
<Sidebar collapsed={collapsed}>
|
|
144
|
-
<ShellNav
|
|
145
|
-
heading={<ShellNavHeading title="Relatórios" action={<CreateReportButton />} />}
|
|
146
|
-
groups={reportGroups}
|
|
147
|
-
footer={settingsGroups}
|
|
148
|
-
activeId={activeId}
|
|
149
|
-
onSelect={navigateToReport}
|
|
150
|
-
/>
|
|
151
|
-
</Sidebar>
|
|
152
|
-
```
|
|
153
|
-
|
|
154
137
|
## Recolher a coluna
|
|
155
138
|
|
|
156
|
-
`collapsed` pertence à `Sidebar`. Nesse estado, `SidebarItem
|
|
139
|
+
`collapsed` pertence à `Sidebar`. Nesse estado, `SidebarItem` e `SidebarNav` mantêm
|
|
157
140
|
somente os ícones e expõem os rótulos em tooltips. Por isso, todo destino que aparece no modo
|
|
158
141
|
recolhido precisa de um ícone reconhecível e de um `label` completo.
|
|
159
142
|
|
|
@@ -329,26 +312,3 @@ O driver de drag-and-drop continua externo e fornece seus atributos por `dragPro
|
|
|
329
312
|
|---|---|---|---|
|
|
330
313
|
| `className` | `string` | | Ajusta o grupo sem substituir o recuo, o espaçamento e a guia vertical padrão. |
|
|
331
314
|
| `children` | `ReactNode` | | Itens ou grupos que descendem do nó anterior. |
|
|
332
|
-
|
|
333
|
-
## Propriedades de ShellNav
|
|
334
|
-
|
|
335
|
-
| Propriedade | Tipo | Padrão | Descrição |
|
|
336
|
-
|---|---|---|---|
|
|
337
|
-
| `groups` | `ShellNavGroup[]` | | Grupos planos exibidos na região rolável. Grupos vazios são omitidos. |
|
|
338
|
-
| `activeId` | `string` | | Identificador do destino atual. |
|
|
339
|
-
| `onSelect` | `(id: string) => void` | | Recebe o identificador selecionado. |
|
|
340
|
-
| `heading` | `ReactNode` | | Conteúdo fixo acima da navegação; fica oculto no modo recolhido. |
|
|
341
|
-
| `footer` | `ShellNavGroup[]` | | Grupos ancorados abaixo da região rolável. |
|
|
342
|
-
| `navLabel` | `string` | `'Navegação'` | Nome acessível da landmark `nav`. |
|
|
343
|
-
| `className` | `string` | | Ajusta a coluna da navegação. A largura vem do contêiner. |
|
|
344
|
-
|
|
345
|
-
Cada `ShellNavGroup` recebe `label` opcional e `items`. Um `ShellNavItem` declara `id`, `label`,
|
|
346
|
-
`icon`, `badge` e `disabled`.
|
|
347
|
-
|
|
348
|
-
## Propriedades de ShellNavHeading
|
|
349
|
-
|
|
350
|
-
| Propriedade | Tipo | Padrão | Descrição |
|
|
351
|
-
|---|---|---|---|
|
|
352
|
-
| `title` | `ReactNode` | | Título da navegação. |
|
|
353
|
-
| `action` | `ReactNode` | | Ação relacionada apresentada no extremo oposto. |
|
|
354
|
-
| `className` | `string` | | Ajusta a faixa de cabeçalho. |
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
## Carregamento sem progresso conhecido
|
|
2
2
|
|
|
3
|
-
Use `Spinner` quando a duração ou o progresso da espera não forem conhecidos. `
|
|
4
|
-
|
|
3
|
+
Use `Spinner` quando a duração ou o progresso da espera não forem conhecidos. `size` usa os nomes da
|
|
4
|
+
escala dos controles e mede o glifo do controle homônimo: `sm` é o ícone de um `Button` `sm`, `lg` o
|
|
5
|
+
de um `lg`. O ícone é decorativo; quem nomeia a espera é o contêiner (`role="status"`, como fazem
|
|
6
|
+
`DataState` e `PageState`) ou o texto ao lado.
|
|
5
7
|
|
|
6
8
|
```tsx preview
|
|
9
|
+
<Spinner size="xs" />
|
|
7
10
|
<Spinner size="sm" />
|
|
8
11
|
<Spinner />
|
|
9
12
|
<Spinner size="lg" />
|
|
@@ -20,11 +23,11 @@ andamento.
|
|
|
20
23
|
|
|
21
24
|
## Em carga de conteúdo
|
|
22
25
|
|
|
23
|
-
Espera curta sem forma definida
|
|
24
|
-
Skeleton.
|
|
26
|
+
Espera curta sem forma definida; o contêiner nomeia o estado. Para uma consulta inteira, `DataState`
|
|
27
|
+
já monta esse contêiner. Quando o conteúdo tem forma conhecida (lista, card), prefira Skeleton.
|
|
25
28
|
|
|
26
29
|
```tsx preview
|
|
27
|
-
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
|
30
|
+
<div role="status" className="flex items-center gap-2 text-sm text-muted-foreground">
|
|
28
31
|
<Spinner />
|
|
29
32
|
<span>Carregando sessões…</span>
|
|
30
33
|
</div>
|
|
@@ -34,4 +37,4 @@ Skeleton.
|
|
|
34
37
|
|
|
35
38
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
36
39
|
|---|---|---|---|
|
|
37
|
-
| `size` | `'sm' \| 'default' \| 'lg'` | `'default'` | O
|
|
40
|
+
| `size` | `'xs' \| 'sm' \| 'default' \| 'lg'` | `'default'` | O glifo do controle homônimo na escala única (0.875 · 0.875 · 1 · 1.25rem). |
|
|
@@ -66,5 +66,5 @@ disabled esmaece e bloqueia a chave — ligada ou desligada — e o rótulo em p
|
|
|
66
66
|
| `checked` | `boolean` | | O estado, no modo controlado — parear com onCheckedChange. |
|
|
67
67
|
| `onCheckedChange` | `(checked: boolean) => void` | | Chamado a cada alternância, com o novo estado. |
|
|
68
68
|
| `defaultChecked` | `boolean` | `false` | Estado inicial no modo não controlado. |
|
|
69
|
-
| `size` | `'sm' \| 'default'` | `'default'` | Tamanho da chave — sm para densidade em linha de lista. |
|
|
69
|
+
| `size` | `'sm' \| 'default'` | `'default'` | Tamanho da chave, com os nomes da escala única — sm para densidade em linha de lista. |
|
|
70
70
|
| `disabled` | `boolean` | `false` | Esmaece e bloqueia — o Label em par esmaece junto (peer-disabled). |
|
|
@@ -92,7 +92,7 @@ lateral do gatilho.
|
|
|
92
92
|
| `defaultValue` | `string` | | Aba inicial no modo não controlado. |
|
|
93
93
|
| `value` | `string` | | Aba ativa no modo controlado. Use com `onValueChange`. |
|
|
94
94
|
| `onValueChange` | `(value: string) => void` | | Chamado quando a pessoa seleciona outra aba. |
|
|
95
|
-
| `size` | `'default' \| 'sm'` | `'default'` |
|
|
95
|
+
| `size` | `'default' \| 'sm'` | `'default'` | Altura da lista na escala única dos controles (2.25 e 2rem), aplicada em `TabsList`. |
|
|
96
96
|
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Direção da lista de abas. |
|
|
97
97
|
|
|
98
98
|
## Propriedades de TabsList
|
|
@@ -70,7 +70,7 @@ disabled esmaece e bloqueia o clique — o estado pressed permanece visível.
|
|
|
70
70
|
| `onPressedChange` | `(pressed: boolean) => void` | | Chamado a cada alternância, com o novo estado. |
|
|
71
71
|
| `defaultPressed` | `boolean` | `false` | Estado inicial no modo não controlado. |
|
|
72
72
|
| `variant` | `'default' \| 'outline'` | `'default'` | default não tem borda (fundo só quando ativo); outline carrega a borda. |
|
|
73
|
-
| `size` | `'sm' \| 'default' \| 'lg'` | `'default'` | Altura
|
|
73
|
+
| `size` | `'sm' \| 'default' \| 'lg'` | `'default'` | Altura na escala única dos controles (2 · 2.25 · 2.5rem) — sm para toolbar densa, lg para alvo mais confortável. |
|
|
74
74
|
| `disabled` | `boolean` | `false` | Esmaece e bloqueia o clique, preservando o estado visual. |
|
|
75
75
|
|
|
76
76
|
## ToggleGroup
|
package/src/ui/drivers/react.tsx
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @softize/opus/ui/react — React driver
|
|
3
3
|
*
|
|
4
4
|
* Hooks + Provider pra invocar actions client-side.
|
|
5
|
-
* - `OpusProvider` — injeta ClientAdapter no contexto
|
|
5
|
+
* - `OpusProvider` — injeta ClientAdapter no contexto
|
|
6
6
|
* - `useAction(action)` — invoca actions simple/form/view
|
|
7
7
|
* - `useLookupAction(action)` — variante pra search (output Paginated)
|
|
8
8
|
*
|
|
@@ -83,11 +83,6 @@ export function OpusProvider({
|
|
|
83
83
|
return <OpusContext.Provider value={value}>{children}</OpusContext.Provider>
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
/** @deprecated Renomeado para `OpusProvider`; o alias segue até a próxima série. */
|
|
87
|
-
export const TbdlibProvider = OpusProvider
|
|
88
|
-
/** @deprecated Use `OpusProviderProps`. */
|
|
89
|
-
export type TbdlibProviderProps = OpusProviderProps
|
|
90
|
-
|
|
91
86
|
function useClient(): ClientAdapter {
|
|
92
87
|
const ctx = useContext(OpusContext)
|
|
93
88
|
if (ctx === null) {
|
package/src/ui/meta.ts
CHANGED
|
@@ -27,7 +27,7 @@ export const componentMeta = {
|
|
|
27
27
|
name: "alert",
|
|
28
28
|
ancestry: "opus",
|
|
29
29
|
whenToUse:
|
|
30
|
-
"Aviso inline no fluxo da página — `context` declara neutral/info/success/warning/danger e `variant` escolhe subtle/outline (ADR 0006). Forma curta: `<Alert title description icon context />`; para conteúdo rico, componha AlertMedia + AlertHeader (AlertTitle e AlertDescription) + AlertActions. A mídia mantém uma moldura tonal quadrada, mesmo com descrição multilinha. O texto comunica o significado sem depender só da cor. Para interromper cobrando decisão, use `dialog.confirm()`; para recado passageiro, `toast`.",
|
|
30
|
+
"Aviso inline no fluxo da página — `context` declara neutral/info/success/warning/danger e `variant` escolhe subtle/outline (ADR 0006). Forma curta: `<Alert title description icon context />`; para conteúdo rico, componha AlertMedia + AlertHeader (AlertTitle e AlertDescription) + AlertActions. Ações usam Button ghost como ponto de partida; tentativas repetidas podem usar somente o ícone, com nome acessível e tooltip. A mídia mantém uma moldura tonal quadrada, mesmo com descrição multilinha. O texto comunica o significado sem depender só da cor. Para interromper cobrando decisão, use `dialog.confirm()`; para recado passageiro, `toast`.",
|
|
31
31
|
},
|
|
32
32
|
badge: {
|
|
33
33
|
name: "badge",
|
|
@@ -69,7 +69,7 @@ export const componentMeta = {
|
|
|
69
69
|
name: "button",
|
|
70
70
|
ancestry: "shadcn",
|
|
71
71
|
whenToUse:
|
|
72
|
-
"Inicie uma ação com um controle clicável. Use `context` para o significado, `variant` para o tratamento visual e `size` para a escala; `busy` comunica o andamento e impede um novo acionamento. Para ações relacionadas, use ButtonGroup.",
|
|
72
|
+
"Inicie uma ação com um controle clicável. Use `context` para o significado, `variant` para o tratamento visual e `size` para a escala compartilhada (`xs`…`lg` e os quadrados `icon-*`); `icon` recebe um nó e `busy` comunica o andamento e impede um novo acionamento. Para ações relacionadas, use ButtonGroup conectado ou espaçado.",
|
|
73
73
|
},
|
|
74
74
|
card: {
|
|
75
75
|
name: "card",
|
|
@@ -117,7 +117,7 @@ export const componentMeta = {
|
|
|
117
117
|
name: "content-header",
|
|
118
118
|
ancestry: "opus",
|
|
119
119
|
whenToUse:
|
|
120
|
-
"Estruture
|
|
120
|
+
"Estruture uma região de conteúdo com título, contador, descrição e ações. No caso comum, declare esses valores diretamente em Content; componha ContentHeader apenas quando precisar controlar a anatomia. Contadores pertencem a Content e não ao título da Page.",
|
|
121
121
|
},
|
|
122
122
|
copyable: {
|
|
123
123
|
name: "copyable",
|
|
@@ -129,7 +129,7 @@ export const componentMeta = {
|
|
|
129
129
|
name: "dialog",
|
|
130
130
|
ancestry: "opus",
|
|
131
131
|
whenToUse:
|
|
132
|
-
|
|
132
|
+
'Abra conteúdo ou uma tarefa em uma janela modal com foco contido. Use o modo padrão quando a superfície puder ser dispensada e `mode="alert"` quando exigir resposta explícita. Para o caso imperativo comum, use `dialog.alert`, `dialog.confirm`, `dialog.prompt` ou `dialog.choose`. Distribua conteúdo próprio entre cabeçalho, corpo rolável e rodapé de ações.',
|
|
133
133
|
},
|
|
134
134
|
input: {
|
|
135
135
|
name: "input",
|
|
@@ -183,7 +183,7 @@ export const componentMeta = {
|
|
|
183
183
|
name: "spinner",
|
|
184
184
|
ancestry: "shadcn",
|
|
185
185
|
whenToUse:
|
|
186
|
-
|
|
186
|
+
'Indique uma espera sem progresso determinado, como uma ação ou consulta em andamento. O ícone é decorativo: o contêiner (`role="status"`) ou o texto ao lado nomeia a espera. Para reservar a forma do conteúdo, use Skeleton.',
|
|
187
187
|
},
|
|
188
188
|
table: {
|
|
189
189
|
name: "table",
|
|
@@ -327,7 +327,7 @@ export const componentMeta = {
|
|
|
327
327
|
name: "sidebar",
|
|
328
328
|
ancestry: "opus",
|
|
329
329
|
whenToUse:
|
|
330
|
-
"Organize navegação global ou contextual em uma coluna lateral. Split e Pane definem posição e largura; Sidebar fornece a superfície e o colapso, enquanto PaneHeader, PaneBody e PaneFooter estruturam as regiões fixa e rolável. Use SidebarNav para grupos planos
|
|
330
|
+
"Organize navegação global ou contextual em uma coluna lateral. Split e Pane definem posição e largura; Sidebar fornece a superfície e o colapso, enquanto PaneHeader, PaneBody e PaneFooter estruturam as regiões fixa e rolável. Use SidebarNav para grupos planos e componha árvores com SidebarItem e SidebarTreeGroup; cabeçalho e rodapé próprios ficam em PaneHeader e PaneFooter.",
|
|
331
331
|
},
|
|
332
332
|
"scroll-area": {
|
|
333
333
|
name: "scroll-area",
|
|
@@ -400,7 +400,7 @@ export const componentMeta = {
|
|
|
400
400
|
name: "page",
|
|
401
401
|
ancestry: "opus",
|
|
402
402
|
whenToUse:
|
|
403
|
-
"O esqueleto de página do back-office: <main> + container centralizado com teto padrão de 80rem (`max-w-7xl`). O shorthand
|
|
403
|
+
"O esqueleto de página do back-office: <main> + container centralizado com teto padrão de 80rem (`max-w-7xl`). O shorthand cobre título, descrição e ações; a forma explícita acrescenta PageBack para retorno simples ou PageNavigation para uma trilha e permite `PageHeader variant=\"bar\"` quando a mesma anatomia precisar virar uma faixa compacta. No header padrão, PageBack fica acima do título; na barra, vira icon-only com tooltip. PageActionsTarget fica restrito a workspaces imersivos com chrome próprio. Quando todo o body estiver carregando, falhar ou estiver vazio, use PageState: ele oculta o header e ocupa a área disponível, centralizado e sem moldura. Para uma região disponível à criação ou vínculo, use Empty.",
|
|
404
404
|
},
|
|
405
405
|
router: {
|
|
406
406
|
name: "router",
|
|
@@ -412,7 +412,7 @@ export const componentMeta = {
|
|
|
412
412
|
name: "data-state",
|
|
413
413
|
ancestry: "opus",
|
|
414
414
|
whenToUse:
|
|
415
|
-
"Coordene carregamento, erro, vazio e conteúdo de uma consulta assíncrona
|
|
415
|
+
"Coordene carregamento, erro, vazio e conteúdo de uma consulta assíncrona com as mesmas superfícies de PageState: `emptyMessage` compõe Empty com moldura sólida, o erro é um Alert com `onRetry` e `retryLabel`. Use DataState dentro da estrutura que receberá os dados; para uma região disponível à criação, use Empty. Ações em andamento pertencem ao estado `busy` do controle que as iniciou.",
|
|
416
416
|
},
|
|
417
417
|
"action-list-dialog": {
|
|
418
418
|
name: "action-list-dialog",
|