@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.
Files changed (59) hide show
  1. package/CHANGELOG.md +137 -0
  2. package/bin/lib/check.mjs +178 -94
  3. package/bin/lib/copy.mjs +2970 -1801
  4. package/docs/adr/0043-neutral-surfaces-and-interactions-use-opaque-role-tokens.md +52 -0
  5. package/docs/adr/0044-neutral-appearance-derives-from-bounded-axes-per-mode.md +27 -2
  6. package/docs/adr/0045-surface-replaces-content-and-card.md +3 -0
  7. package/docs/adr/0060-surface-composition-separates-chrome-and-intro.md +142 -0
  8. package/docs/adr/0062-listas-contidas-e-texto-flexivel.md +68 -0
  9. package/docs/adr/0063-metadados-das-superficies.md +44 -0
  10. package/docs/adr/0064-action-list-com-itens-e-fontes-externas.md +47 -0
  11. package/docs/adr/0065-presentation-composes-settings-sections.md +295 -0
  12. package/docs/adr/README.md +8 -0
  13. package/package.json +1 -1
  14. package/registry/skills/build-opus-ui/SKILL.md +21 -19
  15. package/registry/skills/build-opus-ui/references/evaluations.md +21 -10
  16. package/registry/skills/build-opus-ui/references/ui-patterns.md +33 -28
  17. package/src/core/presentation.ts +938 -32
  18. package/src/core/types.ts +2 -1
  19. package/src/ui/components/patterns/form.tsx +2 -0
  20. package/src/ui/components/patterns/grouped-list.ts +2 -2
  21. package/src/ui/components/patterns/list.tsx +588 -365
  22. package/src/ui/components/patterns/page-heading-context.tsx +12 -5
  23. package/src/ui/components/patterns/page.tsx +238 -181
  24. package/src/ui/components/patterns/presentation-fields.tsx +246 -0
  25. package/src/ui/components/patterns/presentation-sections.tsx +494 -0
  26. package/src/ui/components/patterns/presentation.tsx +1142 -229
  27. package/src/ui/components/patterns/structural-header.tsx +47 -34
  28. package/src/ui/components/patterns/surface-anatomy.ts +27 -217
  29. package/src/ui/components/patterns/surface.tsx +55 -37
  30. package/src/ui/components/patterns/trigger.tsx +10 -2
  31. package/src/ui/components/primitives/close-button.tsx +11 -3
  32. package/src/ui/components/primitives/command.tsx +2 -8
  33. package/src/ui/components/primitives/detail.tsx +1 -1
  34. package/src/ui/components/primitives/dialog.tsx +59 -89
  35. package/src/ui/components/primitives/drawer.tsx +52 -87
  36. package/src/ui/components/primitives/field.tsx +1 -1
  37. package/src/ui/components/primitives/pagination.tsx +3 -2
  38. package/src/ui/components/primitives/table.tsx +3 -3
  39. package/src/ui/components/primitives/tabs.tsx +13 -2
  40. package/src/ui/docs/content/action-form.md +2 -1
  41. package/src/ui/docs/content/action-list.md +146 -73
  42. package/src/ui/docs/content/action-trigger.md +5 -0
  43. package/src/ui/docs/content/button.md +5 -6
  44. package/src/ui/docs/content/command.md +62 -50
  45. package/src/ui/docs/content/compositions.md +129 -459
  46. package/src/ui/docs/content/dialog.md +72 -101
  47. package/src/ui/docs/content/drawer.md +69 -92
  48. package/src/ui/docs/content/field.md +2 -1
  49. package/src/ui/docs/content/page.md +207 -386
  50. package/src/ui/docs/content/presentation.md +371 -23
  51. package/src/ui/docs/content/separator.md +1 -1
  52. package/src/ui/docs/content/surface.md +94 -116
  53. package/src/ui/docs/content/table.md +7 -0
  54. package/src/ui/docs/content/tokens.md +18 -4
  55. package/src/ui/drivers/context.tsx +11 -4
  56. package/src/ui/drivers/react.tsx +27 -7
  57. package/src/ui/meta.ts +5 -5
  58. package/src/ui/react.tsx +38 -8
  59. package/src/ui/theme.css +44 -33
@@ -52,58 +52,19 @@ Seus filhos diretos recebem o ritmo estrutural de `1rem`. Um grupo compacto, uma
52
52
  linha declara a própria relação em um wrapper filho; `flush` fica reservado ao conteúdo que
