@softize/opus 30.0.0 → 31.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +123 -0
- package/bin/lib/check.mjs +109 -101
- package/bin/lib/copy.mjs +2973 -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/0060-surface-composition-separates-chrome-and-intro.md +142 -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/0066-civil-date-input-and-calendar-list.md +28 -0
- package/docs/adr/README.md +6 -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 +13 -11
- package/registry/skills/build-opus-ui/references/ui-patterns.md +24 -27
- package/src/core/presentation.ts +938 -32
- package/src/core/types.ts +2 -0
- package/src/ui/components/patterns/form.tsx +22 -1
- package/src/ui/components/patterns/grouped-list.ts +2 -2
- package/src/ui/components/patterns/list-calendar.tsx +129 -0
- package/src/ui/components/patterns/list.tsx +612 -382
- package/src/ui/components/patterns/page-heading-context.tsx +12 -5
- package/src/ui/components/patterns/page.tsx +227 -197
- 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 +23 -32
- package/src/ui/components/patterns/surface-anatomy.ts +27 -217
- package/src/ui/components/patterns/surface.tsx +19 -29
- package/src/ui/components/patterns/trigger.tsx +10 -2
- package/src/ui/components/primitives/calendar.tsx +39 -18
- package/src/ui/components/primitives/close-button.tsx +11 -3
- package/src/ui/components/primitives/command.tsx +2 -8
- package/src/ui/components/primitives/date-input.tsx +276 -0
- package/src/ui/components/primitives/detail.tsx +1 -1
- package/src/ui/components/primitives/dialog.tsx +19 -81
- package/src/ui/components/primitives/drawer.tsx +17 -79
- 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 +1 -1
- package/src/ui/components/primitives/tabs.tsx +13 -2
- package/src/ui/docs/content/action-form.md +6 -1
- package/src/ui/docs/content/action-list.md +156 -68
- package/src/ui/docs/content/action-trigger.md +5 -0
- package/src/ui/docs/content/button.md +5 -6
- package/src/ui/docs/content/calendar-month-view.md +50 -0
- package/src/ui/docs/content/calendar.md +6 -1
- package/src/ui/docs/content/command.md +62 -50
- package/src/ui/docs/content/compositions.md +129 -459
- package/src/ui/docs/content/date-input.md +67 -0
- package/src/ui/docs/content/dialog.md +44 -112
- package/src/ui/docs/content/drawer.md +44 -103
- package/src/ui/docs/content/field.md +2 -1
- package/src/ui/docs/content/input.md +3 -0
- package/src/ui/docs/content/page.md +204 -412
- 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 +65 -120
- package/src/ui/docs/content/tokens.md +18 -4
- package/src/ui/docs/registry.tsx +38 -9
- package/src/ui/drivers/context.tsx +11 -4
- package/src/ui/drivers/react.tsx +27 -7
- package/src/ui/meta.ts +17 -6
- package/src/ui/react.tsx +41 -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.
|
|
90
|
-
|
|
91
|
-
```tsx preview col
|
|
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
|
-
```
|
|
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.
|
|
114
104
|
|
|
115
|
-
##
|
|
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
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
forma curta com `PageHeader` ou `PageBody`.
|
|
183
|
-
|
|
184
|
-
```tsx preview col
|
|
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
|
-
```
|
|
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.
|
|
206
138
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
[Composições](/ui/compositions) compara essa forma, com o título no corpo, à forma compacta, com o
|
|
211
|
-
título no cabeçalho.
|
|
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.
|
|
212
142
|
|
|
213
|
-
##
|
|
143
|
+
## Rodapé de etapa
|
|
214
144
|
|
|
215
|
-
Use `PageFooter` quando a
|
|
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,209 +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.
|
|
281
|
-
|
|
282
|
-
## Levar as ações para um hospedeiro próprio
|
|
283
|
-
|
|
284
|
-
Use `PageActionsTarget` somente quando um hospedeiro próprio tiver uma região externa para elas: as
|
|
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.
|
|
288
|
-
|
|
289
|
-
```tsx preview col
|
|
290
|
-
function Example() {
|
|
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
|
|
162
|
+
## Carregamento, erro e ausência
|
|
319
163
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
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.
|
|
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.
|
|
328
167
|
|
|
329
168
|
```tsx preview col
|
|
330
|
-
<Page title="
|
|
331
|
-
<PageState
|
|
332
|
-
status="error"
|
|
333
|
-
title="Não foi possível carregar o relatório"
|
|
334
|
-
description="Tente novamente. Se o problema continuar, volte mais tarde."
|
|
335
|
-
onRetry={() => {}}
|
|
336
|
-
retryLabel="Tentar novamente"
|
|
337
|
-
/>
|
|
338
|
-
</Page>
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
`loading` centraliza o `Spinner` num contêiner `role="status"`; `error` usa a mesma anatomia visual
|
|
342
|
-
centralizada dos outros estados, conserva `role="alert"` e oferece uma ação `outline` textual quando
|
|
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`.
|
|
347
|
-
|
|
348
|
-
```tsx preview col
|
|
349
|
-
<Page title="Relatórios">
|
|
169
|
+
<Page title="Clientes">
|
|
350
170
|
<PageState
|
|
351
171
|
status="empty"
|
|
352
|
-
title="Nenhum
|
|
353
|
-
description="Crie
|
|
354
|
-
action={<Button>Criar relatório</Button>}
|
|
172
|
+
title="Nenhum cliente"
|
|
173
|
+
description="Crie um cliente para começar."
|
|
355
174
|
/>
|
|
356
175
|
</Page>
|
|
357
176
|
```
|
|
358
177
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
[`ActionList`](/ui/action-list) ou [`Alert`](/ui/alert).
|
|
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.
|
|
362
180
|
|
|
363
|
-
##
|
|
181
|
+
## Ações em um hospedeiro próprio
|
|
364
182
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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.
|
|
368
186
|
|
|
369
|
-
|
|
370
|
-
render(
|
|
371
|
-
<Page title="Manual de atendimento" description="Orientações para a equipe." meta={<><Badge>Publicado</Badge><span>Por Ana</span></>}>
|
|
372
|
-
<p>Conteúdo do manual.</p>
|
|
373
|
-
</Page>
|
|
374
|
-
);
|
|
375
|
-
```
|
|
187
|
+
## Migração
|
|
376
188
|
|
|
377
|
-
|
|
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.
|
|
378
196
|
|
|
379
197
|
## Propriedades de Page
|
|
380
198
|
|
|
381
|
-
| Propriedade | Tipo | Padrão
|
|
382
|
-
| ------------- | -------------------------- |
|
|
383
|
-
| `description` | `ReactNode` |
|
|
384
|
-
| `meta`
|
|
385
|
-
| `title` | `ReactNode` |
|
|
386
|
-
| `actions` | `ReactNode` |
|
|
387
|
-
| `layout` | `'flow' \| 'fill'` | `'flow'`
|
|
388
|
-
| `className` | `string` |
|
|
389
|
-
| `children` | `ReactNode` |
|
|
390
|
-
| demais | Atributos de `HTMLElement` |
|
|
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. |
|
|
391
210
|
|
|
392
211
|
## Propriedades de PageShell
|
|
393
212
|
|
|
394
|
-
| Propriedade
|
|
395
|
-
|
|
|
396
|
-
| `
|
|
397
|
-
| `
|
|
398
|
-
| `
|
|
399
|
-
|
|
|
400
|
-
| 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. |
|
|
401
219
|
|
|
402
|
-
|
|
220
|
+
A Page não insere divisores entre header, body e footer.
|
|
403
221
|
`contentClassName?: string` configura largura e alinhamento do conteúdo. O ritmo e os recuos
|
|
404
|
-
|
|
222
|
+
pertencem à Page; não use essa prop para substituir padding ou gap.
|
|
405
223
|
|
|
406
224
|
## Propriedades de PageHeader
|
|
407
225
|
|
|
408
|
-
| Propriedade | Tipo | Descrição
|
|
409
|
-
| ----------- | ----------------------------- |
|
|
410
|
-
| `
|
|
411
|
-
| `
|
|
412
|
-
|
|
|
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. |
|
|
413
232
|
|
|
414
233
|
## Propriedades de PageBack
|
|
415
234
|
|
|
416
235
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
417
236
|
| ------------ | -------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------ |
|
|
418
|
-
| `href` | `string` |
|
|
419
|
-
| `
|
|
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. |
|
|
420
241
|
| `aria-label` | `string` | `Voltar para {children}` | Nome acessível; informe-o quando `children` não for texto simples. |
|
|
421
242
|
| `onClick` | `MouseEventHandler<HTMLAnchorElement>` | | Integração opcional com o roteador do consumidor, junto do `href`, nunca no lugar dele. |
|
|
422
243
|
| `className` | `string` | | Classes adicionais do link renderizado como botão `ghost`. |
|
|
423
244
|
|
|
424
|
-
## Propriedades de PageNavigation
|
|
425
|
-
|
|
426
|
-
| Propriedade | Tipo | Descrição |
|
|
427
|
-
| ----------- | ----------------------------- | ----------------------------------------------- |
|
|
428
|
-
| `children` | `ReactNode` | Trilha estrutural, normalmente um `Breadcrumb`. |
|
|
429
|
-
| `className` | `string` | Classes adicionais do container introdutório. |
|
|
430
|
-
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao container. |
|
|
431
|
-
|
|
432
245
|
## Propriedades de PageTitle
|
|
433
246
|
|
|
434
|
-
| Propriedade | Tipo | Descrição
|
|
435
|
-
| ----------- | --------------------------------- |
|
|
436
|
-
| `children` | `ReactNode` | Título principal `h1`
|
|
437
|
-
| `className` | `string` | Classes adicionais do título.
|
|
438
|
-
| 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. |
|
|
439
252
|
|
|
440
253
|
## Propriedades de PageActions
|
|
441
254
|
|
|
@@ -457,7 +270,9 @@ continuam sob responsabilidade do body; não use essa prop para substituir paddi
|
|
|
457
270
|
|
|
458
271
|
`contentClassName?: string` configura largura e alinhamento do container interno.
|
|
459
272
|
|
|
460
|
-
|
|
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.
|
|
461
276
|
|
|
462
277
|
| Propriedade | Tipo | Descrição |
|
|
463
278
|
| ----------- | ----------------------------- | --------------------------------------------------- |
|
|
@@ -493,75 +308,52 @@ ocupa a altura.
|
|
|
493
308
|
|
|
494
309
|
## Propriedades de PageDescription
|
|
495
310
|
|
|
496
|
-
| Propriedade | Tipo | Padrão | Descrição
|
|
497
|
-
| ----------- | -------------------------------------- | ------ |
|
|
498
|
-
| `children` | `ReactNode` | | Orientação breve e opcional; filho direto
|
|
499
|
-
| `className` | `string` | | Ajusta a apresentação do parágrafo.
|
|
500
|
-
| `…props` | `HTMLAttributes<HTMLParagraphElement>` | | Atributos nativos.
|
|
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. |
|
|
501
316
|
|
|
502
|
-
##
|
|
503
|
-
|
|
504
|
-
Quando o cabeçalho também identifica o conteúdo, mantenha o título nele e omita a intro.
|
|
505
|
-
Não declare o mesmo título nas duas regiões.
|
|
506
|
-
|
|
507
|
-
```tsx preview col
|
|
508
|
-
<Page>
|
|
509
|
-
<PageHeader>
|
|
510
|
-
<PageTitle>Preferências</PageTitle>
|
|
511
|
-
</PageHeader>
|
|
512
|
-
<PageBody>Configurações da conta.</PageBody>
|
|
513
|
-
</Page>
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
## Propriedades de PageIntro
|
|
517
|
-
|
|
518
|
-
Aceita atributos HTML de `div` e exige um `PageTitle`. Recebe opcionalmente `PageDescription` e
|
|
519
|
-
`PageIntroActions`. Deve abrir o `PageBody`; navegação e ações da superfície ficam no header.
|
|
520
|
-
|
|
521
|
-
| Propriedade | Tipo | Descrição |
|
|
522
|
-
| ----------- | ----------------------------- | ------------------------------------------------------------------------ |
|
|
523
|
-
| `children` | `ReactNode` | Um `PageTitle` e, opcionalmente, `PageDescription`, `PageMeta` e `PageIntroActions`. |
|
|
524
|
-
| `className` | `string` | Classes adicionais da introdução. |
|
|
525
|
-
| demais | Atributos de `HTMLDivElement` | Repassados à região introdutória. |
|
|
526
|
-
|
|
527
|
-
## Propriedades de PageIntroActions
|
|
317
|
+
## Propriedades de PageMeta
|
|
528
318
|
|
|
529
|
-
|
|
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. |
|
|
530
323
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
| demais | Atributos de `HTMLDivElement` | Repassados ao agrupamento. |
|
|
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.
|
|
536
328
|
|
|
537
|
-
|
|
538
|
-
|
|
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.
|
|
539
332
|
|
|
540
|
-
### Divisão visual das regiões
|
|
541
333
|
|
|
542
|
-
|
|
543
|
-
Use `surfaceLayout="continuous"` para uma composição sem divisores. O header vazio continua
|
|
544
|
-
omitido. Essa escolha é independente de `layout="flow" | "fill"`, que controla a altura e a rolagem.
|
|
334
|
+
## Página centralizada
|
|
545
335
|
|
|
546
|
-
|
|
336
|
+
Para configurações curtas, escolha uma coluna estreita:
|
|
547
337
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
338
|
+
```tsx
|
|
339
|
+
<Page width="narrow" title="Segurança">
|
|
340
|
+
<SecuritySettings />
|
|
341
|
+
</Page>
|
|
342
|
+
```
|
|
552
343
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
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.
|
|
556
348
|
|
|
557
|
-
##
|
|
349
|
+
## Largura da coluna
|
|
558
350
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
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.
|
|
563
355
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
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.
|