@softize/opus 14.0.0 → 15.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +63 -0
- package/bin/cli.mjs +2 -0
- package/bin/lib/check.mjs +33 -5
- package/bin/lib/cli-shared.mjs +30 -1
- package/bin/lib/copy.mjs +3 -0
- package/bin/lib/db.mjs +2 -0
- package/docs/adr/0004-page-content-state-is-composed.md +39 -5
- package/docs/adr/0005-structural-surfaces-share-an-explicit-anatomy.md +9 -3
- package/docs/adr/0009-page-title-does-not-carry-a-counter.md +57 -0
- package/docs/adr/0010-page-header-owns-page-chrome.md +73 -0
- package/docs/data-layer.md +9 -0
- package/package.json +1 -1
- package/registry/skills/build-opus-ui/SKILL.md +3 -2
- package/registry/skills/build-opus-ui/references/ui-patterns.md +17 -6
- package/src/ui/components/patterns/list.tsx +41 -26
- package/src/ui/components/patterns/page-state.tsx +48 -6
- package/src/ui/components/patterns/page.tsx +221 -55
- package/src/ui/components/patterns/state-surface.tsx +137 -23
- package/src/ui/components/patterns/surface-header.tsx +102 -17
- package/src/ui/components/patterns/trigger.tsx +7 -6
- package/src/ui/components/primitives/button-group.tsx +34 -8
- package/src/ui/components/primitives/control.ts +12 -3
- package/src/ui/docs/content/action-list-dialog.md +1 -1
- package/src/ui/docs/content/action-list.md +34 -3
- package/src/ui/docs/content/action-trigger.md +4 -3
- package/src/ui/docs/content/alert.md +16 -4
- package/src/ui/docs/content/button.md +20 -5
- package/src/ui/docs/content/content.md +3 -3
- package/src/ui/docs/content/data-state.md +4 -4
- package/src/ui/docs/content/page.md +159 -44
- package/src/ui/meta.ts +6 -6
- package/src/ui/react.tsx +8 -2
|
@@ -37,8 +37,9 @@ confirm: {
|
|
|
37
37
|
|
|
38
38
|
## Ação somente com ícone
|
|
39
39
|
|
|
40
|
-
Com `icon`, o botão exibe somente o ícone no quadrado `icon-
|
|
41
|
-
dentro de uma linha ou card) e usa `label`, ou `action.label`, no tooltip e no nome acessível.
|
|
40
|
+
Com `icon`, o botão exibe somente o ícone no quadrado `icon-xs` da escala (1.5rem, a ação que mora
|
|
41
|
+
dentro de uma linha ou card) e usa `label`, ou `action.label`, no tooltip e no nome acessível. Uma
|
|
42
|
+
composição que peça mais presença, como a barra do `PageHeader`, declara `size="icon-sm"`. O clique
|
|
42
43
|
não aciona o item clicável ao redor. `itemLabel` identifica o registro na mensagem de confirmação.
|
|
43
44
|
|
|
44
45
|
```tsx
|
|
@@ -83,4 +84,4 @@ um atalho, um arrastar, um item de menu.
|
|
|
83
84
|
| `onSuccess` | `(data: TData) => void` | | Pós-sucesso (cache já invalidado pelo action.invalidates). |
|
|
84
85
|
| `icon` | `React.ReactNode` | | Torna o botão icon-only: rótulo no tooltip e no `aria-label`, clique que não vaza para o item. |
|
|
85
86
|
| `itemLabel` | `string` | | Nome do alvo na pergunta (sai entre aspas, em destaque, antes da mensagem do contrato). |
|
|
86
|
-
| `className` | `string` | | Classes do botão. O tamanho vem de `size` (escala única); com `icon
|
|
87
|
+
| `className` | `string` | | Classes do botão. O tamanho vem de `size` (escala única); com `icon`, o default é `icon-xs`. |
|
|
@@ -54,6 +54,11 @@ Quando a mensagem precisa de conteúdo rico, componha os slots da família. `Ale
|
|
|
54
54
|
`AlertDescription` pertencem ao header. As ações ficam no fim lógico da superfície e centralizadas
|
|
55
55
|
verticalmente na mesma linha do conteúdo — a mesma posição usada pelas ações do Toast.
|
|
56
56
|
|
|
57
|
+
Use `ghost` como tratamento padrão para ações dentro do alert: a mensagem já fornece a superfície e
|
|
58
|
+
o botão não precisa desenhar outra moldura. Mantenha texto quando a ação expressa um resultado
|
|
59
|
+
específico. Para tentar novamente, recarregar ou repetir a operação descrita pelo aviso, prefira um
|
|
60
|
+
botão só com ícone, nome acessível e tooltip.
|
|
61
|
+
|
|
57
62
|
```tsx preview col
|
|
58
63
|
<Alert context="danger">
|
|
59
64
|
<AlertMedia>
|
|
@@ -67,9 +72,16 @@ verticalmente na mesma linha do conteúdo — a mesma posição usada pelas aç
|
|
|
67
72
|
</AlertDescription>
|
|
68
73
|
</AlertHeader>
|
|
69
74
|
<AlertActions>
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
75
|
+
<TooltipProvider>
|
|
76
|
+
<Tooltip>
|
|
77
|
+
<TooltipTrigger asChild>
|
|
78
|
+
<Button variant="ghost" size="icon" aria-label="Tentar novamente">
|
|
79
|
+
<RefreshCw />
|
|
80
|
+
</Button>
|
|
81
|
+
</TooltipTrigger>
|
|
82
|
+
<TooltipContent>Tentar novamente</TooltipContent>
|
|
83
|
+
</Tooltip>
|
|
84
|
+
</TooltipProvider>
|
|
73
85
|
</AlertActions>
|
|
74
86
|
</Alert>
|
|
75
87
|
```
|
|
@@ -83,7 +95,7 @@ ação.
|
|
|
83
95
|
title="Sessão presa"
|
|
84
96
|
description="O ambiente não subiu no tempo esperado."
|
|
85
97
|
>
|
|
86
|
-
<Button
|
|
98
|
+
<Button variant="ghost">
|
|
87
99
|
Reiniciar
|
|
88
100
|
</Button>
|
|
89
101
|
</Alert>
|
|
@@ -27,8 +27,8 @@ há texto visível. O glifo dentro do controle acompanha o tamanho (0.875rem em
|
|
|
27
27
|
| `sm` | 2rem | Toolbar e cabeçalho densos, ao lado de `Select` e `Tabs` `sm`. |
|
|
28
28
|
| `default` | 2.25rem | A linha padrão, a mesma de `Input`. |
|
|
29
29
|
| `lg` | 2.5rem | Chamada principal com mais área de toque. |
|
|
30
|
-
| `icon-xs` | 1.5rem | Ação só de ícone dentro de um campo
|
|
31
|
-
| `icon-sm` | 1.75rem | Ação só de ícone
|
|
30
|
+
| `icon-xs` | 1.5rem | Ação só de ícone dentro de um campo ou de uma linha densa; é o quadrado de `ActionTrigger` com `icon`. |
|
|
31
|
+
| `icon-sm` | 1.75rem | Ação só de ícone em composições compactas que precisam de mais presença; também é o quadrado das setas do pager de `ActionList`. |
|
|
32
32
|
| `icon` | 2.25rem | Ação só de ícone na linha padrão. |
|
|
33
33
|
| `icon-lg` | 2.5rem | Ação só de ícone ao lado de um `lg`. |
|
|
34
34
|
|
|
@@ -80,9 +80,9 @@ buttonVariants serve para o caso sem filho único.
|
|
|
80
80
|
|
|
81
81
|
## ButtonGroup
|
|
82
82
|
|
|
83
|
-
Use `ButtonGroup`
|
|
84
|
-
colapsam e somente as pontas externas
|
|
85
|
-
para preservar a unidade visual.
|
|
83
|
+
Use `ButtonGroup` para manter ações relacionadas juntas. No modo `connected`, que permanece como
|
|
84
|
+
padrão, as bordas internas colapsam e somente as pontas externas ficam arredondadas. Mantenha a
|
|
85
|
+
mesma variante nos filhos para preservar a unidade visual.
|
|
86
86
|
|
|
87
87
|
```tsx preview
|
|
88
88
|
<ButtonGroup>
|
|
@@ -92,6 +92,20 @@ para preservar a unidade visual.
|
|
|
92
92
|
</ButtonGroup>
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
### Ações espaçadas
|
|
96
|
+
|
|
97
|
+
Use `mode="spaced"` quando os controles pertencem ao mesmo conjunto, mas cada um precisa preservar
|
|
98
|
+
sua própria forma e superfície de hover. O grupo aplica o intervalo compacto de `0.25rem` sem
|
|
99
|
+
conectar bordas. Esse modo atende ações icon-only em barras e linhas de listagem.
|
|
100
|
+
|
|
101
|
+
```tsx preview
|
|
102
|
+
<ButtonGroup mode="spaced">
|
|
103
|
+
<Button variant="ghost" size="icon" aria-label="Recarregar"><RotateCw /></Button>
|
|
104
|
+
<Button variant="ghost" size="icon" aria-label="Exibição"><SlidersHorizontal /></Button>
|
|
105
|
+
<Button context="primary" size="icon" aria-label="Novo item"><Plus /></Button>
|
|
106
|
+
</ButtonGroup>
|
|
107
|
+
```
|
|
108
|
+
|
|
95
109
|
### Ação dividida
|
|
96
110
|
|
|
97
111
|
Combine a ação principal, um separador e um botão de ícone quando o mesmo comando oferecer
|
|
@@ -139,6 +153,7 @@ semântica de outro elemento, como `label`.
|
|
|
139
153
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
140
154
|
|---|---|---|---|
|
|
141
155
|
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Direção do bloco e do colapso das bordas. |
|
|
156
|
+
| `mode` | `'connected' \| 'spaced'` | `'connected'` | Conecta as bordas dos controles ou preserva cada controle com intervalo compacto. |
|
|
142
157
|
| `shape` | `'default' \| 'pill'` | `'default'` | Geometria das extremidades externas do grupo. |
|
|
143
158
|
|
|
144
159
|
### Propriedades de ButtonGroupSeparator
|
|
@@ -22,8 +22,8 @@ render(
|
|
|
22
22
|
|
|
23
23
|
Use os slots quando o header precisar de composição própria. A árvore aceita exatamente um
|
|
24
24
|
`ContentHeader` e um `ContentBody` como filhos diretos. O header exige um `ContentTitle` e aceita
|
|
25
|
-
uma descrição, um contador (`ContentMeta`) e uma região de ações
|
|
26
|
-
|
|
25
|
+
uma descrição, um contador (`ContentMeta`) e uma região de ações. O contador é próprio de
|
|
26
|
+
`Content`; `PageHeader` reconhece somente título, descrição e ações.
|
|
27
27
|
|
|
28
28
|
```tsx preview col
|
|
29
29
|
render(
|
|
@@ -49,7 +49,7 @@ do pai correto, filhos estruturais indiretos e a mistura de shorthand com compos
|
|
|
49
49
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
50
50
|
|---|---|---|---|
|
|
51
51
|
| `title` | `ReactNode` | | Forma curta: título da região (vira o heading ligado à `section`). |
|
|
52
|
-
| `count` | `number` | | Forma curta: total de itens ao lado do título
|
|
52
|
+
| `count` | `number` | | Forma curta: total de itens ao lado do título da região. |
|
|
53
53
|
| `description` | `ReactNode` | | Forma curta: frase de apoio sob o título. |
|
|
54
54
|
| `actions` | `ReactNode` | | Forma curta: ações alinhadas à direita do header. |
|
|
55
55
|
| `level` | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | herdado | Nível semântico do heading, independente do destaque visual. |
|
|
@@ -4,8 +4,8 @@ Use `DataState` para apresentar carregamento, erro, vazio e conteúdo de uma mes
|
|
|
4
4
|
superfícies são as mesmas de `PageState`, na escala de uma seção: o carregamento é um contêiner
|
|
5
5
|
`role="status"` com o `Spinner`; o vazio compõe `Empty` com moldura sólida e `emptyMessage` como
|
|
6
6
|
título; o erro é um `Alert` de contexto `danger` com uma mensagem segura, sem expor detalhes
|
|
7
|
-
técnicos, e
|
|
8
|
-
clique, use `busy` em `Button`.
|
|
7
|
+
técnicos, e uma ação `ghost` só com ícone quando há `onRetry`. `retryLabel` fornece o nome acessível
|
|
8
|
+
e o tooltip dessa ação. Para uma ação em andamento depois do clique, use `busy` em `Button`.
|
|
9
9
|
|
|
10
10
|
```tsx preview col
|
|
11
11
|
<div className="w-full space-y-3">
|
|
@@ -48,6 +48,6 @@ disponível para criação ou vínculo, use `Empty` diretamente, com a moldura t
|
|
|
48
48
|
| `emptyMessage` | `string` | `'Nada por aqui.'` | Frase do vazio (ex.: "Nenhum papel."). |
|
|
49
49
|
| `error` | `{ message?: string } \| null` | | Erro da carga — aviso calmo. A mensagem técnica não vai para tela (use `errorMessage`). |
|
|
50
50
|
| `errorMessage` | `string` | `'Não foi possível carregar.'` | Título do aviso de erro, orientado à pessoa. |
|
|
51
|
-
| `onRetry` | `() => void \| Promise<void>` | | Recuperação: mostra
|
|
52
|
-
| `retryLabel` | `string` | `'Tentar de novo'` |
|
|
51
|
+
| `onRetry` | `() => void \| Promise<void>` | | Recuperação: mostra a ação de tentar de novo somente com ícone no estado de erro. |
|
|
52
|
+
| `retryLabel` | `string` | `'Tentar de novo'` | Nome acessível e tooltip da ação de recuperação. |
|
|
53
53
|
| `colSpan` | `number` | | Em tabela: renderiza o estado como `<tr><td colSpan>` (cabe direto no tbody). |
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
## Esqueleto de página
|
|
2
2
|
|
|
3
|
-
Use `Page` para manter
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
Use `Page` para manter navegação contextual, título, ações e conteúdo na mesma anatomia. O
|
|
4
|
+
`PageHeader` padrão acompanha o conteúdo dentro do container; `variant="bar"` transforma o mesmo
|
|
5
|
+
cabeçalho em uma faixa compacta no topo. Não monte um chrome paralelo para repetir essas regiões.
|
|
6
|
+
|
|
7
|
+
Em larguras amplas, as ações ficam no extremo oposto e acompanham a base do título e da descrição;
|
|
8
|
+
em larguras estreitas, passam para uma linha abaixo. O container é centralizado e ocupa a largura
|
|
9
|
+
disponível até `80rem` (`max-w-7xl`). Use `className` somente quando a composição pedir outro teto
|
|
10
|
+
ou largura total.
|
|
9
11
|
|
|
10
12
|
A forma curta é o padrão para páginas comuns. Ela cria internamente `PageHeader` e `PageBody`;
|
|
11
13
|
portanto, não produz uma estrutura visual ou semântica diferente da forma explícita. O cabeçalho é a
|
|
12
|
-
mesma
|
|
13
|
-
|
|
14
|
+
mesma base estrutural de `Content`, mas reconhece somente título, descrição e ações. Contadores e
|
|
15
|
+
outros indicadores pertencem ao conteúdo que os explica.
|
|
14
16
|
|
|
15
|
-
`Page`
|
|
16
|
-
de um shell com sidebar; a navegação lateral não exige remover o teto nem reconstruir o cabeçalho.
|
|
17
|
-
Uma navegação contextual para outra página pode ocupar `actions`, e tabs ficam reservados a
|
|
17
|
+
`Page` também pode ocupar o painel principal de um shell com sidebar. Tabs ficam reservados a
|
|
18
18
|
recortes da mesma superfície. Canvas e outros workspaces espaciais imersivos podem usar um shell
|
|
19
|
-
próprio quando o cabeçalho reduzir a área útil ou duplicar controles persistentes
|
|
19
|
+
próprio quando o cabeçalho reduzir a área útil ou duplicar controles persistentes.
|
|
20
20
|
|
|
21
21
|
Estados integrais de carregamento, falha ou ausência são compostos no body com `PageState`,
|
|
22
22
|
detalhado abaixo. `Page` não recebe flags de dados: uma página pode agregar fontes independentes e
|
|
@@ -27,7 +27,6 @@ render(
|
|
|
27
27
|
<div className="w-full overflow-hidden rounded-lg border border-border">
|
|
28
28
|
<Page
|
|
29
29
|
title="Workspaces"
|
|
30
|
-
count={3}
|
|
31
30
|
description="Ambientes compartilhados pela equipe."
|
|
32
31
|
actions={
|
|
33
32
|
<Button>
|
|
@@ -40,16 +39,58 @@ render(
|
|
|
40
39
|
</div>
|
|
41
40
|
</Page>
|
|
42
41
|
</div>,
|
|
43
|
-
)
|
|
42
|
+
);
|
|
44
43
|
```
|
|
45
44
|
|
|
46
|
-
##
|
|
45
|
+
## Retorno para a página pai
|
|
46
|
+
|
|
47
|
+
Use `PageBack` em uma subpágina simples. O destino é explícito para continuar correto após refresh ou
|
|
48
|
+
acesso por link direto; não derive esse retorno do histórico do navegador. No header padrão, o
|
|
49
|
+
controle aparece acima do título com ícone e rótulo.
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
```tsx preview col
|
|
52
|
+
<Page>
|
|
53
|
+
<PageHeader>
|
|
54
|
+
<PageBack href="/customers">Clientes</PageBack>
|
|
55
|
+
<PageTitle>Qualidade da base</PageTitle>
|
|
56
|
+
<PageDescription>Revise conflitos e canais de contato.</PageDescription>
|
|
57
|
+
</PageHeader>
|
|
58
|
+
<PageBody>Conteúdo da análise.</PageBody>
|
|
59
|
+
</Page>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Não combine `PageBack` com breadcrumb. Use o retorno para um único pai conhecido. Quando houver
|
|
63
|
+
mais de um ancestral relevante, envolva o `Breadcrumb` em `PageNavigation`; ele ocupa a mesma
|
|
64
|
+
posição introdutória sem transformar a trilha em ação.
|
|
65
|
+
|
|
66
|
+
## Cabeçalho em barra
|
|
67
|
+
|
|
68
|
+
Use `variant="bar"` quando título, retorno e ações precisarem formar uma faixa compacta e persistente
|
|
69
|
+
no topo da página. `Page` estende a borda por toda a largura e mantém o conteúdo da barra alinhado ao
|
|
70
|
+
mesmo teto do body. Nesse modo, `PageBack` vira icon-only e recebe tooltip e nome acessível “Voltar
|
|
71
|
+
para {destino}”. Mantenha também as ações compactas: use `sm` em botões com texto e `icon-sm` em
|
|
72
|
+
botões que exibem somente um ícone.
|
|
73
|
+
|
|
74
|
+
```tsx preview col
|
|
75
|
+
<Page className="max-w-none">
|
|
76
|
+
<PageHeader variant="bar">
|
|
77
|
+
<PageBack href="/customers">Clientes</PageBack>
|
|
78
|
+
<PageTitle>Qualidade da base</PageTitle>
|
|
79
|
+
<PageActions>
|
|
80
|
+
<Button variant="ghost" size="icon-sm" aria-label="Mais ações">
|
|
81
|
+
<Ellipsis />
|
|
82
|
+
</Button>
|
|
83
|
+
</PageActions>
|
|
84
|
+
</PageHeader>
|
|
85
|
+
<PageBody>Conteúdo da análise.</PageBody>
|
|
86
|
+
</Page>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Uma página comum não ganha a barra apenas por estar dentro de um shell. Escolha essa variante quando
|
|
90
|
+
a faixa acrescentar contexto ou ações persistentes; sem isso, mantenha o header padrão.
|
|
91
|
+
|
|
92
|
+
`PageActionsTarget` continua disponível para um workspace imersivo que já possua um chrome próprio.
|
|
93
|
+
Ele projeta somente `PageActions` no elemento informado; não cria uma segunda região de cabeçalho.
|
|
53
94
|
|
|
54
95
|
## Composição explícita
|
|
55
96
|
|
|
@@ -61,9 +102,12 @@ render(
|
|
|
61
102
|
<Page>
|
|
62
103
|
<PageHeader>
|
|
63
104
|
<PageTitle>Workspaces</PageTitle>
|
|
64
|
-
<PageMeta>3</PageMeta>
|
|
65
105
|
<PageDescription>Ambientes compartilhados pela equipe.</PageDescription>
|
|
66
|
-
<PageActions
|
|
106
|
+
<PageActions>
|
|
107
|
+
<Button>
|
|
108
|
+
<Plus /> Novo workspace
|
|
109
|
+
</Button>
|
|
110
|
+
</PageActions>
|
|
67
111
|
</PageHeader>
|
|
68
112
|
<PageBody>
|
|
69
113
|
<div className="rounded-lg border border-dashed border-border p-10 text-center">
|
|
@@ -71,15 +115,18 @@ render(
|
|
|
71
115
|
</div>
|
|
72
116
|
</PageBody>
|
|
73
117
|
</Page>,
|
|
74
|
-
)
|
|
118
|
+
);
|
|
75
119
|
```
|
|
76
120
|
|
|
77
121
|
## Estados integrais
|
|
78
122
|
|
|
79
123
|
Use `PageState` quando carregamento, falha ou ausência substituírem todo o conteúdo principal. Na
|
|
80
124
|
forma curta ele pode ser escrito como filho direto de `Page`, que cria o `PageBody`; na forma
|
|
81
|
-
explícita, coloque-o dentro de `PageBody`.
|
|
82
|
-
|
|
125
|
+
explícita, coloque-o sozinho dentro de `PageBody`. Enquanto `status` for `loading`, `error` ou
|
|
126
|
+
`empty`, `Page` oculta o cabeçalho e o estado ocupa a altura disponível. O título do estado assume o
|
|
127
|
+
heading principal. Esse registro também funciona quando um componente intermediário decide qual
|
|
128
|
+
`PageState` renderizar. Em `ready`, o cabeçalho e o conteúdo voltam à composição normal. O cabeçalho some inteiro, incluindo o `PageBack`: uma subpágina que dependa desse retorno
|
|
129
|
+
oferece a saída pelo `action` do próprio `PageState` (ADR 0004, adendo).
|
|
83
130
|
|
|
84
131
|
```tsx preview col
|
|
85
132
|
<Page title="Relatório">
|
|
@@ -87,15 +134,18 @@ altura e semântica acessível consistentes.
|
|
|
87
134
|
status="error"
|
|
88
135
|
title="Não foi possível carregar o relatório"
|
|
89
136
|
description="Tente novamente. Se o problema continuar, volte mais tarde."
|
|
90
|
-
|
|
137
|
+
onRetry={() => {}}
|
|
138
|
+
retryLabel="Tentar novamente"
|
|
91
139
|
/>
|
|
92
140
|
</Page>
|
|
93
141
|
```
|
|
94
142
|
|
|
95
|
-
`loading` centraliza o `Spinner` num contêiner `role="status"`; `error`
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
143
|
+
`loading` centraliza o `Spinner` num contêiner `role="status"`; `error` usa a mesma anatomia visual
|
|
144
|
+
centralizada dos outros estados, conserva `role="alert"` e oferece uma ação `outline` textual quando
|
|
145
|
+
há `onRetry`; `empty` centraliza `Empty` sem moldura; e `ready` entrega os filhos sem
|
|
146
|
+
acrescentar uma superfície. A moldura tracejada continua reservada ao `Empty` usado diretamente para
|
|
147
|
+
representar uma região disponível para criar ou vincular. `title` e `description` nomeiam a situação
|
|
148
|
+
e, sem `title`, valem `errorMessage` e `emptyMessage`.
|
|
99
149
|
|
|
100
150
|
```tsx preview col
|
|
101
151
|
<Page title="Relatórios">
|
|
@@ -115,24 +165,89 @@ estado na própria seção com `DataState`, `ActionView`, `ActionList` ou `Alert
|
|
|
115
165
|
|
|
116
166
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
117
167
|
| ------------- | ----------- | ----------- | ----------------------------------------------------------------------------------------------- |
|
|
118
|
-
| `title` | `
|
|
119
|
-
| `count` | `number` | | Total de itens ao lado do título (mono, esmaecido). |
|
|
168
|
+
| `title` | `ReactNode` | | O h1 da página. |
|
|
120
169
|
| `description` | `ReactNode` | | Linha de contexto sob o título (ex.: "N no total · X ativos"). |
|
|
121
170
|
| `actions` | `ReactNode` | | Ações contextuais no extremo oposto do cabeçalho; em telas estreitas, ficam abaixo do contexto. |
|
|
122
171
|
| `className` | `string` | `max-w-7xl` | Classes do container para substituir o teto padrão de `80rem`. |
|
|
123
172
|
| `children` | `ReactNode` | | O body da página — espaçamento e diagramação são seus. |
|
|
124
173
|
|
|
174
|
+
## Propriedades de PageHeader
|
|
175
|
+
|
|
176
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
177
|
+
| ----------- | ---------------------- | ----------- | ---------------------------------------------------------------- |
|
|
178
|
+
| `variant` | `'default' \| 'bar'` | `'default'` | Apresentação no container ou como faixa compacta no topo. |
|
|
179
|
+
| `className` | `string` | | Classes adicionais da região externa do cabeçalho. |
|
|
180
|
+
| `children` | `ReactNode` | | Um `PageTitle` e, opcionalmente, `PageBack` ou `PageNavigation`, descrição e ações. |
|
|
181
|
+
|
|
182
|
+
## Propriedades de PageBack
|
|
183
|
+
|
|
184
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
185
|
+
| ------------ | ---------------------------- | ------------------------- | ----------------------------------------------------------------------- |
|
|
186
|
+
| `href` | `string` | obrigatório | Destino explícito da página pai. Sem ele o retorno não é tabulável nem tem nome acessível. |
|
|
187
|
+
| `children` | `ReactNode` | | Nome visível do destino no header padrão e conteúdo do tooltip na barra. |
|
|
188
|
+
| `aria-label` | `string` | `Voltar para {children}` | Nome acessível; informe-o quando `children` não for texto simples. |
|
|
189
|
+
| `onClick` | `MouseEventHandler<HTMLAnchorElement>` | | Integração opcional com o roteador do consumidor, junto do `href`, nunca no lugar dele. |
|
|
190
|
+
| `className` | `string` | | Classes adicionais do link renderizado como botão `ghost`. |
|
|
191
|
+
|
|
192
|
+
## Propriedades de PageNavigation
|
|
193
|
+
|
|
194
|
+
| Propriedade | Tipo | Descrição |
|
|
195
|
+
| ----------- | ----------------------------- | ----------------------------------------------- |
|
|
196
|
+
| `children` | `ReactNode` | Trilha estrutural, normalmente um `Breadcrumb`. |
|
|
197
|
+
| `className` | `string` | Classes adicionais do container introdutório. |
|
|
198
|
+
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao container. |
|
|
199
|
+
|
|
200
|
+
## Propriedades de PageTitle
|
|
201
|
+
|
|
202
|
+
| Propriedade | Tipo | Descrição |
|
|
203
|
+
| ----------- | --------------------------------- | ------------------------------------------------------ |
|
|
204
|
+
| `children` | `ReactNode` | Título principal `h1`; compacto na variante `bar`. |
|
|
205
|
+
| `className` | `string` | Classes adicionais do título. |
|
|
206
|
+
| demais | Atributos de `HTMLHeadingElement` | Atributos nativos repassados ao heading. |
|
|
207
|
+
|
|
208
|
+
## Propriedades de PageDescription
|
|
209
|
+
|
|
210
|
+
| Propriedade | Tipo | Descrição |
|
|
211
|
+
| ----------- | ----------------------------------- | ---------------------------------------- |
|
|
212
|
+
| `children` | `ReactNode` | Contexto apresentado abaixo do título. |
|
|
213
|
+
| `className` | `string` | Classes adicionais da descrição. |
|
|
214
|
+
| demais | Atributos de `HTMLParagraphElement` | Atributos nativos repassados ao parágrafo. |
|
|
215
|
+
|
|
216
|
+
## Propriedades de PageActions
|
|
217
|
+
|
|
218
|
+
| Propriedade | Tipo | Descrição |
|
|
219
|
+
| ----------- | ------------------------------ | -------------------------------------------- |
|
|
220
|
+
| `children` | `ReactNode` | Ações no extremo oposto do cabeçalho. |
|
|
221
|
+
| `className` | `string` | Classes adicionais da região de ações. |
|
|
222
|
+
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao container. |
|
|
223
|
+
|
|
224
|
+
## Propriedades de PageBody
|
|
225
|
+
|
|
226
|
+
| Propriedade | Tipo | Descrição |
|
|
227
|
+
| ----------- | ----------------------------- | ----------------------------------------------------- |
|
|
228
|
+
| `children` | `ReactNode` | Conteúdo principal; recebe o container na barra. |
|
|
229
|
+
| `className` | `string` | Classes adicionais da região principal. |
|
|
230
|
+
| demais | Atributos de `HTMLDivElement` | Atributos nativos repassados ao container. |
|
|
231
|
+
|
|
232
|
+
## Propriedades de PageActionsTarget
|
|
233
|
+
|
|
234
|
+
| Propriedade | Tipo | Descrição |
|
|
235
|
+
| ----------- | -------------------- | ----------------------------------------------------------------------- |
|
|
236
|
+
| `target` | `HTMLElement \| null` | Destino externo das ações; `null` mantém as ações no header. |
|
|
237
|
+
| `children` | `ReactNode` | Árvore de página que poderá declarar `PageActions`. |
|
|
238
|
+
|
|
125
239
|
## Propriedades de PageState
|
|
126
240
|
|
|
127
|
-
| Propriedade
|
|
128
|
-
|
|
129
|
-
| `status`
|
|
130
|
-
| `title`
|
|
131
|
-
| `description`
|
|
132
|
-
| `icon`
|
|
133
|
-
| `action`
|
|
134
|
-
| `emptyMessage` | `string`
|
|
135
|
-
| `errorMessage` | `string`
|
|
136
|
-
| `onRetry`
|
|
137
|
-
| `retryLabel`
|
|
138
|
-
| `children`
|
|
241
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
242
|
+
| -------------- | -------------------------------------------- | ----------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
243
|
+
| `status` | `'loading' \| 'error' \| 'empty' \| 'ready'` | | Estado integral do conteúdo. |
|
|
244
|
+
| `title` | `ReactNode` | Texto seguro por estado | Situação reconhecível pela pessoa. |
|
|
245
|
+
| `description` | `ReactNode` | | Impacto ou próximo passo aplicável. |
|
|
246
|
+
| `icon` | `ReactNode` | Alerta no erro | Ícone decorativo do estado. |
|
|
247
|
+
| `action` | `ReactNode` | | Seleção ou criação aplicável ao estado. |
|
|
248
|
+
| `emptyMessage` | `string` | `'Nada por aqui'` | Título do vazio quando `title` não é informado. |
|
|
249
|
+
| `errorMessage` | `string` | `'Não foi possível carregar esta página'` | Título do erro quando `title` não é informado. |
|
|
250
|
+
| `onRetry` | `() => void \| Promise<void>` | | Recuperação do erro: acrescenta um botão `outline` textual ao lado de `action`. |
|
|
251
|
+
| `retryLabel` | `string` | `'Tentar de novo'` | Texto do botão de recuperação. |
|
|
252
|
+
| `children` | `ReactNode` | | Conteúdo renderizado somente em `ready`. |
|
|
253
|
+
| `className` | `string` | | Classes da superfície de estado. |
|
package/src/ui/meta.ts
CHANGED
|
@@ -27,7 +27,7 @@ export const componentMeta = {
|
|
|
27
27
|
name: "alert",
|
|
28
28
|
ancestry: "opus",
|
|
29
29
|
whenToUse:
|
|
30
|
-
"Aviso inline no fluxo da página — `context` declara neutral/info/success/warning/danger e `variant` escolhe subtle/outline (ADR 0006). Forma curta: `<Alert title description icon context />`; para conteúdo rico, componha AlertMedia + AlertHeader (AlertTitle e AlertDescription) + AlertActions. A mídia mantém uma moldura tonal quadrada, mesmo com descrição multilinha. O texto comunica o significado sem depender só da cor. Para interromper cobrando decisão, use `dialog.confirm()`; para recado passageiro, `toast`.",
|
|
30
|
+
"Aviso inline no fluxo da página — `context` declara neutral/info/success/warning/danger e `variant` escolhe subtle/outline (ADR 0006). Forma curta: `<Alert title description icon context />`; para conteúdo rico, componha AlertMedia + AlertHeader (AlertTitle e AlertDescription) + AlertActions. Ações usam Button ghost como ponto de partida; tentativas repetidas podem usar somente o ícone, com nome acessível e tooltip. A mídia mantém uma moldura tonal quadrada, mesmo com descrição multilinha. O texto comunica o significado sem depender só da cor. Para interromper cobrando decisão, use `dialog.confirm()`; para recado passageiro, `toast`.",
|
|
31
31
|
},
|
|
32
32
|
badge: {
|
|
33
33
|
name: "badge",
|
|
@@ -69,7 +69,7 @@ export const componentMeta = {
|
|
|
69
69
|
name: "button",
|
|
70
70
|
ancestry: "shadcn",
|
|
71
71
|
whenToUse:
|
|
72
|
-
"Inicie uma ação com um controle clicável. Use `context` para o significado, `variant` para o tratamento visual e `size` para a escala compartilhada (`xs`…`lg` e os quadrados `icon-*`); `icon` recebe um nó e `busy` comunica o andamento e impede um novo acionamento. Para ações relacionadas, use ButtonGroup.",
|
|
72
|
+
"Inicie uma ação com um controle clicável. Use `context` para o significado, `variant` para o tratamento visual e `size` para a escala compartilhada (`xs`…`lg` e os quadrados `icon-*`); `icon` recebe um nó e `busy` comunica o andamento e impede um novo acionamento. Para ações relacionadas, use ButtonGroup conectado ou espaçado.",
|
|
73
73
|
},
|
|
74
74
|
card: {
|
|
75
75
|
name: "card",
|
|
@@ -117,7 +117,7 @@ export const componentMeta = {
|
|
|
117
117
|
name: "content-header",
|
|
118
118
|
ancestry: "opus",
|
|
119
119
|
whenToUse:
|
|
120
|
-
"Estruture
|
|
120
|
+
"Estruture uma região de conteúdo com título, contador, descrição e ações. No caso comum, declare esses valores diretamente em Content; componha ContentHeader apenas quando precisar controlar a anatomia. Contadores pertencem a Content e não ao título da Page.",
|
|
121
121
|
},
|
|
122
122
|
copyable: {
|
|
123
123
|
name: "copyable",
|
|
@@ -129,7 +129,7 @@ export const componentMeta = {
|
|
|
129
129
|
name: "dialog",
|
|
130
130
|
ancestry: "opus",
|
|
131
131
|
whenToUse:
|
|
132
|
-
|
|
132
|
+
'Abra conteúdo ou uma tarefa em uma janela modal com foco contido. Use o modo padrão quando a superfície puder ser dispensada e `mode="alert"` quando exigir resposta explícita. Para o caso imperativo comum, use `dialog.alert`, `dialog.confirm`, `dialog.prompt` ou `dialog.choose`. Distribua conteúdo próprio entre cabeçalho, corpo rolável e rodapé de ações.',
|
|
133
133
|
},
|
|
134
134
|
input: {
|
|
135
135
|
name: "input",
|
|
@@ -183,7 +183,7 @@ export const componentMeta = {
|
|
|
183
183
|
name: "spinner",
|
|
184
184
|
ancestry: "shadcn",
|
|
185
185
|
whenToUse:
|
|
186
|
-
|
|
186
|
+
'Indique uma espera sem progresso determinado, como uma ação ou consulta em andamento. O ícone é decorativo: o contêiner (`role="status"`) ou o texto ao lado nomeia a espera. Para reservar a forma do conteúdo, use Skeleton.',
|
|
187
187
|
},
|
|
188
188
|
table: {
|
|
189
189
|
name: "table",
|
|
@@ -400,7 +400,7 @@ export const componentMeta = {
|
|
|
400
400
|
name: "page",
|
|
401
401
|
ancestry: "opus",
|
|
402
402
|
whenToUse:
|
|
403
|
-
"O esqueleto de página do back-office: <main> + container centralizado com teto padrão de 80rem (`max-w-7xl`). O shorthand
|
|
403
|
+
"O esqueleto de página do back-office: <main> + container centralizado com teto padrão de 80rem (`max-w-7xl`). O shorthand cobre título, descrição e ações; a forma explícita acrescenta PageBack para retorno simples ou PageNavigation para uma trilha e permite `PageHeader variant=\"bar\"` quando a mesma anatomia precisar virar uma faixa compacta. No header padrão, PageBack fica acima do título; na barra, vira icon-only com tooltip. PageActionsTarget fica restrito a workspaces imersivos com chrome próprio. Quando todo o body estiver carregando, falhar ou estiver vazio, use PageState: ele oculta o header e ocupa a área disponível, centralizado e sem moldura. Para uma região disponível à criação ou vínculo, use Empty.",
|
|
404
404
|
},
|
|
405
405
|
router: {
|
|
406
406
|
name: "router",
|
package/src/ui/react.tsx
CHANGED
|
@@ -423,14 +423,20 @@ export type { DataStateProps } from "./components/patterns/data-state.tsx";
|
|
|
423
423
|
export {
|
|
424
424
|
Page,
|
|
425
425
|
PageHeader,
|
|
426
|
+
PageNavigation,
|
|
427
|
+
PageBack,
|
|
426
428
|
PageTitle,
|
|
427
429
|
PageDescription,
|
|
428
|
-
PageMeta,
|
|
429
430
|
PageActions,
|
|
430
431
|
PageActionsTarget,
|
|
431
432
|
PageBody,
|
|
432
433
|
} from "./components/patterns/page.tsx";
|
|
433
|
-
export type {
|
|
434
|
+
export type {
|
|
435
|
+
PageProps,
|
|
436
|
+
PageBackProps,
|
|
437
|
+
PageHeaderProps,
|
|
438
|
+
PageHeaderVariant,
|
|
439
|
+
} from "./components/patterns/page.tsx";
|
|
434
440
|
|
|
435
441
|
// Estado integral do conteúdo de Page (loading/error/empty/ready), sem acoplar Page a dados.
|
|
436
442
|
export { PageState } from "./components/patterns/page-state.tsx";
|