53
53
  controla todo o inset.
54
54
  O backdrop escurece a página sem aplicar desfoque.
55
- O fechamento do cabeçalho usa uma ação circular neutra e sutil. `closeSize` escolhe entre `xs` e
56
- `sm`; o padrão é `sm`.
55
+ O fechamento do cabeçalho usa uma ação circular neutra e sutil. `closeSize` escolhe entre `xs`,
56
+ `sm` e `default`; o padrão é `xs` (`1,5rem`).
57
57
  O `ButtonGroup` preserva a largura natural das ações por padrão. Use `distribution="equal"`
58
58
  somente para decisões deliberadamente equivalentes. O `DialogFooter` organiza a faixa, mas não
59
59
  decide a distribuição nem a aparência dos botões.
60
60
  `DialogClose` encerra o modal sem exigir estado controlado. Use `open` e `onOpenChange` quando outra
61
61
  parte da interface também precisar controlar a abertura.
62
62
 
63
- ## Regiões separadas ou contínuas
63
+ ## Regiões com divisores automáticos
64
64
 
65
- `layout` declara a anatomia da superfície inteira e fica em `DialogContent`; os slots leem esse
66
- valor e não o recebem. O padrão é `sectioned`: as regiões têm o mesmo recuo, o rodapé ganha uma
67
- faixa sutil e as fronteiras entre regiões vizinhas ganham um divisor. É o modal de tarefa, com
68
- cabeçalho, conteúdo e ações claramente separados.
69
-
70
- Use `layout="continuous"` para uma superfície curta, em que o espaço basta para separar as regiões
71
- e a linha seria um ruído — um aviso de uma frase, uma escolha rápida.
72
-
73
- ```tsx preview
74
- <Dialog>
75
- <DialogTrigger asChild>
76
- <Button variant="outline">Publicar contrato</Button>
77
- </DialogTrigger>
78
- <DialogContent layout="continuous">
79
- <DialogHeader>
80
- <DialogTitle>Publicar contrato</DialogTitle>
81
- </DialogHeader>
82
- <DialogBody>
83
- <p className="text-sm text-muted-foreground">
84
- A versão publicada passa a valer para todos os consumidores.
85
- </p>
86
- </DialogBody>
87
- <DialogFooter>
88
- <ButtonGroup mode="spaced">
89
- <DialogClose asChild>
90
- <Button variant="ghost">Cancelar</Button>
91
- </DialogClose>
92
- <Button>Publicar</Button>
93
- </ButtonGroup>
94
- </DialogFooter>
95
- </DialogContent>
96
- </Dialog>
97
- ```
98
-
99
- Os divisores do modo seccionado são derivados da vizinhança: cada região desenha a linha quando há
100
- uma região do outro lado. Um cabeçalho sem corpo não fecha nada, e um cabeçalho seguido direto de um
101
- rodapé produz uma linha só. A tela não escreve `border-b` nem `border-t`.
102
-
103
- A faixa sutil do rodapé é a mesma no `Dialog` e no [`Drawer`](/ui/drawer): as duas famílias
104
- compartilham a anatomia, e um fluxo que troca de superfície não muda de aparência no meio.
105
-
106
- `mode="alert"` mantém a composição centrada da resposta obrigatória e não usa `layout`.
65
+ Cabeçalho, corpo e rodapé usam recuo de `1rem`. Os divisores dependem das regiões presentes:
66
+ um cabeçalho isolado não desenha linha; seguido diretamente pelo rodapé, produz uma linha só.
67
+ A tela não declara uma variante visual nem reconstrói bordas nos slots.
107
68
 
108
69
  ## Ações e navegação no cabeçalho
109
70
 
@@ -126,13 +87,13 @@ fluxo modal encadeado, em que a superfície permanece aberta e troca de etapa.
126
87
  <DialogContent>
127
88
  <DialogHeader>
128
89
  <DialogNavigation>
129
- <Button variant="ghost" size="icon-sm" aria-label="Voltar para a lista">
90
+ <Button variant="ghost" size="icon" aria-label="Voltar para a lista">
130
91
  <ArrowLeft />
131
92
  </Button>
132
93
  </DialogNavigation>
133
94
  <DialogTitle>Evento 4821</DialogTitle>
134
95
  <DialogActions>
