@softize/opus 23.0.0 → 24.0.1
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 +99 -0
- package/bin/cli.mjs +2 -0
- package/bin/lib/check.mjs +241 -42
- package/bin/lib/copy.mjs +16 -34
- package/docs/adr/0023-surfaces-share-one-anatomy-and-two-layouts.md +6 -0
- package/docs/adr/0039-filter-presentation-is-independent-from-filter-type.md +3 -3
- package/docs/adr/0040-tabs-use-a-single-navigation-presentation.md +5 -6
- package/docs/adr/0042-toggle-group-shares-the-grouped-control-grammar.md +79 -0
- package/docs/adr/0043-neutral-surfaces-and-interactions-use-opaque-role-tokens.md +73 -0
- package/docs/adr/0044-neutral-appearance-derives-from-bounded-axes-per-mode.md +133 -0
- package/docs/adr/0045-surface-replaces-content-and-card.md +230 -0
- package/docs/adr/0046-structural-body-owns-content-rhythm.md +103 -0
- package/docs/adr/0047-pane-is-only-a-split-layout-unit.md +71 -0
- package/docs/adr/0048-modal-intro-separates-content-from-chrome.md +34 -0
- package/docs/adr/0049-inline-navigation-groups-with-the-heading.md +95 -0
- package/package.json +5 -1
- package/registry/skills/build-opus-ui/SKILL.md +11 -11
- package/registry/skills/build-opus-ui/references/evaluations.md +10 -9
- package/registry/skills/build-opus-ui/references/ui-patterns.md +17 -16
- package/registry/templates/app/src/App.tsx +24 -12
- package/src/ui/appearance.ts +149 -0
- package/src/ui/components/patterns/action-form-card.tsx +46 -33
- package/src/ui/components/patterns/action-list-dialog.tsx +2 -4
- package/src/ui/components/patterns/confirm.tsx +3 -1
- package/src/ui/components/patterns/fill-region.ts +8 -7
- package/src/ui/components/patterns/form-dialog.tsx +1 -3
- package/src/ui/components/patterns/form.tsx +8 -7
- package/src/ui/components/patterns/list.tsx +15 -19
- package/src/ui/components/patterns/page.tsx +15 -11
- package/src/ui/components/patterns/pane.tsx +9 -240
- package/src/ui/components/patterns/presentation.tsx +14 -14
- package/src/ui/components/patterns/sidebar.tsx +7 -17
- package/src/ui/components/patterns/split.tsx +111 -59
- package/src/ui/components/patterns/{surface-header.tsx → structural-header.tsx} +90 -27
- package/src/ui/components/patterns/structural-media.tsx +26 -0
- package/src/ui/components/patterns/surface-anatomy.ts +71 -61
- package/src/ui/components/patterns/surface-assistant.tsx +2 -4
- package/src/ui/components/patterns/surface.tsx +620 -0
- package/src/ui/components/patterns/trigger.tsx +11 -9
- package/src/ui/components/primitives/ask.tsx +155 -83
- package/src/ui/components/primitives/button.tsx +11 -9
- package/src/ui/components/primitives/checkbox.tsx +8 -8
- package/src/ui/components/primitives/command.tsx +1 -1
- package/src/ui/components/primitives/composer.tsx +47 -45
- package/src/ui/components/primitives/detail.tsx +9 -2
- package/src/ui/components/primitives/dialog.tsx +60 -26
- package/src/ui/components/primitives/drawer.tsx +58 -12
- package/src/ui/components/primitives/icon-picker.tsx +90 -73
- package/src/ui/components/primitives/input-group.tsx +35 -28
- package/src/ui/components/primitives/input-otp.tsx +16 -16
- package/src/ui/components/primitives/input.tsx +20 -10
- package/src/ui/components/primitives/item.tsx +9 -12
- package/src/ui/components/primitives/menu.tsx +44 -65
- package/src/ui/components/primitives/metric-card.tsx +75 -59
- package/src/ui/components/primitives/radio-group.tsx +9 -9
- package/src/ui/components/primitives/select.tsx +344 -209
- package/src/ui/components/primitives/switch.tsx +10 -10
- package/src/ui/components/primitives/table.tsx +29 -24
- package/src/ui/components/primitives/tabs.tsx +4 -2
- package/src/ui/components/primitives/textarea.tsx +6 -6
- package/src/ui/components/primitives/toggle-group-context.ts +24 -0
- package/src/ui/components/primitives/toggle-group.tsx +116 -74
- package/src/ui/components/primitives/toggle.tsx +82 -16
- package/src/ui/docs/DocBrowser.tsx +77 -69
- package/src/ui/docs/content/action-form-card.md +9 -9
- package/src/ui/docs/content/action-list.md +76 -70
- package/src/ui/docs/content/action-view.md +33 -18
- package/src/ui/docs/content/button.md +1 -1
- package/src/ui/docs/content/communication.md +1 -1
- package/src/ui/docs/content/compositions.md +479 -0
- package/src/ui/docs/content/customization.md +64 -11
- package/src/ui/docs/content/detail.md +8 -6
- package/src/ui/docs/content/dialog.md +105 -60
- package/src/ui/docs/content/drawer.md +68 -22
- package/src/ui/docs/content/field.md +14 -15
- package/src/ui/docs/content/icon-tile.md +14 -13
- package/src/ui/docs/content/page.md +44 -34
- package/src/ui/docs/content/pane.md +42 -290
- package/src/ui/docs/content/presentation.md +3 -3
- package/src/ui/docs/content/separator.md +6 -6
- package/src/ui/docs/content/sidebar.md +68 -266
- package/src/ui/docs/content/skeleton.md +20 -18
- package/src/ui/docs/content/split.md +14 -14
- package/src/ui/docs/content/surface.md +513 -0
- package/src/ui/docs/content/tabs.md +20 -20
- package/src/ui/docs/content/toggle.md +117 -65
- package/src/ui/docs/content/tokens.md +124 -40
- package/src/ui/docs/registry.tsx +10 -6
- package/src/ui/index.ts +30 -27
- package/src/ui/meta.ts +15 -27
- package/src/ui/react.tsx +40 -43
- package/src/ui/theme.css +311 -64
- package/src/ui/components/patterns/content-header.tsx +0 -528
- package/src/ui/components/patterns/surface-media.tsx +0 -69
- package/src/ui/components/primitives/card.tsx +0 -191
- package/src/ui/docs/content/card.md +0 -292
- package/src/ui/docs/content/content.md +0 -275
|
@@ -17,12 +17,12 @@ variáveis.
|
|
|
17
17
|
|
|
18
18
|
```css
|
|
19
19
|
/* index.css do app — depois do import do tema. */
|
|
20
|
-
@import
|
|
20
|
+
@import "@softize/opus/ui/theme.css";
|
|
21
21
|
|
|
22
22
|
:root {
|
|
23
23
|
--primary: hsl(262 83% 58%); /* A cor da marca do projeto. */
|
|
24
24
|
--ring: hsl(262 83% 58%);
|
|
25
|
-
--radius: 0.5rem;
|
|
25
|
+
--radius: 0.5rem; /* Uma base menor deixa toda a escala mais contida. */
|
|
26
26
|
}
|
|
27
27
|
```
|
|
28
28
|
|
|
@@ -36,6 +36,55 @@ Quando o produto precisa de outra densidade, declare essa escolha no CSS do app.
|
|
|
36
36
|
Opus mede em `rem` acompanha a proporção. O valor continua sendo uma escolha do app, não uma regra
|
|
37
37
|
da biblioteca.
|
|
38
38
|
|
|
39
|
+
### Ajuste de aparência dos neutros
|
|
40
|
+
|
|
41
|
+
Quando a aplicação quer neutros levemente tingidos pela marca, camadas mais separadas ou um escuro
|
|
42
|
+
mais profundo — como padrão do produto ou como preferência de cada pessoa —, ela não precisa
|
|
43
|
+
redeclarar `--background`, `--card` e os demais tokens neutros. O tema calcula essa escala a partir
|
|
44
|
+
de quatro eixos por modo, e basta alterar os eixos. Cada um aceita um inteiro de 0 a 100; a tabela
|
|
45
|
+
com o efeito e o preset de cada eixo está em [Tokens](/ui/tokens).
|
|
46
|
+
|
|
47
|
+
Para definir o padrão do produto, declare os eixos no CSS do app. Os eixos do modo claro e os do
|
|
48
|
+
modo escuro ficam juntos em `:root`; o tema usa o conjunto do modo ativo.
|
|
49
|
+
|
|
50
|
+
```css
|
|
51
|
+
:root {
|
|
52
|
+
--neutral-hue: 262; /* O matiz da marca nos neutros. */
|
|
53
|
+
--appearance-light-color-intensity: 40;
|
|
54
|
+
--appearance-dark-color-intensity: 60;
|
|
55
|
+
--appearance-dark-surface-brightness: 30; /* Um escuro mais profundo que o preset. */
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Para aplicar a preferência de uma pessoa, use o helper de `@softize/opus/ui/appearance`. Ele
|
|
60
|
+
arredonda e limita os valores, grava os eixos informados e remove os demais. Guardar a preferência
|
|
61
|
+
e desenhar a tela de ajuste são responsabilidades da aplicação.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { applyAppearanceCustomProperties } from "@softize/opus/ui/appearance";
|
|
65
|
+
|
|
66
|
+
const style = document.documentElement.style;
|
|
67
|
+
|
|
68
|
+
// Aplica somente os eixos informados; os demais continuam no padrão.
|
|
69
|
+
applyAppearanceCustomProperties(style, "light", { layerContrast: 60 });
|
|
70
|
+
applyAppearanceCustomProperties(style, "dark", {
|
|
71
|
+
contrast: 40,
|
|
72
|
+
surfaceBrightness: 20,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Voltar ao padrão é aplicar sem overrides: as propriedades são removidas.
|
|
76
|
+
applyAppearanceCustomProperties(style, "dark");
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
O Opus não oferece um componente de reset. Sem o override, vale o que o CSS do app declarou ou,
|
|
80
|
+
na falta disso, o preset do tema. Em renderização no servidor, `appearanceCustomProperties` devolve
|
|
81
|
+
o mesmo mapa sem tocar no DOM, para a aplicação escrever os eixos no HTML inicial.
|
|
82
|
+
|
|
83
|
+
Nenhum valor de 0 a 100 deixa a interface menos legível que o tema padrão: a separação entre os
|
|
84
|
+
papéis e o contraste do texto sobre as superfícies em repouso nunca ficam abaixo do preset. Um
|
|
85
|
+
token neutro redeclarado diretamente pelo app, como `--background`, deixa de acompanhar os eixos e
|
|
86
|
+
fica fora dessa proteção.
|
|
87
|
+
|
|
39
88
|
## 2 · className em tudo
|
|
40
89
|
|
|
41
90
|
Todo componente aceita `className` e o combina com as próprias classes por tailwind-merge: quando
|
|
@@ -44,28 +93,30 @@ local, como largura, margem e grid, e não para repintar o visual dos componente
|
|
|
44
93
|
|
|
45
94
|
```tsx
|
|
46
95
|
<Button className="w-full">Continuar</Button>
|
|
47
|
-
<
|
|
96
|
+
<Surface framed elevation="raised" className="max-w-sm" />
|
|
48
97
|
<DialogContent className="max-w-2xl" />
|
|
49
98
|
```
|
|
50
99
|
|
|
51
100
|
## 3 · Recomposição estrutural
|
|
52
101
|
|
|
53
|
-
Os componentes são divididos em partes nomeadas, como `
|
|
102
|
+
Os componentes são divididos em partes nomeadas, como `SurfaceHeader` e `SurfaceBody`, e a tela usa só as
|
|
54
103
|
que precisa. `asChild` faz o filho assumir o estilo e o comportamento do componente, e as funções
|
|
55
104
|
`*Variants` aplicam o visual de um componente a um elemento qualquer.
|
|
56
105
|
|
|
57
106
|
```tsx preview
|
|
58
107
|
<Button asChild variant="outline">
|
|
59
|
-
<a href="#" onClick={(e) => e.preventDefault()}>
|
|
108
|
+
<a href="#" onClick={(e) => e.preventDefault()}>
|
|
109
|
+
Link com aparência de botão
|
|
110
|
+
</a>
|
|
60
111
|
</Button>
|
|
61
112
|
```
|
|
62
113
|
|
|
63
114
|
```tsx
|
|
64
115
|
// Partes: só o que a tela pede.
|
|
65
|
-
<
|
|
66
|
-
<
|
|
67
|
-
<
|
|
68
|
-
</
|
|
116
|
+
<Surface framed elevation="raised">
|
|
117
|
+
<SurfaceHeader><SurfaceTitle>Workspace</SurfaceTitle></SurfaceHeader>
|
|
118
|
+
<SurfaceBody>…</SurfaceBody>
|
|
119
|
+
</Surface>
|
|
69
120
|
|
|
70
121
|
// asChild: o link assume o estilo e o comportamento do botão.
|
|
71
122
|
<Button asChild><a href="/docs">Abrir documentação</a></Button>
|
|
@@ -128,8 +179,10 @@ componentes.
|
|
|
128
179
|
## O que fica fora das alavancas
|
|
129
180
|
|
|
130
181
|
Alguns detalhes fazem parte da identidade visual do Opus e são iguais em todo projeto: a faixa do
|
|
131
|
-
rodapé do dialog, a
|
|
132
|
-
|
|
182
|
+
rodapé do dialog, a ordem entre canvas, controle, superfície elevada e estados neutros, o
|
|
183
|
+
escurecimento de botões sólidos ao serem pressionados e a seta do tooltip. Eles não são
|
|
184
|
+
configuráveis pela aplicação. O ajuste de aparência muda a distância entre os papéis neutros, mas
|
|
185
|
+
não a ordem entre eles.
|
|
133
186
|
|
|
134
187
|
Se uma necessidade real não cabe nas alavancas (tokens, `className`, partes e `asChild`, props e
|
|
135
188
|
contrato), não crie uma variação local. Proponha a evolução do componente no Opus, com a
|
|
@@ -44,12 +44,13 @@ React substitui a apresentação. `0` e `false` seguem como valores. A regra é
|
|
|
44
44
|
</DetailGroup>
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
##
|
|
47
|
+
## Elevação, moldura e divisórias internas
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
Por padrão, o grupo usa o mesmo fundo de uma superfície elevada. Use `elevation="none"` quando ele
|
|
50
|
+
precisar se integrar ao fundo do hospedeiro. `variant="framed"` adiciona somente a borda externa.
|
|
51
|
+
`dividers` desenha as divisórias internas; na orientação horizontal, também forma a grade tabular
|
|
52
|
+
com fundo sutil e padding próprio na coluna de rótulos. As opções são independentes e podem ser
|
|
53
|
+
combinadas. `orientation` define se a chave fica sobre o valor ou ao lado dele.
|
|
53
54
|
|
|
54
55
|
Na orientação horizontal, todos os valores começam depois da mesma coluna de rótulo, com largura
|
|
55
56
|
padrão de `7rem` em grupos simples e `8.5rem` quando `dividers` está ativo. Quando a superfície
|
|
@@ -73,7 +74,8 @@ exigir mais espaço para os rótulos, ajuste a variável no grupo, por exemplo c
|
|
|
73
74
|
|
|
74
75
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
75
76
|
| ------------- | ---------------------------- | ------------ | --------------------------------------------------------------------------------------------------------- |
|
|
76
|
-
| `variant` | `'plain' \| 'framed'` | `'plain'` | `framed` aplica somente a moldura canônica ao conjunto
|
|
77
|
+
| `variant` | `'plain' \| 'framed'` | `'plain'` | `framed` aplica somente a moldura canônica ao conjunto. |
|
|
78
|
+
| `elevation` | `'none' \| 'raised'` | `'raised'` | `raised` usa o fundo de superfície elevada; `none` herda o fundo do hospedeiro. |
|
|
77
79
|
| `dividers` | `boolean` | `false` | Linhas finas entre os campos; na orientação horizontal, aplica fundo sutil e padding próprio aos rótulos. |
|
|
78
80
|
| `columns` | `1 \| 2 \| 3 \| 4 \| 'auto'` | `1` | Número fixo de colunas ou distribuição automática por largura mínima. |
|
|
79
81
|
| `orientation` | `'vertical' \| 'horizontal'` | `'vertical'` | Chave sobre o valor ou ao lado dele em cada campo. |
|
|
@@ -29,9 +29,11 @@ distinta da página.
|
|
|
29
29
|
<DialogHeader>
|
|
30
30
|
<DialogTitle>Criar workspace</DialogTitle>
|
|
31
31
|
</DialogHeader>
|
|
32
|
-
<DialogBody
|
|
33
|
-
<
|
|
34
|
-
|
|
32
|
+
<DialogBody>
|
|
33
|
+
<div className="space-y-2">
|
|
34
|
+
<Label htmlFor="workspace-name">Nome</Label>
|
|
35
|
+
<Input id="workspace-name" placeholder="Ex.: Empresa X" />
|
|
36
|
+
</div>
|
|
35
37
|
</DialogBody>
|
|
36
38
|
<DialogFooter>
|
|
37
39
|
<ButtonGroup mode="spaced">
|
|
@@ -46,6 +48,9 @@ distinta da página.
|
|
|
46
48
|
```
|
|
47
49
|
|
|
48
50
|
O corpo cresce até o limite da janela e passa a rolar; cabeçalho e rodapé permanecem visíveis.
|
|
51
|
+
Seus filhos diretos recebem o ritmo estrutural de `1.5rem`. Um grupo compacto, uma grade ou uma
|
|
52
|
+
linha declara a própria relação em um wrapper filho; `flush` fica reservado ao conteúdo que
|
|
53
|
+
controla todo o inset.
|
|
49
54
|
O backdrop escurece a página sem aplicar desfoque.
|
|
50
55
|
O fechamento do cabeçalho usa uma ação circular neutra e sutil. `closeSize` escolhe entre `xs` e
|
|
51
56
|
`sm`; o padrão é `sm`.
|
|
@@ -104,8 +109,10 @@ compartilham a anatomia, e um fluxo que troca de superfície não muda de aparê
|
|
|
104
109
|
|
|
105
110
|
O cabeçalho reconhece quatro slots — `DialogNavigation`, `DialogMedia`, `DialogTitle` e
|
|
106
111
|
`DialogActions` — e posiciona cada um: a navegação abre a linha, o título ocupa a folga, as ações
|
|
107
|
-
vão para o extremo oposto e o botão de fechar entra depois delas.
|
|
108
|
-
|
|
112
|
+
vão para o extremo oposto e o botão de fechar entra depois delas. A navegação fica a `0.5rem` do
|
|
113
|
+
título, ou da mídia que o antecede, para se ler junto dele; as ações mantêm a distância maior da
|
|
114
|
+
família. Um nó que não seja um desses slots interrompe a renderização com um erro; contexto e
|
|
115
|
+
conteúdo pertencem ao `DialogBody`.
|
|
109
116
|
|
|
110
117
|
Use `DialogActions` para uma ação da tela que precisa ficar à vista sem competir com o rodapé, como
|
|
111
118
|
abrir um assistente ou alternar um modo de visualização. Use `DialogNavigation` para o retorno de um
|
|
@@ -131,7 +138,9 @@ fluxo modal encadeado, em que a superfície permanece aberta e troca de etapa.
|
|
|
131
138
|
</DialogActions>
|
|
132
139
|
</DialogHeader>
|
|
133
140
|
<DialogBody>
|
|
134
|
-
<p className="text-sm text-muted-foreground">
|
|
141
|
+
<p className="text-sm text-muted-foreground">
|
|
142
|
+
Detalhe do evento selecionado.
|
|
143
|
+
</p>
|
|
135
144
|
</DialogBody>
|
|
136
145
|
</DialogContent>
|
|
137
146
|
</Dialog>
|
|
@@ -147,9 +156,9 @@ decidir aparece no começo do corpo, como texto ou `Alert`.
|
|
|
147
156
|
## Identificar a tarefa com um ícone
|
|
148
157
|
|
|
149
158
|
Use `DialogMedia` quando um ícone ajuda a reconhecer a tarefa antes da leitura do título. No modo
|
|
150
|
-
padrão, ele
|
|
151
|
-
|
|
152
|
-
|
|
159
|
+
padrão, ele apenas reserva e alinha o espaço antes do título. Componha [`IconTile`](/ui/icon-tile)
|
|
160
|
+
explicitamente quando o ícone precisar de moldura; passe o glifo diretamente quando não precisar.
|
|
161
|
+
O mesmo contrato vale no `mode="alert"`: a mídia não ganha tamanho, fundo ou borda automaticamente.
|
|
153
162
|
|
|
154
163
|
```tsx preview
|
|
155
164
|
render(
|
|
@@ -161,13 +170,17 @@ render(
|
|
|
161
170
|
<DialogContent>
|
|
162
171
|
<DialogHeader>
|
|
163
172
|
<DialogMedia>
|
|
164
|
-
<
|
|
173
|
+
<IconTile size="sm">
|
|
174
|
+
<Share2 />
|
|
175
|
+
</IconTile>
|
|
165
176
|
</DialogMedia>
|
|
166
177
|
<DialogTitle>Compartilhar contrato</DialogTitle>
|
|
167
178
|
</DialogHeader>
|
|
168
|
-
<DialogBody
|
|
169
|
-
<
|
|
170
|
-
|
|
179
|
+
<DialogBody>
|
|
180
|
+
<div className="space-y-2">
|
|
181
|
+
<Label htmlFor="share-email">E-mail</Label>
|
|
182
|
+
<Input id="share-email" placeholder="nome@empresa.com.br" />
|
|
183
|
+
</div>
|
|
171
184
|
</DialogBody>
|
|
172
185
|
<DialogFooter>
|
|
173
186
|
<ButtonGroup mode="spaced">
|
|
@@ -185,8 +198,10 @@ render(
|
|
|
185
198
|
</DialogTrigger>
|
|
186
199
|
<DialogContent>
|
|
187
200
|
<DialogHeader>
|
|
188
|
-
<DialogMedia
|
|
189
|
-
<
|
|
201
|
+
<DialogMedia>
|
|
202
|
+
<IconTile size="lg" context="danger">
|
|
203
|
+
<ShieldOff />
|
|
204
|
+
</IconTile>
|
|
190
205
|
</DialogMedia>
|
|
191
206
|
<DialogTitle>Revogar acesso de Marina?</DialogTitle>
|
|
192
207
|
</DialogHeader>
|
|
@@ -211,7 +226,8 @@ render(
|
|
|
211
226
|
);
|
|
212
227
|
```
|
|
213
228
|
|
|
214
|
-
Na API imperativa, a opção `media`
|
|
229
|
+
Na API imperativa, a opção `media` preserva o nó recebido. Passe um `IconTile` quando quiser
|
|
230
|
+
moldura.
|
|
215
231
|
|
|
216
232
|
## Pedir uma resposta pela API imperativa
|
|
217
233
|
|
|
@@ -245,7 +261,11 @@ function Demo() {
|
|
|
245
261
|
const accepted = await dialog.confirm({
|
|
246
262
|
title: "Excluir rascunho?",
|
|
247
263
|
body: "O rascunho e os comentários dele serão removidos.",
|
|
248
|
-
media:
|
|
264
|
+
media: (
|
|
265
|
+
<IconTile context="danger">
|
|
266
|
+
<Trash2 />
|
|
267
|
+
</IconTile>
|
|
268
|
+
),
|
|
249
269
|
action: "Excluir",
|
|
250
270
|
context: "danger",
|
|
251
271
|
});
|
|
@@ -443,42 +463,43 @@ botão. O texto informa o efeito real, como `Excluir`, `Revogar acesso` ou `Arqu
|
|
|
443
463
|
|
|
444
464
|
## Propriedades de DialogContent
|
|
445
465
|
|
|
446
|
-
| Propriedade | Tipo
|
|
447
|
-
| ----------------- |
|
|
448
|
-
| `showCloseButton` | `boolean`
|
|
449
|
-
| `closeDisabled` | `boolean`
|
|
450
|
-
| `closeSize` | `"xs" \| "sm"`
|
|
451
|
-
| `layout` | `'continuous' \| 'sectioned'` | `'sectioned'` | Anatomia da superfície inteira; os slots leem esse valor e não o recebem. Ignorado em `mode="alert"`.
|
|
452
|
-
| `className` | `string`
|
|
453
|
-
| `children` | `ReactNode`
|
|
466
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
467
|
+
| ----------------- | ----------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
468
|
+
| `showCloseButton` | `boolean` | `true` | No modo padrão, inclui a ação de fechamento no cabeçalho; o modo de alerta exige uma resposta identificável. |
|
|
469
|
+
| `closeDisabled` | `boolean` | `false` | Mantém o botão de fechar visível e desabilitado e impede que Esc e o clique externo fechem a superfície. Handlers como `onEscapeKeyDown` e `onPointerDownOutside` continuam sendo chamados antes do bloqueio. |
|
|
470
|
+
| `closeSize` | `"xs" \| "sm"` | `"sm"` | Define o tamanho da ação circular de fechar. |
|
|
471
|
+
| `layout` | `'continuous' \| 'sectioned'` | `'sectioned'` | Anatomia da superfície inteira; os slots leem esse valor e não o recebem. Ignorado em `mode="alert"`. |
|
|
472
|
+
| `className` | `string` | | Ajusta a superfície. A largura máxima é `32rem` no modo padrão e `20rem` no alerta; amplie o alerta com `max-w-lg` quando o rodapé tiver três ações. |
|
|
473
|
+
| `children` | `ReactNode` | | Cabeçalho, corpo, rodapé ou conteúdo próprio. |
|
|
454
474
|
|
|
455
475
|
## Propriedades de DialogHeader
|
|
456
476
|
|
|
457
|
-
| Propriedade | Tipo | Padrão | Descrição
|
|
458
|
-
| ----------- | ----------- | ------ |
|
|
459
|
-
| `className` | `string` | | Ajusta a faixa superior sobre o recuo do layout.
|
|
477
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
478
|
+
| ----------- | ----------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
479
|
+
| `className` | `string` | | Ajusta a faixa superior sobre o recuo do layout. |
|
|
460
480
|
| `children` | `ReactNode` | | Somente `DialogNavigation`, `DialogMedia`, `DialogTitle` e `DialogActions`, no máximo um de cada; o fechamento padrão entra depois deles. |
|
|
461
481
|
|
|
462
482
|
## Propriedades de DialogNavigation
|
|
463
483
|
|
|
464
|
-
| Propriedade | Tipo | Padrão | Descrição
|
|
465
|
-
| ----------- | ----------- | ------ |
|
|
466
|
-
| `className` | `string` | | Ajusta a região introdutória da linha.
|
|
467
|
-
| `children` | `ReactNode` | | Retorno de um fluxo modal encadeado, antes do título.
|
|
484
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
485
|
+
| ----------- | ----------- | ------ | ----------------------------------------------------- |
|
|
486
|
+
| `className` | `string` | | Ajusta a região introdutória da linha. |
|
|
487
|
+
| `children` | `ReactNode` | | Retorno de um fluxo modal encadeado, antes do título. |
|
|
468
488
|
|
|
469
489
|
## Propriedades de DialogActions
|
|
470
490
|
|
|
471
|
-
| Propriedade | Tipo | Padrão | Descrição
|
|
472
|
-
| ----------- | ----------- | ------ |
|
|
473
|
-
| `className` | `string` | | Ajusta o agrupamento das ações.
|
|
474
|
-
| `children` | `ReactNode` | | Ações da tela no cabeçalho, antes do botão de fechar.
|
|
491
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
492
|
+
| ----------- | ----------- | ------ | ----------------------------------------------------- |
|
|
493
|
+
| `className` | `string` | | Ajusta o agrupamento das ações. |
|
|
494
|
+
| `children` | `ReactNode` | | Ações da tela no cabeçalho, antes do botão de fechar. |
|
|
475
495
|
|
|
476
496
|
## Propriedades de DialogBody
|
|
477
497
|
|
|
478
|
-
| Propriedade | Tipo | Padrão
|
|
479
|
-
| ----------- | ----------- |
|
|
480
|
-
| `
|
|
481
|
-
| `
|
|
498
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
499
|
+
| ----------- | ----------- | ------- | ---------------------------------------------------------------------- |
|
|
500
|
+
| `flush` | `boolean` | `false` | Remove o inset para conteúdo que controla o próprio recuo. |
|
|
501
|
+
| `className` | `string` | | Ajusta o corpo rolável do modo padrão ou o conteúdo próprio do alerta. |
|
|
502
|
+
| `children` | `ReactNode` | | Conteúdo principal da tarefa. |
|
|
482
503
|
|
|
483
504
|
## Propriedades de DialogFooter
|
|
484
505
|
|
|
@@ -489,25 +510,18 @@ botão. O texto informa o efeito real, como `Excluir`, `Revogar acesso` ou `Arqu
|
|
|
489
510
|
|
|
490
511
|
## Propriedades de DialogTitle
|
|
491
512
|
|
|
492
|
-
| Propriedade | Tipo
|
|
493
|
-
| ----------- |
|
|
494
|
-
| `level` | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | `h2` da primitiva | Hierarquia do documento. O tamanho vem do `layout`, nunca do nível.
|
|
495
|
-
| `className` | `string`
|
|
496
|
-
| `children` | `ReactNode`
|
|
513
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
514
|
+
| ----------- | ---------------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
515
|
+
| `level` | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | `h2` da primitiva | Hierarquia do documento. O tamanho vem do `layout`, nunca do nível. |
|
|
516
|
+
| `className` | `string` | | Ajusta o título. No modo padrão, ele trunca quando não cabe na linha; no alerta, fica centralizado e pode ocupar mais de uma linha. |
|
|
517
|
+
| `children` | `ReactNode` | | Nome da tarefa ou do conteúdo modal. |
|
|
497
518
|
|
|
498
519
|
## Propriedades de DialogMedia
|
|
499
520
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
|
504
|
-
| ----------- | ----------------------------------------------------------- | --------- | -------------------------------------------------- |
|
|
505
|
-
| `size` | `'xs' \| 'sm' \| 'default' \| 'lg'` | `sm` | Escala da moldura; no alerta vale a moldura maior. |
|
|
506
|
-
| `context` | `UiContext` | `neutral` | Cor semântica da moldura. |
|
|
507
|
-
| `variant` | `'subtle' \| 'outline'` | `subtle` | Tratamento visual da moldura. |
|
|
508
|
-
| `className` | `string` | | Ajustes pontuais da moldura. |
|
|
509
|
-
| `children` | `ReactNode` | | Ícone que reforça o contexto da resposta. |
|
|
510
|
-
| `asChild` | `boolean` | `false` | Cede o elemento para uma marca com visual próprio — um orbe, um logotipo — que ocupa o slot sem ganhar a moldura por cima. |
|
|
521
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
522
|
+
| ----------- | ----------- | ------ | ----------------------------------------------------------------------- |
|
|
523
|
+
| `className` | `string` | | Ajusta o alinhamento do slot. |
|
|
524
|
+
| `children` | `ReactNode` | | `IconTile`, marca, imagem ou glifo. O slot não acrescenta apresentação. |
|
|
511
525
|
|
|
512
526
|
## Propriedades de DialogClose
|
|
513
527
|
|
|
@@ -540,7 +554,7 @@ imperativa.
|
|
|
540
554
|
| -------- | ----------- | ------ | ------------------------------------------------ |
|
|
541
555
|
| `title` | `ReactNode` | | Nomeia o aviso que exige reconhecimento. |
|
|
542
556
|
| `body` | `ReactNode` | | Apresenta contexto relevante no início do corpo. |
|
|
543
|
-
| `media` | `ReactNode` | | Exibe
|
|
557
|
+
| `media` | `ReactNode` | | Exibe o nó recebido em `DialogMedia`. |
|
|
544
558
|
| `action` | `string` | `'OK'` | Define o rótulo de reconhecimento. |
|
|
545
559
|
|
|
546
560
|
## Opções de dialog.confirm
|
|
@@ -549,7 +563,7 @@ imperativa.
|
|
|
549
563
|
| --------- | ----------------------- | ------------- | ------------------------------------------------------------------- |
|
|
550
564
|
| `title` | `ReactNode` | | Nomeia a decisão. |
|
|
551
565
|
| `body` | `ReactNode` | | Apresenta a consequência ou outro contexto necessário para decidir. |
|
|
552
|
-
| `media` | `ReactNode` | | Exibe
|
|
566
|
+
| `media` | `ReactNode` | | Exibe o nó recebido em `DialogMedia`. |
|
|
553
567
|
| `action` | `string` | `'Confirmar'` | Define o rótulo do resultado afirmativo. |
|
|
554
568
|
| `cancel` | `string` | `'Cancelar'` | Define o rótulo da resposta negativa. |
|
|
555
569
|
| `context` | `'primary' \| 'danger'` | `'primary'` | Define o contexto da ação afirmativa. |
|
|
@@ -560,7 +574,7 @@ imperativa.
|
|
|
560
574
|
| -------------- | ----------------------- | ------------- | ------------------------------------------------------------------ |
|
|
561
575
|
| `title` | `ReactNode` | | Nomeia a informação solicitada. |
|
|
562
576
|
| `body` | `ReactNode` | | Explica como a informação será usada quando isso mudar a resposta. |
|
|
563
|
-
| `media` | `ReactNode` | | Exibe
|
|
577
|
+
| `media` | `ReactNode` | | Exibe o nó recebido em `DialogMedia`. |
|
|
564
578
|
| `action` | `string` | `'Confirmar'` | Define o rótulo do resultado afirmativo. |
|
|
565
579
|
| `cancel` | `string` | `'Cancelar'` | Define o rótulo da resposta negativa. |
|
|
566
580
|
| `context` | `'primary' \| 'danger'` | `'primary'` | Define o contexto da ação afirmativa. |
|
|
@@ -573,7 +587,7 @@ imperativa.
|
|
|
573
587
|
| --------- | ------------------------- | ------ | ------------------------------------------------ |
|
|
574
588
|
| `title` | `ReactNode` | | Nomeia a escolha. |
|
|
575
589
|
| `body` | `ReactNode` | | Apresenta o contexto necessário antes das ações. |
|
|
576
|
-
| `media` | `ReactNode` | | Exibe
|
|
590
|
+
| `media` | `ReactNode` | | Exibe o nó recebido em `DialogMedia`. |
|
|
577
591
|
| `actions` | `readonly DialogChoice[]` | | Declara os resultados disponíveis. |
|
|
578
592
|
|
|
579
593
|
## Propriedades de DialogChoice
|
|
@@ -586,3 +600,34 @@ imperativa.
|
|
|
586
600
|
| `context` | `ButtonContext` | Última ação: `primary`; demais: `neutral` | Define o significado semântico. |
|
|
587
601
|
| `variant` | `ButtonVariant` | Última ação: `solid`; demais: `outline` | Define o tratamento visual. |
|
|
588
602
|
| `disabled` | `boolean` | `false` | Impede a escolha desta ação. |
|
|
603
|
+
|
|
604
|
+
## Intro separada do chrome
|
|
605
|
+
|
|
606
|
+
Quando o cabeçalho contém apenas navegação, ações globais e o fechamento, coloque o título do
|
|
607
|
+
conteúdo no primeiro bloco de `DialogBody`. `DialogIntro` exige um `DialogTitle` e aceita um
|
|
608
|
+
`DialogIntroActions`; o body continua responsável pelo espaço antes, entre e depois dos blocos.
|
|
609
|
+
|
|
610
|
+
```tsx
|
|
611
|
+
<Dialog>
|
|
612
|
+
<DialogContent>
|
|
613
|
+
<DialogHeader>
|
|
614
|
+
<DialogActions>
|
|
615
|
+
<Button variant="ghost">Ajuda</Button>
|
|
616
|
+
</DialogActions>
|
|
617
|
+
</DialogHeader>
|
|
618
|
+
<DialogBody>
|
|
619
|
+
<DialogIntro>
|
|
620
|
+
<DialogTitle>Editar evento</DialogTitle>
|
|
621
|
+
<DialogIntroActions>
|
|
622
|
+
<Button variant="outline">Revisar</Button>
|
|
623
|
+
</DialogIntroActions>
|
|
624
|
+
</DialogIntro>
|
|
625
|
+
<form>…</form>
|
|
626
|
+
</DialogBody>
|
|
627
|
+
<DialogFooter>…</DialogFooter>
|
|
628
|
+
</DialogContent>
|
|
629
|
+
</Dialog>
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
No formato compacto, mantenha `DialogTitle` e `DialogActions` no próprio `DialogHeader`. Para
|
|
633
|
+
comparar as duas formas em cada `layout`, abra [Composições](/ui/compositions).
|
|
@@ -18,9 +18,11 @@ cantos, em qualquer valor de `side`.
|
|
|
18
18
|
<DrawerHeader>
|
|
19
19
|
<DrawerTitle>ABC-1D23</DrawerTitle>
|
|
20
20
|
</DrawerHeader>
|
|
21
|
-
<DrawerBody className="
|
|
22
|
-
<
|
|
23
|
-
|
|
21
|
+
<DrawerBody className="text-sm text-muted-foreground">
|
|
22
|
+
<div className="space-y-1">
|
|
23
|
+
<p>Corolla XEi 2022 · 38.400 km</p>
|
|
24
|
+
<p>Última revisão em 12 de maio.</p>
|
|
25
|
+
</div>
|
|
24
26
|
</DrawerBody>
|
|
25
27
|
</DrawerContent>
|
|
26
28
|
</Drawer>
|
|
@@ -42,9 +44,11 @@ neutra e sutil; `closeSize` escolhe entre `xs` e `sm`, com `sm` como padrão.
|
|
|
42
44
|
<DrawerHeader>
|
|
43
45
|
<DrawerTitle>Editar veículo</DrawerTitle>
|
|
44
46
|
</DrawerHeader>
|
|
45
|
-
<DrawerBody
|
|
46
|
-
<
|
|
47
|
-
|
|
47
|
+
<DrawerBody>
|
|
48
|
+
<div className="space-y-2">
|
|
49
|
+
<Label htmlFor="vehicle-owner">Responsável</Label>
|
|
50
|
+
<Input id="vehicle-owner" defaultValue="Marina Alves" />
|
|
51
|
+
</div>
|
|
48
52
|
</DrawerBody>
|
|
49
53
|
<DrawerFooter>
|
|
50
54
|
<ButtonGroup mode="spaced">
|
|
@@ -98,13 +102,14 @@ rodapé produz uma linha só. A tela não escreve `border-b` nem `border-t`.
|
|
|
98
102
|
|
|
99
103
|
O cabeçalho reconhece quatro slots — `DrawerNavigation`, `DrawerMedia`, `DrawerTitle` e
|
|
100
104
|
`DrawerActions` — e posiciona cada um: a navegação abre a linha, a mídia vem antes do título, o
|
|
101
|
-
título ocupa a folga, as ações vão para o extremo oposto e o botão de fechar entra depois delas.
|
|
102
|
-
|
|
103
|
-
|
|
105
|
+
título ocupa a folga, as ações vão para o extremo oposto e o botão de fechar entra depois delas. A
|
|
106
|
+
navegação fica a `0.5rem` do título, ou da mídia que o antecede, para se ler junto dele; as ações
|
|
107
|
+
mantêm a distância maior da família. Um nó que não seja um desses slots interrompe a renderização
|
|
108
|
+
com um erro; contexto e conteúdo pertencem ao `DrawerBody`.
|
|
104
109
|
|
|
105
|
-
`DrawerMedia`
|
|
106
|
-
|
|
107
|
-
em que o painel permanece aberto e troca de etapa.
|
|
110
|
+
`DrawerMedia` reserva o espaço que identifica o tipo do recurso aberto, sem acrescentar moldura.
|
|
111
|
+
Componha [`IconTile`](/ui/icon-tile) quando ela ajudar na hierarquia. `DrawerNavigation` carrega o
|
|
112
|
+
retorno de um fluxo encadeado, em que o painel permanece aberto e troca de etapa.
|
|
108
113
|
|
|
109
114
|
```tsx preview
|
|
110
115
|
<Drawer>
|
|
@@ -118,8 +123,10 @@ em que o painel permanece aberto e troca de etapa.
|
|
|
118
123
|
<ArrowLeft />
|
|
119
124
|
</Button>
|
|
120
125
|
</DrawerNavigation>
|
|
121
|
-
<DrawerMedia
|
|
122
|
-
<
|
|
126
|
+
<DrawerMedia>
|
|
127
|
+
<IconTile size="sm" context="primary">
|
|
128
|
+
<CarFront />
|
|
129
|
+
</IconTile>
|
|
123
130
|
</DrawerMedia>
|
|
124
131
|
<DrawerTitle>ABC-1D23</DrawerTitle>
|
|
125
132
|
<DrawerActions>
|
|
@@ -210,13 +217,10 @@ de continuar, use [`Dialog mode="alert"`](/ui/dialog), que não fecha pelo cliqu
|
|
|
210
217
|
|
|
211
218
|
## Propriedades de DrawerMedia
|
|
212
219
|
|
|
213
|
-
| Propriedade | Tipo
|
|
214
|
-
| ----------- |
|
|
215
|
-
| `
|
|
216
|
-
| `
|
|
217
|
-
| `variant` | `'subtle' \| 'outline'` | `'subtle'` | Usa preenchimento tonal ou acrescenta borda. |
|
|
218
|
-
| `className` | `string` | | Ajusta a moldura sem substituir a escala. |
|
|
219
|
-
| `asChild` | `boolean` | `false` | Cede o elemento para uma marca com visual próprio — um orbe, um logotipo — que ocupa o slot sem ganhar a moldura por cima. |
|
|
220
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
221
|
+
| ----------- | ----------- | ------ | ----------------------------------------------------------------------- |
|
|
222
|
+
| `className` | `string` | | Ajusta o alinhamento do slot. |
|
|
223
|
+
| `children` | `ReactNode` | | `IconTile`, marca, imagem ou glifo. O slot não acrescenta apresentação. |
|
|
220
224
|
|
|
221
225
|
## Propriedades de DrawerNavigation
|
|
222
226
|
|
|
@@ -244,7 +248,14 @@ de continuar, use [`Dialog mode="alert"`](/ui/dialog), que não fecha pelo cliqu
|
|
|
244
248
|
|
|
245
249
|
`DrawerBody` aceita os atributos de `HTMLDivElement` e ocupa a região flexível e rolável entre
|
|
246
250
|
`DrawerHeader` e `DrawerFooter`. O cabeçalho nomeia o painel; contexto relevante entra no começo
|
|
247
|
-
do corpo como texto ou `Alert`.
|
|
251
|
+
do corpo como texto ou `Alert`. Seus filhos diretos recebem o ritmo estrutural; use `flush` quando
|
|
252
|
+
o conteúdo controlar o próprio inset e um wrapper filho para relações internas mais compactas.
|
|
253
|
+
|
|
254
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
255
|
+
| ----------- | ----------- | ------- | ---------------------------------------------------------- |
|
|
256
|
+
| `flush` | `boolean` | `false` | Remove o inset para conteúdo que controla o próprio recuo. |
|
|
257
|
+
| `className` | `string` | | Ajusta ocupação, overflow, alinhamento ou tipografia. |
|
|
258
|
+
| `children` | `ReactNode` | | Blocos principais do painel. |
|
|
248
259
|
|
|
249
260
|
## Propriedades de DrawerFooter
|
|
250
261
|
|
|
@@ -252,3 +263,38 @@ do corpo como texto ou `Alert`.
|
|
|
252
263
|
| ----------- | ----------- | ------ | ------------------------------------------------------------- |
|
|
253
264
|
| `className` | `string` | | Ajusta a faixa do rodapé, inclusive a distribuição das ações. |
|
|
254
265
|
| `children` | `ReactNode` | | Ações persistentes, normalmente dentro de um `ButtonGroup`. |
|
|
266
|
+
|
|
267
|
+
## Intro separada do chrome
|
|
268
|
+
|
|
269
|
+
Quando o cabeçalho contém apenas o recolhimento, ações globais e o fechamento, use `DrawerIntro`
|
|
270
|
+
como primeiro bloco de `DrawerBody`. Ele exige um `DrawerTitle` e aceita `DrawerIntroActions`.
|
|
271
|
+
Assim o título acompanha o conteúdo rolável enquanto o chrome permanece estável.
|
|
272
|
+
|
|
273
|
+
```tsx
|
|
274
|
+
<Drawer>
|
|
275
|
+
<DrawerContent showCloseButton={false}>
|
|
276
|
+
<DrawerHeader>
|
|
277
|
+
<DrawerNavigation>
|
|
278
|
+
<DrawerClose asChild>
|
|
279
|
+
<Button>Recolher</Button>
|
|
280
|
+
</DrawerClose>
|
|
281
|
+
</DrawerNavigation>
|
|
282
|
+
<DrawerActions>
|
|
283
|
+
<Button variant="ghost">Conversa</Button>
|
|
284
|
+
</DrawerActions>
|
|
285
|
+
</DrawerHeader>
|
|
286
|
+
<DrawerBody>
|
|
287
|
+
<DrawerIntro>
|
|
288
|
+
<DrawerTitle>Editar evento</DrawerTitle>
|
|
289
|
+
<DrawerIntroActions>
|
|
290
|
+
<Button variant="outline">Revisar</Button>
|
|
291
|
+
</DrawerIntroActions>
|
|
292
|
+
</DrawerIntro>
|
|
293
|
+
<form>…</form>
|
|
294
|
+
</DrawerBody>
|
|
295
|
+
</DrawerContent>
|
|
296
|
+
</Drawer>
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
No formato compacto, mantenha `DrawerTitle` e `DrawerActions` no próprio `DrawerHeader`. Para
|
|
300
|
+
comparar as duas formas em cada `layout`, abra [Composições](/ui/compositions).
|