@softize/opus 29.0.0 → 31.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 +137 -0
- package/bin/lib/check.mjs +178 -94
- package/bin/lib/copy.mjs +2970 -1801
- package/docs/adr/0043-neutral-surfaces-and-interactions-use-opaque-role-tokens.md +52 -0
- package/docs/adr/0044-neutral-appearance-derives-from-bounded-axes-per-mode.md +27 -2
- package/docs/adr/0045-surface-replaces-content-and-card.md +3 -0
- package/docs/adr/0060-surface-composition-separates-chrome-and-intro.md +142 -0
- package/docs/adr/0062-listas-contidas-e-texto-flexivel.md +68 -0
- package/docs/adr/0063-metadados-das-superficies.md +44 -0
- package/docs/adr/0064-action-list-com-itens-e-fontes-externas.md +47 -0
- package/docs/adr/0065-presentation-composes-settings-sections.md +295 -0
- package/docs/adr/README.md +8 -0
- package/package.json +1 -1
- package/registry/skills/build-opus-ui/SKILL.md +21 -19
- package/registry/skills/build-opus-ui/references/evaluations.md +21 -10
- package/registry/skills/build-opus-ui/references/ui-patterns.md +33 -28
- package/src/core/presentation.ts +938 -32
- package/src/core/types.ts +2 -1
- package/src/ui/components/patterns/form.tsx +2 -0
- package/src/ui/components/patterns/grouped-list.ts +2 -2
- package/src/ui/components/patterns/list.tsx +588 -365
- package/src/ui/components/patterns/page-heading-context.tsx +12 -5
- package/src/ui/components/patterns/page.tsx +238 -181
- package/src/ui/components/patterns/presentation-fields.tsx +246 -0
- package/src/ui/components/patterns/presentation-sections.tsx +494 -0
- package/src/ui/components/patterns/presentation.tsx +1142 -229
- package/src/ui/components/patterns/structural-header.tsx +47 -34
- package/src/ui/components/patterns/surface-anatomy.ts +27 -217
- package/src/ui/components/patterns/surface.tsx +55 -37
- package/src/ui/components/patterns/trigger.tsx +10 -2
- package/src/ui/components/primitives/close-button.tsx +11 -3
- package/src/ui/components/primitives/command.tsx +2 -8
- package/src/ui/components/primitives/detail.tsx +1 -1
- package/src/ui/components/primitives/dialog.tsx +59 -89
- package/src/ui/components/primitives/drawer.tsx +52 -87
- package/src/ui/components/primitives/field.tsx +1 -1
- package/src/ui/components/primitives/pagination.tsx +3 -2
- package/src/ui/components/primitives/table.tsx +3 -3
- package/src/ui/components/primitives/tabs.tsx +13 -2
- package/src/ui/docs/content/action-form.md +2 -1
- package/src/ui/docs/content/action-list.md +146 -73
- package/src/ui/docs/content/action-trigger.md +5 -0
- package/src/ui/docs/content/button.md +5 -6
- package/src/ui/docs/content/command.md +62 -50
- package/src/ui/docs/content/compositions.md +129 -459
- package/src/ui/docs/content/dialog.md +72 -101
- package/src/ui/docs/content/drawer.md +69 -92
- package/src/ui/docs/content/field.md +2 -1
- package/src/ui/docs/content/page.md +207 -386
- package/src/ui/docs/content/presentation.md +371 -23
- package/src/ui/docs/content/separator.md +1 -1
- package/src/ui/docs/content/surface.md +94 -116
- package/src/ui/docs/content/table.md +7 -0
- package/src/ui/docs/content/tokens.md +18 -4
- package/src/ui/drivers/context.tsx +11 -4
- package/src/ui/drivers/react.tsx +27 -7
- package/src/ui/meta.ts +5 -5
- package/src/ui/react.tsx +38 -8
- package/src/ui/theme.css +44 -33
|
@@ -1,229 +1,155 @@
|
|
|
1
|
-
##
|
|
1
|
+
## Página com cabeçalho único
|
|
2
2
|
|
|
3
|
-
Use `Page` para
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Use `Page` para reunir título, ações e conteúdo em uma coluna aberta, sem divisores
|
|
4
|
+
entre regiões. A coluna tem padding de `2,5rem` em todos os lados, intervalo de `1,5rem`
|
|
5
|
+
entre cabeçalho e conteúdo, `1rem` entre as demais regiões e título de `1,875rem`.
|
|
6
|
+
A largura e a ocupação de altura são independentes:
|
|
7
|
+
`flow` rola a página inteira; `fill` mantém o cabeçalho visível e entrega a altura restante
|
|
8
|
+
ao conteúdo. Drawer e Dialog conservam seus recuos de `1rem` e superfícies delimitadas.
|
|
7
9
|
|
|
8
|
-
A forma curta
|
|
9
|
-
exige exatamente um heading principal. Use `PageTitle` na intro ou no cabeçalho, `Surface level={1}` no body,
|
|
10
|
-
ou deixe um `PageState` ativo assumir esse papel. O cabeçalho pode ser omitido quando o próprio
|
|
11
|
-
conteúdo nomeia a página. Contadores e outros indicadores pertencem ao conteúdo que os explica.
|
|
10
|
+
A forma curta cobre páginas comuns:
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
```tsx preview col
|
|
13
|
+
<Page title="Clientes" actions={<Button size="default">Criar cliente</Button>}>
|
|
14
|
+
<p>Conteúdo da listagem.</p>
|
|
15
|
+
</Page>
|
|
16
|
+
```
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
`
|
|
20
|
-
|
|
18
|
+
Use `default` para ações textuais do cabeçalho e `icon` para ícones. A linha reserva
|
|
19
|
+
`2,25rem` mesmo sem botões, evitando variação na altura. Drawer, Dialog e Surface compartilham
|
|
20
|
+
essa escala nos headers. Controles do body e dos menus mantêm sua escala local.
|
|
21
21
|
|
|
22
|
-
`
|
|
23
|
-
|
|
24
|
-
barra visual. Tabs ficam reservados a recortes da mesma superfície. Canvas e outros workspaces
|
|
25
|
-
espaciais imersivos podem usar um shell próprio.
|
|
22
|
+
`PageActions` usa `ButtonGroup` internamente, sem moldura e com o espaçamento padrão de `0,25rem`.
|
|
23
|
+
O voltar e as ações fornecidas pelo shell e pela página entram no mesmo grupo, nessa ordem.
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
## Composição explícita
|
|
26
|
+
|
|
27
|
+
Use os slots para acrescentar metadados ou compor as ações diretamente. Declare um título
|
|
28
|
+
principal no header. Não misture `title` da forma curta com `PageHeader` ou `PageBody`.
|
|
30
29
|
|
|
31
30
|
```tsx preview col
|
|
32
|
-
|
|
33
|
-
<
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
<div className="rounded-lg border border-dashed border-border p-10 text-center text-sm text-muted-foreground">
|
|
43
|
-
O conteúdo da página (tabela, cards, grid…).
|
|
44
|
-
</div>
|
|
45
|
-
</Page>
|
|
46
|
-
</div>,
|
|
47
|
-
);
|
|
31
|
+
<Page>
|
|
32
|
+
<PageHeader>
|
|
33
|
+
<PageTitle>Carla Souza</PageTitle>
|
|
34
|
+
<PageMeta>Atualizado hoje · Por: Marina</PageMeta>
|
|
35
|
+
<PageActions>
|
|
36
|
+
<Button size="default">Editar</Button>
|
|
37
|
+
</PageActions>
|
|
38
|
+
</PageHeader>
|
|
39
|
+
<PageBody>Dados do cliente.</PageBody>
|
|
40
|
+
</Page>
|
|
48
41
|
```
|
|
49
42
|
|
|
50
|
-
|
|
43
|
+
`description` e `PageDescription` são orientações breves e opcionais. Regras necessárias
|
|
44
|
+
à decisão pertencem aos campos, às ações ou ao corpo. `PageMeta` recebe badges, autoria e
|
|
45
|
+
datas; o slot ausente não reserva espaço.
|
|
51
46
|
|
|
52
|
-
|
|
53
|
-
ajudar a reconhecer a finalidade da página. Omita texto que só repita o título. Regras de negócio,
|
|
54
|
-
limites e consequências ficam nos campos, ações ou corpo em que são necessários. Pular o
|
|
55
|
-
subheading não deve comprometer a decisão nem a conclusão correta da tarefa.
|
|
47
|
+
## Abas no cabeçalho
|
|
56
48
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
49
|
+
Use `PageHeader.tabs` para reunir as abas ao cabeçalho. Com `layout="fill"`, elas
|
|
50
|
+
permanecem visíveis durante a rolagem dos resultados.
|
|
51
|
+
Envolva a página em `Tabs`, coloque `TabsList` no header e `TabsPanel` no body.
|
|
52
|
+
O cabeçalho fornece o alinhamento; seleção, indicador ativo e teclado continuam no Tabs. Ações da coleção ficam na barra da listagem dentro do painel ativo. `PageActions`
|
|
53
|
+
recebe somente ações gerais da página, sem repetir o título no painel.
|
|
54
|
+
|
|
55
|
+
```tsx preview col
|
|
56
|
+
<Tabs defaultValue="deliveries" className="min-h-0 flex-1">
|
|
57
|
+
<Page>
|
|
58
|
+
<PageHeader
|
|
59
|
+
tabs={
|
|
60
|
+
<TabsList aria-label="Configurações de e-mail">
|
|
61
|
+
<TabsListItem value="deliveries">Envios</TabsListItem>
|
|
62
|
+
<TabsListItem value="senders">Remetentes</TabsListItem>
|
|
63
|
+
</TabsList>
|
|
64
|
+
}
|
|
65
|
+
>
|
|
66
|
+
<PageTitle>E-mails</PageTitle>
|
|
67
|
+
</PageHeader>
|
|
68
|
+
<PageBody>
|
|
69
|
+
<TabsPanel value="deliveries">Acompanhe as entregas de e-mail.</TabsPanel>
|
|
70
|
+
<TabsPanel value="senders">Configure os remetentes.</TabsPanel>
|
|
71
|
+
</PageBody>
|
|
72
|
+
</Page>
|
|
73
|
+
</Tabs>
|
|
64
74
|
```
|
|
65
75
|
|
|
76
|
+
`DrawerHeader`, `DialogHeader` e `SurfaceHeader` oferecem a mesma região `tabs`.
|
|
77
|
+
Ela recebe abas horizontais. Alertas e legendas de fieldset não aceitam essa região.
|
|
78
|
+
Para listas que ocupam a altura disponível, use `Page layout="fill"`; o `TabsPanel`
|
|
79
|
+
repassa essa altura à lista ativa. Sem `tabs`, a geometria do header permanece igual.
|
|
80
|
+
|
|
66
81
|
## Retorno para a página pai
|
|
67
82
|
|
|
68
|
-
Use `PageBack`
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
`
|
|
83
|
+
Use `PageBack` com `href` explícito, que continue correto após acesso por link direto.
|
|
84
|
+
Para retorno controlado por uma pilha de Presentation, use `onBack` no lugar de `href`: ele
|
|
85
|
+
renderiza um botão acessível e aceita `disabled` durante operações.
|
|
86
|
+
Ele aparece como primeiro ícone das ações, em `ghost`, com nome acessível e tooltip.
|
|
87
|
+
O aplicativo precisa de `TooltipProvider`, como nos demais controles com tooltip.
|
|
72
88
|
|
|
73
89
|
```tsx preview col
|
|
74
90
|
<Page>
|
|
75
91
|
<PageHeader>
|
|
76
92
|
<PageBack href="/customers">Clientes</PageBack>
|
|
93
|
+
<PageTitle>Carla Souza</PageTitle>
|
|
94
|
+
<PageActions>
|
|
95
|
+
<Button size="default">Editar</Button>
|
|
96
|
+
</PageActions>
|
|
77
97
|
</PageHeader>
|
|
78
|
-
<PageBody>
|
|
79
|
-
<PageIntro>
|
|
80
|
-
<PageTitle>Qualidade da base</PageTitle>
|
|
81
|
-
</PageIntro>
|
|
82
|
-
Conteúdo da análise.
|
|
83
|
-
</PageBody>
|
|
98
|
+
<PageBody>Dados do cliente.</PageBody>
|
|
84
99
|
</Page>
|
|
85
100
|
```
|
|
86
101
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
ocupa a mesma posição introdutória sem transformar a trilha em ação.
|
|
102
|
+
O retorno também pode ser declarado primeiro dentro de `PageActions`. Páginas raiz
|
|
103
|
+
não precisam dele. A navegação corrente não recebe uma segunda barra de breadcrumb.
|
|
90
104
|
|
|
91
|
-
|
|
92
|
-
<Page>
|
|
93
|
-
<PageHeader>
|
|
94
|
-
<PageNavigation>
|
|
95
|
-
<Breadcrumb>
|
|
96
|
-
<BreadcrumbList>
|
|
97
|
-
<BreadcrumbItem>Vendas</BreadcrumbItem>
|
|
98
|
-
<BreadcrumbSeparator />
|
|
99
|
-
<BreadcrumbItem>Clientes</BreadcrumbItem>
|
|
100
|
-
<BreadcrumbSeparator />
|
|
101
|
-
<BreadcrumbPage>Carla Souza</BreadcrumbPage>
|
|
102
|
-
</BreadcrumbList>
|
|
103
|
-
</Breadcrumb>
|
|
104
|
-
</PageNavigation>
|
|
105
|
-
</PageHeader>
|
|
106
|
-
<PageBody>
|
|
107
|
-
<PageIntro>
|
|
108
|
-
<PageTitle>Carla Souza</PageTitle>
|
|
109
|
-
</PageIntro>
|
|
110
|
-
Dados do cliente.
|
|
111
|
-
</PageBody>
|
|
112
|
-
</Page>
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
## Contexto conhecido pelo shell
|
|
105
|
+
## Ações conhecidas pelo shell
|
|
116
106
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
navegação e as ações do shell no `PageHeader` estável da página ativa.
|
|
107
|
+
`PageShell` entrega ações à Page descendente sem desenhar outro cabeçalho. Declare o retorno
|
|
108
|
+
antes das demais ações. Isso permite à aplicação escolher o pai e à rota cuidar do conteúdo.
|
|
120
109
|
|
|
121
110
|
```tsx preview col
|
|
122
|
-
<PageShell
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
<BreadcrumbList>
|
|
126
|
-
<BreadcrumbItem>Vendas</BreadcrumbItem>
|
|
127
|
-
<BreadcrumbSeparator />
|
|
128
|
-
<BreadcrumbPage>Clientes</BreadcrumbPage>
|
|
129
|
-
</BreadcrumbList>
|
|
130
|
-
</Breadcrumb>
|
|
131
|
-
}
|
|
132
|
-
>
|
|
133
|
-
<Page
|
|
134
|
-
title="Clientes"
|
|
135
|
-
actions={
|
|
136
|
-
<Button variant="outline" size="sm">
|
|
137
|
-
Exportar
|
|
138
|
-
</Button>
|
|
139
|
-
}
|
|
140
|
-
>
|
|
141
|
-
Conteúdo da listagem.
|
|
111
|
+
<PageShell actions={<PageBack href="/customers">Clientes</PageBack>}>
|
|
112
|
+
<Page title="Carla Souza" actions={<Button size="default">Editar</Button>}>
|
|
113
|
+
Dados do cliente.
|
|
142
114
|
</Page>
|
|
143
115
|
</PageShell>
|
|
144
116
|
```
|
|
145
117
|
|
|
146
|
-
|
|
147
|
-
Se uma ação não puder ser executada sem o conteúdo, a própria rota deve omiti-la naquele estado.
|
|
118
|
+
## Listas e rolagem
|
|
148
119
|
|
|
149
|
-
|
|
120
|
+
Use `layout="fill"` quando a lista deve ocupar a altura disponível. `ActionList` recebe a
|
|
121
|
+
altura por `PageBody` e mantém sua própria rolagem. O título pertence ao header da Page;
|
|
122
|
+
criação e outras operações da coleção ficam em `ActionList.toolbarActions`. Uma `Surface`
|
|
123
|
+
no body representa uma seção subordinada, não outro título principal.
|
|
150
124
|
|
|
151
|
-
```tsx
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
</BreadcrumbList>
|
|
160
|
-
</Breadcrumb>
|
|
161
|
-
}
|
|
162
|
-
>
|
|
163
|
-
<Page>
|
|
164
|
-
<PageHeader>
|
|
165
|
-
<PageActions>
|
|
166
|
-
<Button size="sm">Exportar</Button>
|
|
167
|
-
</PageActions>
|
|
168
|
-
</PageHeader>
|
|
169
|
-
<PageBody>
|
|
170
|
-
<PageIntro>
|
|
171
|
-
<PageTitle>Clientes</PageTitle>
|
|
172
|
-
</PageIntro>
|
|
173
|
-
Conteúdo da listagem.
|
|
174
|
-
</PageBody>
|
|
175
|
-
</Page>
|
|
176
|
-
</PageShell>
|
|
125
|
+
```tsx
|
|
126
|
+
<Page title="Clientes" layout="fill">
|
|
127
|
+
<ActionList
|
|
128
|
+
action={customerListContract}
|
|
129
|
+
input={{}}
|
|
130
|
+
toolbarActions={<Button aria-label="Criar cliente">Criar</Button>}
|
|
131
|
+
/>
|
|
132
|
+
</Page>
|
|
177
133
|
```
|
|
178
134
|
|
|
179
|
-
|
|
135
|
+
`flow`, o padrão, rola título e conteúdo juntos. `fill` mantém o header visível e permite
|
|
136
|
+
que uma região interna assuma a rolagem. Preserve a cadeia de altura no layout que hospeda
|
|
137
|
+
a Page; não acrescente outro contêiner vertical com rolagem ao redor.
|
|
180
138
|
|
|
181
|
-
|
|
182
|
-
|
|
139
|
+
O body separa seus blocos diretos por `1rem`. Uma grade ou grupo com ritmo próprio fica
|
|
140
|
+
num wrapper filho. O padding externo pertence à coluna; PageBody não acrescenta outro
|
|
141
|
+
recuo ao conteúdo.
|
|
183
142
|
|
|
184
|
-
|
|
185
|
-
render(
|
|
186
|
-
<Page>
|
|
187
|
-
<PageHeader>
|
|
188
|
-
<PageActions>
|
|
189
|
-
<Button variant="outline" size="sm">
|
|
190
|
-
Exportar
|
|
191
|
-
</Button>
|
|
192
|
-
</PageActions>
|
|
193
|
-
</PageHeader>
|
|
194
|
-
<PageBody>
|
|
195
|
-
<PageIntro>
|
|
196
|
-
<PageTitle>Workspaces</PageTitle>
|
|
197
|
-
</PageIntro>
|
|
198
|
-
|
|
199
|
-
<div className="rounded-lg border border-dashed border-border p-10 text-center">
|
|
200
|
-
O conteúdo da página.
|
|
201
|
-
</div>
|
|
202
|
-
</PageBody>
|
|
203
|
-
</Page>,
|
|
204
|
-
);
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
Em uma página de listagem, [`Surface`](/ui/surface) pode fornecer o título e as ações da coleção,
|
|
208
|
-
deixando `Page` apenas com `PageBody`. Se `PageShell` fornecer navegação ou ações nesse caso, `Page`
|
|
209
|
-
materializa somente o `PageHeader` necessário para recebê-las, sem duplicar o heading de `Surface`.
|
|
210
|
-
[Composições](/ui/compositions) compara essa forma, com o título no corpo, à forma compacta, com o
|
|
211
|
-
título no cabeçalho.
|
|
143
|
+
## Rodapé de etapa
|
|
212
144
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
Use `PageFooter` quando a página for uma etapa de um fluxo e a decisão precisar ficar ao alcance ao
|
|
216
|
-
fim do conteúdo, como confirmar uma importação. O rodapé fica depois do body, com as ações alinhadas
|
|
217
|
-
no fim da linha.
|
|
145
|
+
Use `PageFooter` quando a confirmação precisa permanecer disponível ao fim de uma etapa.
|
|
218
146
|
|
|
219
147
|
```tsx preview col
|
|
220
148
|
<Page>
|
|
221
|
-
<
|
|
222
|
-
<
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
Revise os 128 registros antes de confirmar.
|
|
226
|
-
</PageBody>
|
|
149
|
+
<PageHeader>
|
|
150
|
+
<PageTitle>Importar clientes</PageTitle>
|
|
151
|
+
</PageHeader>
|
|
152
|
+
<PageBody>Revise os registros antes de confirmar.</PageBody>
|
|
227
153
|
<PageFooter>
|
|
228
154
|
<ButtonGroup mode="spaced">
|
|
229
155
|
<Button variant="ghost">Cancelar</Button>
|
|
@@ -233,192 +159,96 @@ no fim da linha.
|
|
|
233
159
|
</Page>
|
|
234
160
|
```
|
|
235
161
|
|
|
236
|
-
##
|
|
237
|
-
|
|
238
|
-
Use `layout="fill"` quando uma região interna, como uma tabela longa ou um split, precisar rolar
|
|
239
|
-
dentro da página em vez de a página inteira rolar. A página passa a ocupar exatamente a altura do
|
|
240
|
-
contêiner. Para uma região que você mesmo compõe, dê `min-h-0 flex-1` à que assume a folga e a
|
|
241
|
-
rolagem, como o `PageBody` do exemplo.
|
|
242
|
-
|
|
243
|
-
```tsx preview col
|
|
244
|
-
render(
|
|
245
|
-
<div className="h-72 overflow-hidden rounded-lg border border-border">
|
|
246
|
-
<Page layout="fill">
|
|
247
|
-
<PageBody className="min-h-0 flex-1 overflow-y-auto">
|
|
248
|
-
<PageIntro>
|
|
249
|
-
<PageTitle>Ordens de serviço</PageTitle>
|
|
250
|
-
</PageIntro>
|
|
251
|
-
|
|
252
|
-
<div className="space-y-2">
|
|
253
|
-
{[
|
|
254
|
-
"OS-1842",
|
|
255
|
-
"OS-1839",
|
|
256
|
-
"OS-1835",
|
|
257
|
-
"OS-1830",
|
|
258
|
-
"OS-1827",
|
|
259
|
-
"OS-1821",
|
|
260
|
-
"OS-1818",
|
|
261
|
-
].map((id) => (
|
|
262
|
-
<div
|
|
263
|
-
key={id}
|
|
264
|
-
className="rounded-md border border-border p-3 text-sm"
|
|
265
|
-
>
|
|
266
|
-
{id}
|
|
267
|
-
</div>
|
|
268
|
-
))}
|
|
269
|
-
</div>
|
|
270
|
-
</PageBody>
|
|
271
|
-
</Page>
|
|
272
|
-
</div>,
|
|
273
|
-
);
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
Uma [`ActionList`](/ui/action-list) não precisa dessas classes. Filha de `PageBody`, ou de um
|
|
277
|
-
[`Surface`](/ui/surface) dentro dele, ela recebe a altura da página e assume `layout="fill"`
|
|
278
|
-
sozinha: `PageBody`, `Surface` e `SurfaceBody` passam a repassar a altura até ela, o cabeçalho da
|
|
279
|
-
tabela fica fixo e só os resultados rolam. As demais seções do `PageBody` mantêm a altura do
|
|
280
|
-
próprio conteúdo, e uma página `fill` sem lista não muda.
|
|
162
|
+
## Carregamento, erro e ausência
|
|
281
163
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
`PageActions` da árvore interna passam a ser
|
|
286
|
-
renderizadas no elemento indicado em `target`. Enquanto `target` for `null`, fora de um shell, as
|
|
287
|
-
ações continuam no cabeçalho da página.
|
|
164
|
+
`PageState` substitui o conteúdo durante um estado integral e assume o heading principal.
|
|
165
|
+
O header fica oculto nesse período; quando o conteúdo volta a ficar pronto, ele reaparece.
|
|
166
|
+
Uma falha parcial pertence à seção afetada e não deve ocultar as demais.
|
|
288
167
|
|
|
289
168
|
```tsx preview col
|
|
290
|
-
|
|
291
|
-
const [target, setTarget] = useState<HTMLElement | null>(null);
|
|
292
|
-
|
|
293
|
-
return (
|
|
294
|
-
<div className="space-y-3">
|
|
295
|
-
<div
|
|
296
|
-
ref={setTarget}
|
|
297
|
-
className="flex justify-end rounded-lg border border-border p-2"
|
|
298
|
-
/>
|
|
299
|
-
<PageActionsTarget target={target}>
|
|
300
|
-
<Page
|
|
301
|
-
title="Clientes"
|
|
302
|
-
actions={
|
|
303
|
-
<Button variant="outline" size="sm">
|
|
304
|
-
Exportar
|
|
305
|
-
</Button>
|
|
306
|
-
}
|
|
307
|
-
>
|
|
308
|
-
Conteúdo da listagem.
|
|
309
|
-
</Page>
|
|
310
|
-
</PageActionsTarget>
|
|
311
|
-
</div>
|
|
312
|
-
);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
render(<Example />);
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
## Estados integrais
|
|
319
|
-
|
|
320
|
-
Use `PageState` quando carregamento, falha ou ausência substituírem todo o conteúdo principal. Na
|
|
321
|
-
forma curta ele pode ser escrito como filho direto de `Page`, que cria o `PageBody`; na forma
|
|
322
|
-
explícita, coloque-o sozinho dentro de `PageBody`. Enquanto `status` for `loading`, `error` ou
|
|
323
|
-
`empty`, `Page` oculta o cabeçalho inteiro — incluindo a navegação e as ações recebidas de
|
|
324
|
-
`PageShell` — e o estado ocupa a altura disponível. Uma subpágina que dependa do retorno oferece a
|
|
325
|
-
saída pelo `action` do próprio `PageState`. O título do estado assume o heading principal. Esse
|
|
326
|
-
registro também funciona quando um componente intermediário decide qual `PageState` renderizar. Em
|
|
327
|
-
`ready`, o cabeçalho e o conteúdo voltam à composição normal.
|
|
328
|
-
|
|
329
|
-
```tsx preview col
|
|
330
|
-
<Page title="Relatório">
|
|
169
|
+
<Page title="Clientes">
|
|
331
170
|
<PageState
|
|
332
|
-
status="
|
|
333
|
-
title="
|
|
334
|
-
description="
|
|
335
|
-
onRetry={() => {}}
|
|
336
|
-
retryLabel="Tentar novamente"
|
|
171
|
+
status="empty"
|
|
172
|
+
title="Nenhum cliente"
|
|
173
|
+
description="Crie um cliente para começar."
|
|
337
174
|
/>
|
|
338
175
|
</Page>
|
|
339
176
|
```
|
|
340
177
|
|
|
341
|
-
`
|
|
342
|
-
|
|
343
|
-
há `onRetry`; `empty` centraliza `Empty` sem moldura; e `ready` entrega os filhos sem
|
|
344
|
-
acrescentar uma superfície. A moldura tracejada continua reservada ao `Empty` usado diretamente para
|
|
345
|
-
representar uma região disponível para criar ou vincular. `title` e `description` nomeiam a situação
|
|
346
|
-
e, sem `title`, valem `errorMessage` e `emptyMessage`.
|
|
178
|
+
Use `onRetry` para oferecer recuperação. Não crie loaders e vazios paralelos a `ActionList`
|
|
179
|
+
quando os dados pertencem a uma coleção: a lista já governa esses estados.
|
|
347
180
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
description="Crie o primeiro relatório para começar."
|
|
354
|
-
action={<Button>Criar relatório</Button>}
|
|
355
|
-
/>
|
|
356
|
-
</Page>
|
|
357
|
-
```
|
|
181
|
+
## Ações em um hospedeiro próprio
|
|
182
|
+
|
|
183
|
+
`PageActionsTarget` encaminha as ações para um elemento externo quando um hospedeiro precisa
|
|
184
|
+
dessa integração. Com `target={null}`, elas permanecem no cabeçalho. O destino deve preservar
|
|
185
|
+
nome acessível, ordem de foco e a associação com a página.
|
|
358
186
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
187
|
+
## Migração
|
|
188
|
+
|
|
189
|
+
Mova `PageIntro` para `PageHeader` e `PageIntroActions` para `PageActions`. Remova o breadcrumb
|
|
190
|
+
e use `PageBack` quando houver um pai relevante. Retire limites de largura e classes locais
|
|
191
|
+
de título e padding que duplicavam o padrão. `PageIntro`, `PageIntroActions` e `PageNavigation`
|
|
192
|
+
foram removidos, sem aliases de compatibilidade. As opções
|
|
193
|
+
`flow` e `fill` continuam disponíveis. Remova `composition` e `pageComposition`: Page
|
|
194
|
+
tem uma única aparência. Para preservar a coluna intermediária de antigos documentos,
|
|
195
|
+
declare `width="default"` ou `page: { width: "default" }`. Sem largura explícita, a Page é ampla.
|
|
362
196
|
|
|
363
197
|
## Propriedades de Page
|
|
364
198
|
|
|
365
|
-
| Propriedade | Tipo | Padrão
|
|
366
|
-
| ------------- | -------------------------- |
|
|
367
|
-
| `description` | `ReactNode` |
|
|
368
|
-
| `
|
|
369
|
-
| `
|
|
370
|
-
| `
|
|
371
|
-
| `
|
|
372
|
-
| `
|
|
373
|
-
|
|
|
199
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
200
|
+
| ------------- | -------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
201
|
+
| `description` | `ReactNode` | | Orientação opcional sob o título na forma curta. |
|
|
202
|
+
| `meta` | `ReactNode` | | Forma curta: metadados sob o título e a orientação. Exige `title`. |
|
|
203
|
+
| `title` | `ReactNode` | | O h1 da página. |
|
|
204
|
+
| `actions` | `ReactNode` | | Ações contextuais no extremo oposto do cabeçalho. |
|
|
205
|
+
| `layout` | `'flow' \| 'fill'` | `'flow'` | Ocupação de altura, não anatomia: `fill` limita a página ao shell para que uma região interna role e leva essa altura até uma `ActionList` composta em `PageBody`. |
|
|
206
|
+
| `className` | `string` | | Classes adicionais da coluna. Para escolher sua largura, use `width`. |
|
|
207
|
+
| `children` | `ReactNode` | | O body da página — espaçamento e diagramação são seus. |
|
|
208
|
+
| demais | Atributos de `HTMLElement` | | Atributos nativos repassados ao elemento `main`, como `id` ou `aria-label`. `className` vai para a moldura da página. |
|
|
209
|
+
| `width` | `'narrow' \| 'default' \| 'wide'` | `'wide'` | Limita a coluna inteira a 42rem, 58rem ou à largura disponível. |
|
|
374
210
|
|
|
375
211
|
## Propriedades de PageShell
|
|
376
212
|
|
|
377
|
-
| Propriedade
|
|
378
|
-
|
|
|
379
|
-
| `
|
|
380
|
-
| `
|
|
381
|
-
| `
|
|
382
|
-
|
|
|
383
|
-
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados à moldura. |
|
|
213
|
+
| Propriedade | Tipo | Descrição |
|
|
214
|
+
| ----------- | ----------------------------- | -------------------------------------------------------------------- |
|
|
215
|
+
| `actions` | `ReactNode` | Ações conhecidas pelo shell, antes das ações declaradas pela `Page`. |
|
|
216
|
+
| `children` | `ReactNode` | Rota que renderiza uma `Page` descendente. |
|
|
217
|
+
| `className` | `string` | Classes adicionais da moldura. |
|
|
218
|
+
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados à moldura. |
|
|
384
219
|
|
|
385
|
-
|
|
220
|
+
A Page não insere divisores entre header, body e footer.
|
|
386
221
|
`contentClassName?: string` configura largura e alinhamento do conteúdo. O ritmo e os recuos
|
|
387
|
-
|
|
222
|
+
pertencem à Page; não use essa prop para substituir padding ou gap.
|
|
388
223
|
|
|
389
224
|
## Propriedades de PageHeader
|
|
390
225
|
|
|
391
|
-
| Propriedade | Tipo | Descrição
|
|
392
|
-
| ----------- | ----------------------------- |
|
|
393
|
-
| `
|
|
394
|
-
| `
|
|
395
|
-
|
|
|
226
|
+
| Propriedade | Tipo | Descrição |
|
|
227
|
+
| ----------- | ----------------------------- | ------------------------------------------------------------------------- |
|
|
228
|
+
| `tabs` | `ReactNode` | `TabsList` sob o título, controlado por um `Tabs` ancestral. |
|
|
229
|
+
| `className` | `string` | Classes adicionais do cabeçalho estável. |
|
|
230
|
+
| `children` | `ReactNode` | `PageTitle`, metadados e ações; `PageBack` é inserido primeiro nas ações. |
|
|
231
|
+
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao cabeçalho. |
|
|
396
232
|
|
|
397
233
|
## Propriedades de PageBack
|
|
398
234
|
|
|
399
235
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
400
236
|
| ------------ | -------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------ |
|
|
401
|
-
| `href` | `string` |
|
|
402
|
-
| `
|
|
237
|
+
| `href` | `string` | | Destino explícito da página pai; obrigatório quando não há `onBack`. |
|
|
238
|
+
| `onBack` | `() => void` | | Retorno controlado pela pilha; renderiza botão e não aceita `href`. |
|
|
239
|
+
| `disabled` | `boolean` | `false` | Bloqueia o retorno quando usado com `onBack`. |
|
|
240
|
+
| `children` | `ReactNode` | obrigatório | Nome do destino pai usado no rótulo acessível e na tooltip. |
|
|
403
241
|
| `aria-label` | `string` | `Voltar para {children}` | Nome acessível; informe-o quando `children` não for texto simples. |
|
|
404
242
|
| `onClick` | `MouseEventHandler<HTMLAnchorElement>` | | Integração opcional com o roteador do consumidor, junto do `href`, nunca no lugar dele. |
|
|
405
243
|
| `className` | `string` | | Classes adicionais do link renderizado como botão `ghost`. |
|
|
406
244
|
|
|
407
|
-
## Propriedades de PageNavigation
|
|
408
|
-
|
|
409
|
-
| Propriedade | Tipo | Descrição |
|
|
410
|
-
| ----------- | ----------------------------- | ----------------------------------------------- |
|
|
411
|
-
| `children` | `ReactNode` | Trilha estrutural, normalmente um `Breadcrumb`. |
|
|
412
|
-
| `className` | `string` | Classes adicionais do container introdutório. |
|
|
413
|
-
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao container. |
|
|
414
|
-
|
|
415
245
|
## Propriedades de PageTitle
|
|
416
246
|
|
|
417
|
-
| Propriedade | Tipo | Descrição
|
|
418
|
-
| ----------- | --------------------------------- |
|
|
419
|
-
| `children` | `ReactNode` | Título principal `h1`
|
|
420
|
-
| `className` | `string` | Classes adicionais do título.
|
|
421
|
-
| demais | Atributos de `HTMLHeadingElement` | Atributos nativos repassados ao heading.
|
|
247
|
+
| Propriedade | Tipo | Descrição |
|
|
248
|
+
| ----------- | --------------------------------- | ---------------------------------------- |
|
|
249
|
+
| `children` | `ReactNode` | Título principal `h1` no header. |
|
|
250
|
+
| `className` | `string` | Classes adicionais do título. |
|
|
251
|
+
| demais | Atributos de `HTMLHeadingElement` | Atributos nativos repassados ao heading. |
|
|
422
252
|
|
|
423
253
|
## Propriedades de PageActions
|
|
424
254
|
|
|
@@ -440,7 +270,9 @@ continuam sob responsabilidade do body; não use essa prop para substituir paddi
|
|
|
440
270
|
|
|
441
271
|
`contentClassName?: string` configura largura e alinhamento do container interno.
|
|
442
272
|
|
|
443
|
-
|
|
273
|
+
O recuo externo permanece na coluna mesmo quando o body usa `flush`.
|
|
274
|
+
|
|
275
|
+
`PageBody` separa seus blocos diretos por `1rem`; o recuo externo pertence à coluna. Uma grade, lista compacta ou linha horizontal fica dentro de um wrapper próprio.
|
|
444
276
|
|
|
445
277
|
| Propriedade | Tipo | Descrição |
|
|
446
278
|
| ----------- | ----------------------------- | --------------------------------------------------- |
|
|
@@ -476,63 +308,52 @@ ocupa a altura.
|
|
|
476
308
|
|
|
477
309
|
## Propriedades de PageDescription
|
|
478
310
|
|
|
479
|
-
| Propriedade | Tipo | Padrão | Descrição
|
|
480
|
-
| ----------- | -------------------------------------- | ------ |
|
|
481
|
-
| `children` | `ReactNode` | | Orientação breve e opcional; filho direto
|
|
482
|
-
| `className` | `string` | | Ajusta a apresentação do parágrafo.
|
|
483
|
-
| `…props` | `HTMLAttributes<HTMLParagraphElement>` | | Atributos nativos.
|
|
484
|
-
|
|
485
|
-
## Composição compacta
|
|
311
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
312
|
+
| ----------- | -------------------------------------- | ------ | ---------------------------------------------------- |
|
|
313
|
+
| `children` | `ReactNode` | | Orientação breve e opcional; filho direto do header. |
|
|
314
|
+
| `className` | `string` | | Ajusta a apresentação do parágrafo. |
|
|
315
|
+
| `…props` | `HTMLAttributes<HTMLParagraphElement>` | | Atributos nativos. |
|
|
486
316
|
|
|
487
|
-
|
|
488
|
-
Não declare o mesmo título nas duas regiões.
|
|
317
|
+
## Propriedades de PageMeta
|
|
489
318
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
</PageHeader>
|
|
495
|
-
<PageBody>Configurações da conta.</PageBody>
|
|
496
|
-
</Page>
|
|
497
|
-
```
|
|
319
|
+
| Propriedade | Tipo | Descrição |
|
|
320
|
+
| ----------- | ----------- | ------------------------------------------------------- |
|
|
321
|
+
| `children` | `ReactNode` | Badges, datas, autoria ou outros metadados do registro. |
|
|
322
|
+
| `className` | `string` | Ajusta a faixa de metadados. |
|
|
498
323
|
|
|
499
|
-
|
|
324
|
+
Aceita atributos nativos de `div`. O intervalo superior é de 0,75rem; os itens têm
|
|
325
|
+
0,75rem entre colunas e 0,5rem entre linhas. O componente não insere separadores nem
|
|
326
|
+
carrega dados. Omitir o slot não reserva espaço. Metadados não substituem orientações
|
|
327
|
+
ou condições necessárias à decisão e não substituem a descrição textual da região.
|
|
500
328
|
|
|
501
|
-
|
|
502
|
-
|
|
329
|
+
Presentation com `heading: "content"` recebe uma Page completa, inclusive quando o conteúdo
|
|
330
|
+
vem de um componente de rota. O runtime rejeita conteúdo sem Page e dois rodapés concorrentes
|
|
331
|
+
(PageFooter próprio e comandos de footer da Presentation), em vez de descartar ações.
|
|
503
332
|
|
|
504
|
-
| Propriedade | Tipo | Descrição |
|
|
505
|
-
| ----------- | ----------------------------- | ------------------------------------------------------------------------ |
|
|
506
|
-
| `children` | `ReactNode` | Um `PageTitle` e, opcionalmente, `PageDescription` e `PageIntroActions`. |
|
|
507
|
-
| `className` | `string` | Classes adicionais da introdução. |
|
|
508
|
-
| demais | Atributos de `HTMLDivElement` | Repassados à região introdutória. |
|
|
509
333
|
|
|
510
|
-
##
|
|
334
|
+
## Página centralizada
|
|
511
335
|
|
|
512
|
-
|
|
336
|
+
Para configurações curtas, escolha uma coluna estreita:
|
|
513
337
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
O header ocupa toda a largura disponível. O limite de 80rem e o recuo pertencem ao conteúdo
|
|
521
|
-
interno do Body; o viewport ocupa a largura da página para manter sua barra de rolagem na extremidade.
|
|
522
|
-
|
|
523
|
-
### Divisão visual das regiões
|
|
338
|
+
```tsx
|
|
339
|
+
<Page width="narrow" title="Segurança">
|
|
340
|
+
<SecuritySettings />
|
|
341
|
+
</Page>
|
|
342
|
+
```
|
|
524
343
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
344
|
+
Título, conteúdo e rodapé compartilham o mesmo limite de largura. Com `layout="flow"`,
|
|
345
|
+
rolam juntos e a barra permanece na borda da Page. Com `layout="fill"`, o título permanece
|
|
346
|
+
visível e a lista recebe a altura restante para rolar seus resultados. Sem lista, o body rola.
|
|
347
|
+
As duas ocupações usam a mesma aparência e o mesmo padding.
|
|
528
348
|
|
|
529
|
-
## Largura
|
|
349
|
+
## Largura da coluna
|
|
530
350
|
|
|
531
|
-
`
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
351
|
+
Use `width="narrow"` para preferências curtas, `width="default"` para conteúdo intermediário e
|
|
352
|
+
`width="wide"` para tabelas que precisam da largura disponível. Os limites são 42rem, 58rem e
|
|
353
|
+
sem teto, respectivamente, incluindo o padding da coluna. Header, Body e Footer compartilham
|
|
354
|
+
esse limite; os espaçamentos internos não mudam.
|
|
535
355
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
356
|
+
Sem `width`, a Page ocupa a largura disponível. Na declaração da Presentation, use
|
|
357
|
+
`page: { width: "wide" }`. Quando o conteúdo fornece uma Page completa, ela herda essa
|
|
358
|
+
largura e pode substituí-la com sua própria prop `width`.
|
|
359
|
+
O dimensionamento de Dialog e Drawer permanece independente.
|