135
- <Button variant="ghost" size="icon-sm" aria-label="Mais ações">
96
+ <Button variant="ghost" size="icon" aria-label="Mais ações">
136
97
  <Ellipsis />
137
98
  </Button>
138
99
  </DialogActions>
@@ -146,10 +107,10 @@ fluxo modal encadeado, em que a superfície permanece aberta e troca de etapa.
146
107
  </Dialog>
147
108
  ```
148
109
 
149
- O header compartilha a geometria de Page e Surface delimitada: padding de `1rem` e
150
- linha mínima de `2rem`, nos dois layouts. Declare `size="sm"` nos botões textuais e
151
- `size="icon-sm"` nos de ícone (`2rem`), incluindo o retorno. `CloseButton` já usa
152
- `icon-sm` por padrão. Conteúdo maior pode expandir a linha; rodapés preservam sua escala.
110
+ O header compartilha a geometria de Drawer e Surface delimitada: padding de `1rem` e
111
+ linha mínima de `2,25rem`, na anatomia única. Declare `size="default"` nos botões textuais e
112
+ `size="icon"` nos de ícone (`2,25rem`), incluindo o retorno. O fechamento nativo do modal
113
+ também usa essa escala por padrão. Conteúdo maior pode expandir a linha; rodapés preservam sua escala.
153
114
 
154
115
  O cabeçalho aceita `DialogDescription` como subheading opcional para orientar sobre a finalidade.
155
116
  Omita quando repetir o título. Condições, regras de negócio e consequências necessárias à decisão
@@ -159,7 +120,9 @@ pular o texto compromete a decisão, não sua extensão.
159
120
  ```tsx
160
121
  <DialogHeader>
161
122
  <DialogTitle>Organizar pasta</DialogTitle>
162
- <DialogDescription>Escolha onde a pasta e suas subpastas aparecem.</DialogDescription>
123
+ <DialogDescription>
124
+ Escolha onde a pasta e suas subpastas aparecem.
125
+ </DialogDescription>
163
126
  </DialogHeader>
164
127
  ```
165
128
 
@@ -460,6 +423,34 @@ botão. O texto informa o efeito real, como `Excluir`, `Revogar acesso` ou `Arqu
460
423
  age onde a pessoa está. O modo `alert` cobre a camada até a resposta.
461
424
  - `DialogHost` apresenta uma solicitação por vez para que cada resposta tenha um alvo inequívoco.
462
425
 
426
+ ## Metadados junto à identidade
427
+
428
+ Use `DialogMeta` para badges, autoria e datas relacionados ao registro. A faixa fica
429
+ abaixo da linha de título e ações, com espaço próprio; `DialogDescription` continua
430
+ reservado à orientação textual breve. Os itens quebram em várias linhas quando necessário.
431
+
432
+ ```tsx
433
+ <Dialog defaultOpen>
434
+ <DialogContent>
435
+ <DialogHeader>
436
+ <DialogTitle>Manual de atendimento</DialogTitle>
437
+ <DialogDescription>Orientações para a equipe.</DialogDescription>
438
+ <DialogMeta>
439
+ <Badge>Publicado</Badge>
440
+ <span>Por Ana</span>
441
+ </DialogMeta>
442
+ </DialogHeader>
443
+ <DialogBody>
444
+ <p>Conteúdo do manual.</p>
445
+ </DialogBody>
446
+ </DialogContent>
447
+ </Dialog>
448
+ ```
449
+
450
+ A composição aceita um único `DialogMeta` e exige um `DialogTitle`. Coloque-o em `DialogHeader`. Não coloque o slot solto no corpo.
451
+
452
+ O modo `alert` conserva sua composição especializada e não recebe `DialogMeta`.
453
+
463
454
  ## Propriedades de Dialog
464
455
 
465
456
  | Propriedade | Tipo | Padrão | Descrição |
