@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
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
## Digitar ou escolher uma data
|
|
2
|
+
|
|
3
|
+
Use `DateInput` para preencher uma data civil, como uma entrega ou um feriado. O campo
|
|
4
|
+
exibe `DD/MM/AAAA` e abre o calendário em português ao clicar em qualquer parte do controle.
|
|
5
|
+
O clique mantém o foco na digitação. O ícone é decorativo e não adiciona uma parada de Tab;
|
|
6
|
+
o atalho `Alt` + seta para baixo leva o foco para o calendário.
|
|
7
|
+
|
|
8
|
+
```tsx preview col md
|
|
9
|
+
function Demo() {
|
|
10
|
+
const [date, setDate] = useState("2026-11-02")
|
|
11
|
+
return (
|
|
12
|
+
<div className="grid gap-2">
|
|
13
|
+
<Label htmlFor="delivery-date">Data de entrega</Label>
|
|
14
|
+
<DateInput id="delivery-date" value={date} onValueChange={setDate} />
|
|
15
|
+
</div>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
render(<Demo />)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
A máscara insere as barras durante a digitação: basta informar `02112026`. Também é possível
|
|
22
|
+
digitar `02/11/2026`, colar `2026-11-02` ou escolher o dia no
|
|
23
|
+
calendário. Uma data válida é emitida como `2026-11-02`; apagar o campo emite `''`. O componente
|
|
24
|
+
mantém o dia civil, sem transformá-lo em um instante UTC.
|
|
25
|
+
|
|
26
|
+
Texto incompleto ou uma data impossível permanecem no campo com a máscara, sem conversão para ISO.
|
|
27
|
+
Valide o valor antes de persistir: o componente não troca `31/02/2026` por um dia de março nem
|
|
28
|
+
preserva silenciosamente a data anterior. No `ActionForm`, o schema do contrato mantém essa
|
|
29
|
+
responsabilidade.
|
|
30
|
+
|
|
31
|
+
## Formulário declarativo
|
|
32
|
+
|
|
33
|
+
Declare `widget: 'date'` no campo do contrato e use um schema de data civil. O
|
|
34
|
+
[`ActionForm`](/ui/action-form) compõe o `DateInput` com rótulo, hint, erro e foco de validação.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
const fields = { date: { label: "Data", widget: "date" as const } }
|
|
38
|
+
const input = z.object({ date: z.string().date("Informe uma data válida.") })
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Teclado e estados
|
|
42
|
+
|
|
43
|
+
Com foco no campo, `Alt` + seta para baixo abre o calendário e leva o foco até ele. As setas navegam pelos dias;
|
|
44
|
+
selecionar uma data fecha o calendário e devolve o foco ao campo. `Escape` fecha o calendário
|
|
45
|
+
sem fechar o diálogo que o contém. É possível substituir trechos selecionados e apagar com
|
|
46
|
+
`Backspace` ou `Delete`, sem ficar preso às barras da máscara. `disabled` e `readOnly` impedem
|
|
47
|
+
a abertura pelo campo e pelo atalho.
|
|
48
|
+
Associe `Label.htmlFor` ao `id` e use `aria-describedby` para ajuda ou erro.
|
|
49
|
+
|
|
50
|
+
Para manter um mês inteiro visível, use [`Calendar`](/ui/calendar). Para um campo com estado
|
|
51
|
+
interno, forneça `defaultValue`; `value` e `onValueChange` tornam o componente controlado.
|
|
52
|
+
|
|
53
|
+
## Propriedades de DateInput
|
|
54
|
+
|
|
55
|
+
| Propriedade | Tipo | Padrão | Efeito |
|
|
56
|
+
| --- | --- | --- | --- |
|
|
57
|
+
| `value` | `string` | — | Valor controlado: ISO quando válido, texto durante digitação inválida ou incompleta. |
|
|
58
|
+
| `defaultValue` | `string` | `''` | Valor inicial no modo não controlado; restaurado no reset do formulário nativo. |
|
|
59
|
+
| `onValueChange` | `(value: string) => void` | — | Recebe a data civil, o texto em edição ou `''`. |
|
|
60
|
+
| `name` | `string` | — | Envia o valor por um campo oculto no formulário nativo, sem converter para a apresentação brasileira. |
|
|
61
|
+
| `placeholder` | `string` | `DD/MM/AAAA` | Exemplo de formato no campo vazio. |
|
|
62
|
+
| `disabled`, `readOnly` | `boolean` | `false` | Impedem edição e abertura do calendário. |
|
|
63
|
+
| `id`, `ref`, `form`, `onBlur`, `aria-*` | Atributos do input | — | Identificação, foco, vínculo com formulário e descrição acessível do campo visível. |
|
|
64
|
+
| `className` | `string` | — | Classes da moldura do campo, seguindo o Input com adorno. |
|
|
65
|
+
|
|
66
|
+
O componente não aceita `type`, `onChange`, `icon`, `trailing`, `min`, `max` ou `step`.
|
|
67
|
+
O contrato define os limites de negócio; `onValueChange` substitui o evento de alteração nativo.
|
|
@@ -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
|
|
56
|
-
`sm`; o padrão é `
|
|
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
|
|
63
|
+
## Regiões com divisores automáticos
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
|
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
|
|
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
|
|
150
|
-
linha mínima de `
|
|
151
|
-
`size="icon
|
|
152
|
-
|
|
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>
|
|
123
|
+
<DialogDescription>
|
|
124
|
+
Escolha onde a pasta e suas subpastas aparecem.
|
|
125
|
+
</DialogDescription>
|
|
163
126
|
</DialogHeader>
|
|
164
127
|
```
|
|
165
128
|
|
|
@@ -469,20 +432,22 @@ reservado à orientação textual breve. Os itens quebram em várias linhas quan
|
|
|
469
432
|
```tsx
|
|
470
433
|
<Dialog defaultOpen>
|
|
471
434
|
<DialogContent>
|
|
472
|
-
<DialogHeader
|
|
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>
|
|
473
443
|
<DialogBody>
|
|
474
|
-
<DialogIntro>
|
|
475
|
-
<DialogTitle>Manual de atendimento</DialogTitle>
|
|
476
|
-
<DialogDescription>Orientações para a equipe.</DialogDescription>
|
|
477
|
-
<DialogMeta><Badge>Publicado</Badge><span>Por Ana</span></DialogMeta>
|
|
478
|
-
</DialogIntro>
|
|
479
444
|
<p>Conteúdo do manual.</p>
|
|
480
445
|
</DialogBody>
|
|
481
446
|
</DialogContent>
|
|
482
447
|
</Dialog>
|
|
483
448
|
```
|
|
484
449
|
|
|
485
|
-
A composição aceita um único `DialogMeta` e exige um `DialogTitle`.
|
|
450
|
+
A composição aceita um único `DialogMeta` e exige um `DialogTitle`. Coloque-o em `DialogHeader`. Não coloque o slot solto no corpo.
|
|
486
451
|
|
|
487
452
|
O modo `alert` conserva sua composição especializada e não recebe `DialogMeta`.
|
|
488
453
|
|
|
@@ -506,19 +471,19 @@ O modo `alert` conserva sua composição especializada e não recebe `DialogMeta
|
|
|
506
471
|
|
|
507
472
|
## Propriedades de DialogContent
|
|
508
473
|
|
|
509
|
-
| Propriedade | Tipo
|
|
510
|
-
| ----------------- |
|
|
511
|
-
| `showCloseButton` | `boolean`
|
|
512
|
-
| `closeDisabled` | `boolean`
|
|
513
|
-
| `closeSize` | `"xs" \| "sm"`
|
|
514
|
-
| `
|
|
515
|
-
| `
|
|
516
|
-
| `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. |
|
|
517
481
|
|
|
518
482
|
## Propriedades de DialogHeader
|
|
519
483
|
|
|
520
484
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
521
485
|
| ----------- | ----------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
486
|
+
| `tabs` | `ReactNode` | | `TabsList` sob o título, controlado por um `Tabs` ancestral. Não disponível no modo alert. |
|
|
522
487
|
| `className` | `string` | | Ajusta a faixa superior sobre o recuo do layout. |
|
|
523
488
|
| `children` | `ReactNode` | | Somente `DialogNavigation`, `DialogMedia`, `DialogTitle` e `DialogActions`, no máximo um de cada; o fechamento padrão entra depois deles. |
|
|
524
489
|
|
|
@@ -644,63 +609,30 @@ imperativa.
|
|
|
644
609
|
| `variant` | `ButtonVariant` | Última ação: `solid`; demais: `outline` | Define o tratamento visual. |
|
|
645
610
|
| `disabled` | `boolean` | `false` | Impede a escolha desta ação. |
|
|
646
611
|
|
|
647
|
-
## Intro separada do chrome
|
|
648
|
-
|
|
649
|
-
Quando o cabeçalho contém apenas navegação, ações globais e o fechamento, coloque o título do
|
|
650
|
-
conteúdo no primeiro bloco de `DialogBody`. `DialogIntro` exige um `DialogTitle` e aceita um
|
|
651
|
-
`DialogIntroActions`; o body continua responsável pelo espaço antes, entre e depois dos blocos.
|
|
652
|
-
|
|
653
|
-
```tsx
|
|
654
|
-
<Dialog>
|
|
655
|
-
<DialogContent>
|
|
656
|
-
<DialogHeader>
|
|
657
|
-
<DialogActions>
|
|
658
|
-
<Button variant="ghost">Ajuda</Button>
|
|
659
|
-
</DialogActions>
|
|
660
|
-
</DialogHeader>
|
|
661
|
-
<DialogBody>
|
|
662
|
-
<DialogIntro>
|
|
663
|
-
<DialogTitle>Editar evento</DialogTitle>
|
|
664
|
-
<DialogIntroActions>
|
|
665
|
-
<Button variant="outline">Revisar</Button>
|
|
666
|
-
</DialogIntroActions>
|
|
667
|
-
</DialogIntro>
|
|
668
|
-
<form>…</form>
|
|
669
|
-
</DialogBody>
|
|
670
|
-
<DialogFooter>…</DialogFooter>
|
|
671
|
-
</DialogContent>
|
|
672
|
-
</Dialog>
|
|
673
|
-
```
|
|
674
|
-
|
|
675
|
-
No formato compacto, mantenha `DialogTitle` e `DialogActions` no próprio `DialogHeader`. Para
|
|
676
|
-
comparar as duas formas em cada `layout`, abra [Composições](/ui/compositions).
|
|
677
|
-
|
|
678
612
|
## Propriedades de DialogDescription
|
|
679
613
|
|
|
680
|
-
| Propriedade | Tipo
|
|
681
|
-
|
|
|
682
|
-
| `children`
|
|
683
|
-
| `id`
|
|
684
|
-
| `className` | `string`
|
|
685
|
-
| `…props`
|
|
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. |
|
|
686
620
|
|
|
687
621
|
## Espaçamento do corpo
|
|
688
622
|
|
|
689
623
|
O body separa os blocos diretos por `1rem`. Dialog e Drawer são superfícies delimitadas:
|
|
690
624
|
o conteúdo mantém `1rem` até a borda inferior, mesmo sem uma propriedade `framed`.
|
|
691
|
-
|
|
692
|
-
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.
|
|
693
626
|
Use `flush` quando o conteúdo controlar seus próprios recuos.
|
|
694
627
|
|
|
695
|
-
|
|
696
|
-
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.
|
|
697
629
|
|
|
698
630
|
## Propriedades de DialogMeta
|
|
699
631
|
|
|
700
|
-
| Propriedade | Tipo
|
|
701
|
-
|
|
|
702
|
-
| `children`
|
|
703
|
-
| `className` | `string`
|
|
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. |
|
|
704
636
|
|
|
705
637
|
Aceita atributos nativos de `div`. O intervalo superior é de 0,75rem; os itens têm
|
|
706
638
|
0,75rem entre colunas e 0,5rem entre linhas. O componente não insere separadores nem
|
|
@@ -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 `
|
|
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
|
|
69
|
+
## Regiões com divisores automáticos
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
|
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
|
|
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
|
|
148
|
-
linha mínima de `
|
|
149
|
-
`size="icon
|
|
150
|
-
|
|
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>
|
|
134
|
+
<DrawerDescription>
|
|
135
|
+
Escolha onde a pasta e suas subpastas aparecem.
|
|
136
|
+
</DrawerDescription>
|
|
161
137
|
</DrawerHeader>
|
|
162
138
|
```
|
|
163
139
|
|
|
@@ -199,20 +175,22 @@ reservado à orientação textual breve. Os itens quebram em várias linhas quan
|
|
|
199
175
|
```tsx
|
|
200
176
|
<Drawer defaultOpen>
|
|
201
177
|
<DrawerContent>
|
|
202
|
-
<DrawerHeader
|
|
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>
|
|
203
186
|
<DrawerBody>
|
|
204
|
-
<DrawerIntro>
|
|
205
|
-
<DrawerTitle>Manual de atendimento</DrawerTitle>
|
|
206
|
-
<DrawerDescription>Orientações para a equipe.</DrawerDescription>
|
|
207
|
-
<DrawerMeta><Badge>Publicado</Badge><span>Por Ana</span></DrawerMeta>
|
|
208
|
-
</DrawerIntro>
|
|
209
187
|
<p>Conteúdo do manual.</p>
|
|
210
188
|
</DrawerBody>
|
|
211
189
|
</DrawerContent>
|
|
212
190
|
</Drawer>
|
|
213
191
|
```
|
|
214
192
|
|
|
215
|
-
A composição aceita um único `DrawerMeta` e exige um `DrawerTitle`.
|
|
193
|
+
A composição aceita um único `DrawerMeta` e exige um `DrawerTitle`. Coloque-o em `DrawerHeader`. Não coloque o slot solto no corpo.
|
|
216
194
|
|
|
217
195
|
## Propriedades de Drawer
|
|
218
196
|
|
|
@@ -239,20 +217,20 @@ A composição aceita um único `DrawerMeta` e exige um `DrawerTitle`. Na forma
|
|
|
239
217
|
|
|
240
218
|
## Propriedades de DrawerContent
|
|
241
219
|
|
|
242
|
-
| Propriedade | Tipo | Padrão
|
|
243
|
-
| ----------------- | ---------------------------------------- |
|
|
244
|
-
| `side` | `'top' \| 'right' \| 'bottom' \| 'left'` | `'right'`
|
|
245
|
-
| `
|
|
246
|
-
| `
|
|
247
|
-
| `
|
|
248
|
-
| `
|
|
249
|
-
| `
|
|
250
|
-
| `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é. |
|
|
251
228
|
|
|
252
229
|
## Propriedades de DrawerHeader
|
|
253
230
|
|
|
254
231
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
255
232
|
| ----------- | ----------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
233
|
+
| `tabs` | `ReactNode` | | `TabsList` sob o título, controlado por um `Tabs` ancestral. |
|
|
256
234
|
| `className` | `string` | | Ajusta a faixa superior sobre o recuo do layout. |
|
|
257
235
|
| `children` | `ReactNode` | | Somente `DrawerNavigation`, `DrawerMedia`, `DrawerTitle` e `DrawerActions`, no máximo um de cada; o fechamento padrão entra depois deles. |
|
|
258
236
|
|
|
@@ -305,67 +283,30 @@ o conteúdo controlar o próprio inset e um wrapper filho para relações intern
|
|
|
305
283
|
| `className` | `string` | | Ajusta a faixa do rodapé, inclusive a distribuição das ações. |
|
|
306
284
|
| `children` | `ReactNode` | | Ações persistentes, normalmente dentro de um `ButtonGroup`. |
|
|
307
285
|
|
|
308
|
-
## Intro separada do chrome
|
|
309
|
-
|
|
310
|
-
Quando o cabeçalho contém apenas o recolhimento, ações globais e o fechamento, use `DrawerIntro`
|
|
311
|
-
como primeiro bloco de `DrawerBody`. Ele exige um `DrawerTitle` e aceita `DrawerIntroActions`.
|
|
312
|
-
Assim o título acompanha o conteúdo rolável enquanto o chrome permanece estável.
|
|
313
|
-
|
|
314
|
-
```tsx
|
|
315
|
-
<Drawer>
|
|
316
|
-
<DrawerContent showCloseButton={false}>
|
|
317
|
-
<DrawerHeader>
|
|
318
|
-
<DrawerNavigation>
|
|
319
|
-
<DrawerClose asChild>
|
|
320
|
-
<Button>Recolher</Button>
|
|
321
|
-
</DrawerClose>
|
|
322
|
-
</DrawerNavigation>
|
|
323
|
-
<DrawerActions>
|
|
324
|
-
<Button variant="ghost">Conversa</Button>
|
|
325
|
-
</DrawerActions>
|
|
326
|
-
</DrawerHeader>
|
|
327
|
-
<DrawerBody>
|
|
328
|
-
<DrawerIntro>
|
|
329
|
-
<DrawerTitle>Editar evento</DrawerTitle>
|
|
330
|
-
<DrawerIntroActions>
|
|
331
|
-
<Button variant="outline">Revisar</Button>
|
|
332
|
-
</DrawerIntroActions>
|
|
333
|
-
</DrawerIntro>
|
|
334
|
-
<form>…</form>
|
|
335
|
-
</DrawerBody>
|
|
336
|
-
</DrawerContent>
|
|
337
|
-
</Drawer>
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
No formato compacto, mantenha `DrawerTitle` e `DrawerActions` no próprio `DrawerHeader`. Para
|
|
341
|
-
comparar as duas formas em cada `layout`, abra [Composições](/ui/compositions).
|
|
342
|
-
|
|
343
286
|
## Propriedades de DrawerDescription
|
|
344
287
|
|
|
345
|
-
| Propriedade | Tipo
|
|
346
|
-
|
|
|
347
|
-
| `children`
|
|
348
|
-
| `id`
|
|
349
|
-
| `className` | `string`
|
|
350
|
-
| `…props`
|
|
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. |
|
|
351
294
|
|
|
352
295
|
## Espaçamento do corpo
|
|
353
296
|
|
|
354
297
|
O body separa os blocos diretos por `1rem`. Dialog e Drawer são superfícies delimitadas:
|
|
355
298
|
o conteúdo mantém `1rem` até a borda inferior, mesmo sem uma propriedade `framed`.
|
|
356
|
-
|
|
357
|
-
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.
|
|
358
300
|
Use `flush` quando o conteúdo controlar seus próprios recuos.
|
|
359
301
|
|
|
360
|
-
|
|
361
|
-
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.
|
|
362
303
|
|
|
363
304
|
## Propriedades de DrawerMeta
|
|
364
305
|
|
|
365
|
-
| Propriedade | Tipo
|
|
366
|
-
|
|
|
367
|
-
| `children`
|
|
368
|
-
| `className` | `string`
|
|
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. |
|
|
369
310
|
|
|
370
311
|
Aceita atributos nativos de `div`. O intervalo superior é de 0,75rem; os itens têm
|
|
371
312
|
0,75rem entre colunas e 0,5rem entre linhas. O componente não insere separadores nem
|
|
@@ -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>
|
|
@@ -70,6 +70,9 @@ Associe `htmlFor` no `Label` ao `id` do campo para que o clique no rótulo mova
|
|
|
70
70
|
`type` é repassado ao `<input>` nativo, permitindo que o navegador escolha teclado e validação
|
|
71
71
|
adequados.
|
|
72
72
|
|
|
73
|
+
Para datas com digitação em formato brasileiro e calendário do Opus, use
|
|
74
|
+
[`DateInput`](/ui/date-input).
|
|
75
|
+
|
|
73
76
|
```tsx preview col md
|
|
74
77
|
<Input type="email" placeholder="Ex.: joao@softize.com.br" />
|
|
75
78
|
<Input type="password" placeholder="Token de serviço" />
|