@@ -480,19 +471,19 @@ botão. O texto informa o efeito real, como `Excluir`, `Revogar acesso` ou `Arqu
480
471
 
481
472
  ## Propriedades de DialogContent
482
473
 
483
- | Propriedade | Tipo | Padrão | Descrição |
484
- | ----------------- | ----------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
485
- | `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. |
486
- | `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. |
487
- | `closeSize` | `"xs" \| "sm"` | `"sm"` | Define o tamanho da ação circular de fechar. |
488
- | `layout` | `'continuous' \| 'sectioned'` | `'sectioned'` | Anatomia da superfície inteira; os slots leem esse valor e não o recebem. Ignorado em `mode="alert"`. |
489
- | `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. |
490
- | `children` | `ReactNode` | | Cabeçalho, corpo, rodapé ou conteúdo próprio. |
474
+ | Propriedade | Tipo | Padrão | Descrição |
475
+ | ----------------- | --------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
476
+ | `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. |
477
+ | `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. |
478
+ | `closeSize` | `"xs" \| "sm" \| "default"` | `"xs"` | Define o tamanho da ação circular de fechar. |
479
+ | `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. |
480
+ | `children` | `ReactNode` | | Cabeçalho, corpo, rodapé ou conteúdo próprio. |
491
481
 
492
482
  ## Propriedades de DialogHeader
493
483
 
494
484
  | Propriedade | Tipo | Padrão | Descrição |
495
485
  | ----------- | ----------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
486
+ | `tabs` | `ReactNode` | | `TabsList` sob o título, controlado por um `Tabs` ancestral. Não disponível no modo alert. |
496
487
  | `className` | `string` | | Ajusta a faixa superior sobre o recuo do layout. |
497
488
  | `children` | `ReactNode` | | Somente `DialogNavigation`, `DialogMedia`, `DialogTitle` e `DialogActions`, no máximo um de cada; o fechamento padrão entra depois deles. |
498
489
 
@@ -618,53 +609,33 @@ imperativa.
618
609
  | `variant` | `ButtonVariant` | Última ação: `solid`; demais: `outline` | Define o tratamento visual. |
619
610
  | `disabled` | `boolean` | `false` | Impede a escolha desta ação. |
620
611
 
621
- ## Intro separada do chrome
622
-
623
- Quando o cabeçalho contém apenas navegação, ações globais e o fechamento, coloque o título do
624
- conteúdo no primeiro bloco de `DialogBody`. `DialogIntro` exige um `DialogTitle` e aceita um
625
- `DialogIntroActions`; o body continua responsável pelo espaço antes, entre e depois dos blocos.
626
-
627
- ```tsx
628
- <Dialog>
629
- <DialogContent>
630
- <DialogHeader>
631
- <DialogActions>
632
- <Button variant="ghost">Ajuda</Button>
633
- </DialogActions>
634
- </DialogHeader>
635
- <DialogBody>
636
- <DialogIntro>
637
- <DialogTitle>Editar evento</DialogTitle>
638
- <DialogIntroActions>
639
- <Button variant="outline">Revisar</Button>
640
- </DialogIntroActions>
641
- </DialogIntro>
642
- <form>…</form>
643
- </DialogBody>
644
- <DialogFooter>…</DialogFooter>
645
- </DialogContent>
646
- </Dialog>
647
- ```
648
-
649
- No formato compacto, mantenha `DialogTitle` e `DialogActions` no próprio `DialogHeader`. Para
650
- comparar as duas formas em cada `layout`, abra [Composições](/ui/compositions).
651
-
652
612
  ## Propriedades de DialogDescription
653
613
 
654
- | Propriedade | Tipo | Padrão | Descrição |
655
- | --- | --- | --- | --- |
656
- | `children` | `ReactNode` | | Orientação opcional sob o título em `DialogHeader` ou `DialogIntro`. |
657
- | `id` | `string` | | Identificador para associação acessível explícita. |
658
- | `className` | `string` | | Ajusta a apresentação do parágrafo. |
659
- | `…props` | `ComponentProps<"p">` | | Atributos nativos. |
614
+ | Propriedade | Tipo | Padrão | Descrição |
615
+ | ----------- | --------------------- | ------ | --------------------------------------------------- |
616
+ | `children` | `ReactNode` | | Orientação opcional sob o título em `DialogHeader`. |
617
+ | `id` | `string` | | Identificador para associação acessível explícita. |
618
+ | `className` | `string` | | Ajusta a apresentação do parágrafo. |
619
+ | `…props` | `ComponentProps<"p">` | | Atributos nativos. |
660
620
 
661
621
  ## Espaçamento do corpo
662
622
 
663
623
  O body separa os blocos diretos por `1rem`. Dialog e Drawer são superfícies delimitadas:
664
624
  o conteúdo mantém `1rem` até a borda inferior, mesmo sem uma propriedade `framed`.
665
- Em `sectioned`, o corpo tem `1rem` entre o conteúdo e cada divisória. Em `continuous`,
666
- o cabeçalho fornece o intervalo superior; sem cabeçalho, o próprio corpo abre esse recuo.
625
+ O corpo mantém `1rem` entre o conteúdo e cada divisória.
667
626
  Use `flush` quando o conteúdo controlar seus próprios recuos.
668
627
 
669
- Na intro, `DialogTitle` usa a mesma escala de `PageTitle` (`1.875rem`). No header
670
- compacto, o título conserva a escala de `1.125rem`. O nível semântico não altera essas medidas.
628
+ `DialogTitle` usa `1,125rem`, como PageTitle. O nível semântico não altera a escala visual.
629
+
630
+ ## Propriedades de DialogMeta
631
+
632
+ | Propriedade | Tipo | Descrição |
633
+ | ----------- | ----------- | ------------------------------------------------------- |
634
+ | `children` | `ReactNode` | Badges, datas, autoria ou outros metadados do registro. |
635
+ | `className` | `string` | Ajusta a faixa de metadados. |
636
+
637
+ Aceita atributos nativos de `div`. O intervalo superior é de 0,75rem; os itens têm
638
+ 0,75rem entre colunas e 0,5rem entre linhas. O componente não insere separadores nem
639
+ carrega dados. Omitir o slot não reserva espaço. Metadados não substituem orientações
640
+ ou condições necessárias à decisão e não são anunciados como descrição do modal.
641
+ `DialogMeta` não se aplica a `mode="alert"`; informações necessárias à resposta ficam no corpo do alerta.
@@ -33,7 +33,7 @@ cantos, em qualquer valor de `side`.
33
33
  `side` aceita `top`, `right`, `bottom` e `left`. `DrawerFooter` mantém as ações no rodapé e
34
34
  `DrawerClose` fecha o painel sem exigir controle manual de estado. O corpo preserva o mesmo
35
35
  alinhamento horizontal do cabeçalho e do rodapé. O fechamento do cabeçalho usa uma ação circular
36
- neutra e sutil; `closeSize` escolhe entre `xs` e `sm`, com `sm` como padrão.
36
+ neutra e sutil; `closeSize` escolhe entre `xs`, `sm` e `default`, com `xs` como padrão.
37
37
 
38
38
  ```tsx preview
39
39
  <Drawer>
@@ -66,37 +66,11 @@ O rodapé usa a mesma faixa sutil do [`Dialog`](/ui/dialog). As duas famílias c
66
66
  anatomia, então um fluxo que começa em um modal e continua em um painel não muda de aparência no
67
67
  meio.
68
68
 
69
- ## Regiões separadas ou contínuas
69
+ ## Regiões com divisores automáticos
70
70
 
71
- `layout` declara a anatomia da superfície inteira e fica em `DrawerContent`; os slots leem esse
72
- valor e não o recebem. O padrão é `sectioned`: recuo igual nas três regiões, faixa no rodapé e
73
- divisor entre as regiões vizinhas. É o painel de trabalho, em que o corpo rola sob um cabeçalho e um
74
- rodapé fixos.
75
-
76
- Use `layout="continuous"` quando o painel apresentar um único bloco de leitura e a linha virar
77
- ruído.
78
-
79
- ```tsx preview
80
- <Drawer>
81
- <DrawerTrigger asChild>
82
- <Button variant="outline">Ver resumo</Button>
83
- </DrawerTrigger>
84
- <DrawerContent layout="continuous">
85
- <DrawerHeader>
86
- <DrawerTitle>Resumo da revisão</DrawerTitle>
87
- </DrawerHeader>
88
- <DrawerBody>
89
- <p className="text-sm text-muted-foreground">
90
- Concluída em 2 horas, sem pendências registradas.
91
- </p>
92
- </DrawerBody>
93
- </DrawerContent>
94
- </Drawer>
95
- ```
96
-
97
- Os divisores do modo seccionado são derivados da vizinhança: cada região desenha a linha quando há
98
- uma região do outro lado. Um cabeçalho sem corpo não fecha nada, e um cabeçalho seguido direto de um
99
- rodapé produz uma linha só. A tela não escreve `border-b` nem `border-t`.
71
+ Cabeçalho, corpo e rodapé usam recuo de `1rem`. Os divisores dependem das regiões presentes:
72
+ um cabeçalho isolado não desenha linha; seguido diretamente pelo rodapé, produz uma linha só.
73
+ A tela não declara uma variante visual nem reconstrói bordas nos slots.
100
74
 
101
75
  ## Mídia, ações e navegação no cabeçalho
102
76
 
@@ -119,7 +93,7 @@ retorno de um fluxo encadeado, em que o painel permanece aberto e troca de etapa
119
93
  <DrawerContent side="right">
120
94
  <DrawerHeader>
121
95
  <DrawerNavigation>
122
- <Button variant="ghost" size="icon-sm" aria-label="Voltar para a lista">
96
+ <Button variant="ghost" size="icon" aria-label="Voltar para a lista">
123
97
  <ArrowLeft />
124
98
  </Button>
125
99
  </DrawerNavigation>
@@ -130,7 +104,7 @@ retorno de um fluxo encadeado, em que o painel permanece aberto e troca de etapa
130
104
  </DrawerMedia>
131
105
  <DrawerTitle>ABC-1D23</DrawerTitle>
132
106
  <DrawerActions>
133
- <Button variant="ghost" size="icon-sm" aria-label="Mais ações">
107
+ <Button variant="ghost" size="icon" aria-label="Mais ações">
134
108
  <Ellipsis />
135
109
  </Button>
136
110
  </DrawerActions>
@@ -144,10 +118,10 @@ retorno de um fluxo encadeado, em que o painel permanece aberto e troca de etapa
144
118
  </Drawer>
145
119
  ```
146
120
 
147
- O header compartilha a geometria de Page e Surface delimitada: padding de `1rem` e
148
- linha mínima de `2rem`, nos dois layouts. Declare `size="sm"` nos botões textuais e
149
- `size="icon-sm"` nos de ícone (`2rem`), incluindo o retorno. `CloseButton` já usa
150
- `icon-sm` por padrão. Conteúdo maior pode expandir a linha; rodapés preservam sua escala.
121
+ O header compartilha a geometria de Dialog e Surface delimitada: padding de `1rem` e
122
+ linha mínima de `2,25rem`, na anatomia única. Declare `size="default"` nos botões textuais e
123
+ `size="icon"` nos de ícone (`2,25rem`), incluindo o retorno. O fechamento nativo do modal
124
+ também usa essa escala por padrão. Conteúdo maior pode expandir a linha; rodapés preservam sua escala.
151
125
 
152
126
  O cabeçalho aceita `DrawerDescription` como subheading opcional para orientar sobre a finalidade.
153
127
  Omita quando repetir o título. Condições, regras de negócio e consequências necessárias à decisão
@@ -157,7 +131,9 @@ pular o texto compromete a decisão, não sua extensão.
157
131
  ```tsx
158
132
  <DrawerHeader>
159
133
  <DrawerTitle>Organizar pasta</DrawerTitle>
160
- <DrawerDescription>Escolha onde a pasta e suas subpastas aparecem.</DrawerDescription>
134
+ <DrawerDescription>
135
+ Escolha onde a pasta e suas subpastas aparecem.
136
+ </DrawerDescription>
161
137
  </DrawerHeader>
162
138
  ```
163
139
 
@@ -190,6 +166,32 @@ de continuar, use [`Dialog mode="alert"`](/ui/dialog), que não fecha pelo cliqu
190
166
  - O botão de fechar tem o nome acessível `Fechar`. Botões só com ícone no cabeçalho precisam de
191
167
  `aria-label`.
192
168
 
169
+ ## Metadados junto à identidade
170
+
171
+ Use `DrawerMeta` para badges, autoria e datas relacionados ao registro. A faixa fica
172
+ abaixo da linha de título e ações, com espaço próprio; `DrawerDescription` continua
173
+ reservado à orientação textual breve. Os itens quebram em várias linhas quando necessário.
174
+
175
+ ```tsx
176
+ <Drawer defaultOpen>
177
+ <DrawerContent>
178
+ <DrawerHeader>
179
+ <DrawerTitle>Manual de atendimento</DrawerTitle>
180
+ <DrawerDescription>Orientações para a equipe.</DrawerDescription>
181
+ <DrawerMeta>
182
+ <Badge>Publicado</Badge>
183
+ <span>Por Ana</span>
184
+ </DrawerMeta>
185
+ </DrawerHeader>
186
+ <DrawerBody>
187
+ <p>Conteúdo do manual.</p>
188
+ </DrawerBody>
189
+ </DrawerContent>
190
+ </Drawer>
191
+ ```
192
+
193
+ A composição aceita um único `DrawerMeta` e exige um `DrawerTitle`. Coloque-o em `DrawerHeader`. Não coloque o slot solto no corpo.
194
+
193
195
  ## Propriedades de Drawer
194
196
 
195
197
  | Propriedade | Tipo | Padrão | Descrição |
@@ -215,20 +217,20 @@ de continuar, use [`Dialog mode="alert"`](/ui/dialog), que não fecha pelo cliqu
215
217
 
216
218
  ## Propriedades de DrawerContent
217
219
 
218
- | Propriedade | Tipo | Padrão | Descrição |
219
- | ----------------- | ---------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------- |
220
- | `side` | `'top' \| 'right' \| 'bottom' \| 'left'` | `'right'` | Borda de onde o painel aparece. |
221
- | `layout` | `'continuous' \| 'sectioned'` | `'sectioned'` | Anatomia da superfície inteira; os slots leem esse valor e não o recebem. |
222
- | `showCloseButton` | `boolean` | `true` | Inclui o botão de fechar no cabeçalho. Sem ele, Esc e o overlay continuam fechando o painel. |
223
- | `closeDisabled` | `boolean` | `false` | Mantém o botão de fechar visível e desabilitado e impede que Esc e o clique no overlay fechem o painel. |
224
- | `closeSize` | `"xs" \| "sm"` | `"sm"` | Define o tamanho da ação circular de fechar. |
225
- | `className` | `string` | | Ajusta o painel, como a largura. |
226
- | `children` | `ReactNode` | | Cabeçalho, corpo e rodapé. |
220
+ | Propriedade | Tipo | Padrão | Descrição |
221
+ | ----------------- | ---------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------- |
222
+ | `side` | `'top' \| 'right' \| 'bottom' \| 'left'` | `'right'` | Borda de onde o painel aparece. |
223
+ | `showCloseButton` | `boolean` | `true` | Inclui o botão de fechar no cabeçalho. Sem ele, Esc e o overlay continuam fechando o painel. |
224
+ | `closeDisabled` | `boolean` | `false` | Mantém o botão de fechar visível e desabilitado e impede que Esc e o clique no overlay fechem o painel. |
225
+ | `closeSize` | `"xs" \| "sm" \| "default"` | `"xs"` | Define o tamanho da ação circular de fechar. |
226
+ | `className` | `string` | | Ajusta o painel, como a largura. |
227
+ | `children` | `ReactNode` | | Cabeçalho, corpo e rodapé. |
227
228
 
228
229
  ## Propriedades de DrawerHeader
229
230
 
230
231
  | Propriedade | Tipo | Padrão | Descrição |
231
232
  | ----------- | ----------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
233
+ | `tabs` | `ReactNode` | | `TabsList` sob o título, controlado por um `Tabs` ancestral. |
232
234
  | `className` | `string` | | Ajusta a faixa superior sobre o recuo do layout. |
233
235
  | `children` | `ReactNode` | | Somente `DrawerNavigation`, `DrawerMedia`, `DrawerTitle` e `DrawerActions`, no máximo um de cada; o fechamento padrão entra depois deles. |
234
236
 
@@ -281,57 +283,32 @@ o conteúdo controlar o próprio inset e um wrapper filho para relações intern
281
283
  | `className` | `string` | | Ajusta a faixa do rodapé, inclusive a distribuição das ações. |
282
284
  | `children` | `ReactNode` | | Ações persistentes, normalmente dentro de um `ButtonGroup`. |
283
285
 
284
- ## Intro separada do chrome
285
-
286
- Quando o cabeçalho contém apenas o recolhimento, ações globais e o fechamento, use `DrawerIntro`
287
- como primeiro bloco de `DrawerBody`. Ele exige um `DrawerTitle` e aceita `DrawerIntroActions`.
288
- Assim o título acompanha o conteúdo rolável enquanto o chrome permanece estável.
289
-
290
- ```tsx
291
- <Drawer>
292
- <DrawerContent showCloseButton={false}>
293
- <DrawerHeader>
294
- <DrawerNavigation>
295
- <DrawerClose asChild>
296
- <Button>Recolher</Button>
297
- </DrawerClose>
298
- </DrawerNavigation>
299
- <DrawerActions>
300
- <Button variant="ghost">Conversa</Button>
301
- </DrawerActions>
302
- </DrawerHeader>
303
- <DrawerBody>
304
- <DrawerIntro>
305
- <DrawerTitle>Editar evento</DrawerTitle>
306
- <DrawerIntroActions>
307
- <Button variant="outline">Revisar</Button>
308
- </DrawerIntroActions>
309
- </DrawerIntro>
310
- <form>…</form>
311
- </DrawerBody>
312
- </DrawerContent>
313
- </Drawer>
314
- ```
315
-
316
- No formato compacto, mantenha `DrawerTitle` e `DrawerActions` no próprio `DrawerHeader`. Para
317
- comparar as duas formas em cada `layout`, abra [Composições](/ui/compositions).
318
-
319
286
  ## Propriedades de DrawerDescription
320
287
 
321
- | Propriedade | Tipo | Padrão | Descrição |
322
- | --- | --- | --- | --- |
323
- | `children` | `ReactNode` | | Orientação opcional sob o título em `DrawerHeader` ou `DrawerIntro`. |
324
- | `id` | `string` | | Identificador para associação acessível explícita. |
325
- | `className` | `string` | | Ajusta a apresentação do parágrafo. |
326
- | `…props` | `ComponentProps<"p">` | | Atributos nativos. |
288
+ | Propriedade | Tipo | Padrão | Descrição |
289
+ | ----------- | --------------------- | ------ | --------------------------------------------------- |
290
+ | `children` | `ReactNode` | | Orientação opcional sob o título em `DrawerHeader`. |
291
+ | `id` | `string` | | Identificador para associação acessível explícita. |
292
+ | `className` | `string` | | Ajusta a apresentação do parágrafo. |
293
+ | `…props` | `ComponentProps<"p">` | | Atributos nativos. |
327
294
 
328
295
  ## Espaçamento do corpo
329
296
 
330
297
  O body separa os blocos diretos por `1rem`. Dialog e Drawer são superfícies delimitadas:
331
298
  o conteúdo mantém `1rem` até a borda inferior, mesmo sem uma propriedade `framed`.
332
- Em `sectioned`, o corpo tem `1rem` entre o conteúdo e cada divisória. Em `continuous`,
333
- o cabeçalho fornece o intervalo superior; sem cabeçalho, o próprio corpo abre esse recuo.
299
+ O corpo mantém `1rem` entre o conteúdo e cada divisória.
334
300
  Use `flush` quando o conteúdo controlar seus próprios recuos.
335
301
 
336
- Na intro, `DrawerTitle` usa a mesma escala de `PageTitle` (`1.875rem`). No header
337
- compacto, o título conserva a escala de `1.125rem`. O nível semântico não altera essas medidas.
302
+ `DrawerTitle` usa `1,125rem`, como PageTitle. O nível semântico não altera a escala visual.
303
+
304
+ ## Propriedades de DrawerMeta
305
+
306
+ | Propriedade | Tipo | Descrição |
307
+ | ----------- | ----------- | ------------------------------------------------------- |
308
+ | `children` | `ReactNode` | Badges, datas, autoria ou outros metadados do registro. |
309
+ | `className` | `string` | Ajusta a faixa de metadados. |
310
+
311
+ Aceita atributos nativos de `div`. O intervalo superior é de 0,75rem; os itens têm
312
+ 0,75rem entre colunas e 0,5rem entre linhas. O componente não insere separadores nem
313
+ carrega dados. Omitir o slot não reserva espaço. Metadados não substituem orientações
314
+ ou condições necessárias à decisão e não são anunciados como descrição do modal.
@@ -5,7 +5,8 @@ montado à mão. Quando o formulário executa uma action, prefira [`ActionForm`]
5
5
  monta os mesmos campos a partir do contrato. Na orientação vertical, `FieldLabel` e o controle ficam
6
6
  empilhados. A ajuda fica junto ao rótulo, com [`LabelHelp`](/ui/action-form), o mesmo ícone que o
7
7
  `ActionForm` usa para `FieldSpec.help`. Use `FieldDescription` somente quando a frase precisar
8
- ficar visível o tempo todo abaixo do controle.
8
+ ficar visível o tempo todo abaixo do controle. Essa orientação usa `text-xs` (`0,75rem`),
9
+ enquanto o rótulo mantém `text-sm`.
9
10
 
10
11
  ```tsx preview col md
11
12
  <Field>