@softize/opus 12.6.0 → 12.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/package.json +2 -2
- package/src/ui/components/patterns/data-state.tsx +5 -1
- package/src/ui/components/patterns/form.tsx +1 -1
- package/src/ui/components/patterns/list.tsx +2 -5
- package/src/ui/components/patterns/page.tsx +4 -4
- package/src/ui/components/patterns/trigger.tsx +1 -1
- package/src/ui/components/primitives/alert-dialog.tsx +1 -1
- package/src/ui/components/primitives/dialog.tsx +3 -3
- package/src/ui/components/primitives/empty.tsx +1 -1
- package/src/ui/docs/content/action-form-card.md +1 -1
- package/src/ui/docs/content/action-form-dialog.md +2 -0
- package/src/ui/docs/content/alert-dialog.md +1 -1
- package/src/ui/docs/content/button.md +4 -4
- package/src/ui/docs/content/customization.md +1 -1
- package/src/ui/docs/content/data-state.md +6 -3
- package/src/ui/docs/content/dialog.md +2 -2
- package/src/ui/docs/content/drawer.md +2 -2
- package/src/ui/docs/content/empty.md +10 -0
- package/src/ui/docs/content/page.md +4 -4
- package/src/ui/docs/content/popover.md +1 -1
- package/src/ui/meta.ts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,17 @@ Depois de qualquer bump, rode os gates (`typecheck` · `test` · `opus check` ·
|
|
|
7
7
|
`opus copy --check` · `base copy check` · `manifest:check`) — eles apontam o que a
|
|
8
8
|
mudança cobra do seu código.
|
|
9
9
|
|
|
10
|
+
## 12.6.1 — 2026-08-26
|
|
11
|
+
|
|
12
|
+
Os padrões de UI passam a distinguir melhor estrutura e ação. `Page` centraliza o conteúdo com
|
|
13
|
+
teto padrão de `72rem`; estados vazios em bloco preservam uma moldura sólida, enquanto `Empty`
|
|
14
|
+
mantém a moldura tracejada para regiões disponíveis para criação ou vínculo. Colunas numéricas de
|
|
15
|
+
`ActionList` deixam de impor alinhamento e tipografia próprios.
|
|
16
|
+
|
|
17
|
+
Modais removem a borda redundante e usam recorte que impede overlays internos de provocar rolagem
|
|
18
|
+
ao fechar. Ações de cancelamento em formulários e confirmações usam a variante `ghost`, preservando
|
|
19
|
+
o destaque para a ação principal.
|
|
20
|
+
|
|
10
21
|
## 12.6.0 — 2026-08-25
|
|
11
22
|
|
|
12
23
|
`ContentHeader` oferece a composição compartilhada de título, descrição, metadados e ações para
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softize/opus",
|
|
3
|
-
"version": "12.6.
|
|
3
|
+
"version": "12.6.1",
|
|
4
4
|
"description": "End-to-end action protocol for TypeScript. Single package with subpath exports (core + adapters).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -218,7 +218,7 @@
|
|
|
218
218
|
"@radix-ui/react-slot": "^1.1.1",
|
|
219
219
|
"@radix-ui/react-tabs": "^1.1.2",
|
|
220
220
|
"@radix-ui/react-tooltip": "^1.1.6",
|
|
221
|
-
"@softize/base": "^2.1
|
|
221
|
+
"@softize/base": "^2.2.1",
|
|
222
222
|
"@tailwindcss/typography": "^0.5.20",
|
|
223
223
|
"@types/markdown-it": "^14.1.2",
|
|
224
224
|
"class-variance-authority": "^0.7.1",
|
|
@@ -95,5 +95,9 @@ export function DataState({
|
|
|
95
95
|
</div>
|
|
96
96
|
)
|
|
97
97
|
}
|
|
98
|
-
return
|
|
98
|
+
return (
|
|
99
|
+
<p className="rounded-lg border border-border py-10 text-center text-sm text-muted-foreground/60">
|
|
100
|
+
{emptyText}
|
|
101
|
+
</p>
|
|
102
|
+
)
|
|
99
103
|
}
|
|
@@ -589,7 +589,7 @@ export function ActionForm<TInput extends Record<string, unknown>, TData>({
|
|
|
589
589
|
{wrapFooter(
|
|
590
590
|
<>
|
|
591
591
|
{onCancel !== undefined && (
|
|
592
|
-
<Button type="button" variant="
|
|
592
|
+
<Button type="button" variant="ghost" onClick={onCancel}>
|
|
593
593
|
{cancelLabel}
|
|
594
594
|
</Button>
|
|
595
595
|
)}
|
|
@@ -1002,10 +1002,7 @@ export function ActionList<TInput, TItem>({
|
|
|
1002
1002
|
header: text(c.label, c.key),
|
|
1003
1003
|
sortable: c.sortable === true,
|
|
1004
1004
|
spec: c,
|
|
1005
|
-
className: cn(
|
|
1006
|
-
c.fit === true && 'w-px whitespace-nowrap',
|
|
1007
|
-
c.type === 'number' && 'text-right tabular-nums',
|
|
1008
|
-
),
|
|
1005
|
+
className: cn(c.fit === true && 'w-px whitespace-nowrap'),
|
|
1009
1006
|
cell:
|
|
1010
1007
|
cells?.[c.key] ??
|
|
1011
1008
|
((item: TItem): ReactNode => {
|
|
@@ -1409,7 +1406,7 @@ export function ActionList<TInput, TItem>({
|
|
|
1409
1406
|
)}
|
|
1410
1407
|
</AlertDialogHeader>
|
|
1411
1408
|
<AlertDialogFooter>
|
|
1412
|
-
<Button variant="
|
|
1409
|
+
<Button variant="ghost" size="sm" onClick={() => setConfirming(null)}>
|
|
1413
1410
|
Cancelar
|
|
1414
1411
|
</Button>
|
|
1415
1412
|
<Button
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* <Page /> — o esqueleto de página do back-office.
|
|
3
3
|
*
|
|
4
|
-
* Padroniza o que toda página repete: <main> + container
|
|
5
|
-
*
|
|
4
|
+
* Padroniza o que toda página repete: <main> + container centralizado com teto de 72rem
|
|
5
|
+
* (`max-w-6xl`; quem precisar de outra largura sobrescreve por `className`) + header
|
|
6
6
|
* (título, descrição e ações à direita, alinhadas ao fim desse bloco — em geral o botão
|
|
7
7
|
* de criar). O conteúdo é
|
|
8
8
|
* children, sem nada imposto. Presentacional (sem contrato) de propósito: uma página
|
|
@@ -21,7 +21,7 @@ export interface PageProps {
|
|
|
21
21
|
description?: ReactNode
|
|
22
22
|
/** Ações à direita do header, alinhadas ao fim do bloco de contexto. */
|
|
23
23
|
actions?: ReactNode
|
|
24
|
-
/** Classes do container. Default:
|
|
24
|
+
/** Classes do container. Default: centralizado com `max-w-6xl` (72rem). */
|
|
25
25
|
className?: string
|
|
26
26
|
children: ReactNode
|
|
27
27
|
}
|
|
@@ -29,7 +29,7 @@ export interface PageProps {
|
|
|
29
29
|
export function Page({ title, count, description, actions, className, children }: PageProps): React.ReactElement {
|
|
30
30
|
return (
|
|
31
31
|
<main data-slot="page" className="min-w-0 flex-1">
|
|
32
|
-
<div className={cn('mx-auto px-8 py-8', className)}>
|
|
32
|
+
<div className={cn('mx-auto max-w-6xl px-8 py-8', className)}>
|
|
33
33
|
<div data-slot="page-header" className="mb-6">
|
|
34
34
|
<ContentHeaderFrame
|
|
35
35
|
title={title}
|
|
@@ -183,7 +183,7 @@ export function ActionTrigger<TInput, TData>({
|
|
|
183
183
|
)}
|
|
184
184
|
</AlertDialogHeader>
|
|
185
185
|
<AlertDialogFooter>
|
|
186
|
-
<Button variant="
|
|
186
|
+
<Button variant="ghost" onClick={() => setOpen(false)} disabled={isLoading}>
|
|
187
187
|
{confirm.cancelLabel ?? 'Cancelar'}
|
|
188
188
|
</Button>
|
|
189
189
|
<Button variant={confirmVariant} busy={isLoading} onClick={fire}>
|
|
@@ -51,10 +51,10 @@ export function DialogContent({
|
|
|
51
51
|
<DialogPrimitive.Content
|
|
52
52
|
data-slot="dialog-content"
|
|
53
53
|
className={cn(
|
|
54
|
-
// Superfície PURA: só a casca (
|
|
54
|
+
// Superfície PURA: só a casca (bg/raio/sombra) + coluna flex com teto de
|
|
55
55
|
// altura. O padding mora nos SLOTS (Header/Body/Footer), não aqui — assim ninguém
|
|
56
56
|
// precisa negar margem pra escapar de um p-6 embutido.
|
|
57
|
-
"fixed left-[50%] top-[50%] z-50 flex max-h-[85vh] w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] flex-col overflow-
|
|
57
|
+
"fixed left-[50%] top-[50%] z-50 flex max-h-[85vh] w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] flex-col overflow-clip rounded-xl bg-card text-card-foreground shadow-lg duration-200 outline-none data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg",
|
|
58
58
|
className,
|
|
59
59
|
)}
|
|
60
60
|
{...props}
|
|
@@ -110,7 +110,7 @@ export function DialogFooter({ className, ...props }: React.ComponentProps<'div'
|
|
|
110
110
|
data-slot="dialog-footer"
|
|
111
111
|
// Faixa destacada (divergência da casa, ao estilo do site do shadcn): borda em cima
|
|
112
112
|
// + fundo muted. Sangra até as bordas sozinha — o content não tem padding, então não
|
|
113
|
-
// há -mx pra compensar; o
|
|
113
|
+
// há -mx pra compensar; o recorte do content arredonda o canto de baixo.
|
|
114
114
|
className={cn(
|
|
115
115
|
'flex shrink-0 flex-col-reverse gap-2 border-t bg-muted/30 px-5 py-4 sm:flex-row sm:justify-end',
|
|
116
116
|
className,
|
|
@@ -7,7 +7,7 @@ function Empty({ className, ...props }: React.ComponentProps<"div">) {
|
|
|
7
7
|
<div
|
|
8
8
|
data-slot="empty"
|
|
9
9
|
className={cn(
|
|
10
|
-
"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance md:p-12",
|
|
10
|
+
"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border border-dashed border-border p-6 text-center text-balance md:p-12",
|
|
11
11
|
className
|
|
12
12
|
)}
|
|
13
13
|
{...props}
|
|
@@ -9,7 +9,7 @@ faixa de modal). Pra estruturar uma seção da página como painel. O título é
|
|
|
9
9
|
title="Editar workspace"
|
|
10
10
|
action={docWorkspaceCreate}
|
|
11
11
|
defaultValues={{ name: 'Empresa X', status: 'active' }}
|
|
12
|
-
submitLabel="Salvar"
|
|
12
|
+
submitLabel="Salvar alterações"
|
|
13
13
|
/>
|
|
14
14
|
</DocBrowserActionProvider>
|
|
15
15
|
```
|
|
@@ -16,6 +16,7 @@ render(
|
|
|
16
16
|
title="Novo workspace"
|
|
17
17
|
description="O workspace agrupa os repositórios e agentes do cliente."
|
|
18
18
|
action={docWorkspaceCreate}
|
|
19
|
+
submitLabel="Criar workspace"
|
|
19
20
|
/>
|
|
20
21
|
</DocBrowserActionProvider>,
|
|
21
22
|
)
|
|
@@ -27,4 +28,5 @@ render(
|
|
|
27
28
|
|---|---|---|---|
|
|
28
29
|
| `open / onOpenChange` | `boolean / (open: boolean) => void` | | Controle do modal — o pattern chama onOpenChange(false) no sucesso e no Cancelar. |
|
|
29
30
|
| `title / description` | `string` | | O DialogHeader fixo — description é opcional. |
|
|
31
|
+
| `submitLabel` | `string` | `'Salvar'` | Resultado da ação principal. Em criação, informe `Criar {recurso}`; em edição, `Salvar alterações`. |
|
|
30
32
|
| `…ActionFormProps` | `action, defaultValues, onSuccess, fieldOptions…` | | Todo o resto desce pro ActionForm interno — mesma API da página dele. |
|
|
@@ -70,4 +70,4 @@ composição e onde o `variant` entra:
|
|
|
70
70
|
| `open` (AlertDialog) | `boolean` | | Estado de aberto no modo controlado — pareie com onOpenChange. No padrão, o Trigger cuida disso. |
|
|
71
71
|
| `onOpenChange` (AlertDialog) | `(open: boolean) => void` | | Chamado quando o diálogo abre ou fecha (Trigger, Cancel, Action ou Esc). |
|
|
72
72
|
| `variant` (AlertDialogAction) | `'default' \| 'destructive' \| 'outline' \| 'secondary' \| 'ghost' \| 'link'` | `'default'` | Intenção do botão de confirmar (herdada do Button) — destructive pra ação perigosa. |
|
|
73
|
-
| `variant` (AlertDialogCancel) | `'default' \| 'destructive' \| 'outline' \| 'secondary' \| 'ghost' \| 'link'` | `'
|
|
73
|
+
| `variant` (AlertDialogCancel) | `'default' \| 'destructive' \| 'outline' \| 'secondary' \| 'ghost' \| 'link'` | `'ghost'` | Intenção do botão de cancelar (herdada do Button). |
|
|
@@ -4,10 +4,10 @@ variant é intenção, não decoração: default pra ação principal (uma por t
|
|
|
4
4
|
quando destrói de verdade.
|
|
5
5
|
|
|
6
6
|
```tsx preview
|
|
7
|
-
<Button>
|
|
7
|
+
<Button>Criar workspace</Button>
|
|
8
8
|
<Button variant="secondary">Duplicar</Button>
|
|
9
|
-
<Button variant="outline">
|
|
10
|
-
<Button variant="ghost">
|
|
9
|
+
<Button variant="outline">Ver prévia</Button>
|
|
10
|
+
<Button variant="ghost">Cancelar</Button>
|
|
11
11
|
<Button variant="destructive">Excluir</Button>
|
|
12
12
|
<Button variant="link">Ver documentação</Button>
|
|
13
13
|
```
|
|
@@ -33,7 +33,7 @@ centralizado/Skeleton num nível de página.
|
|
|
33
33
|
|
|
34
34
|
```tsx preview
|
|
35
35
|
<Button disabled>Desabilitado</Button>
|
|
36
|
-
<Button busy>
|
|
36
|
+
<Button busy>Salvando…</Button>
|
|
37
37
|
<Button icon={Plus}>Novo</Button>
|
|
38
38
|
<Button icon={Plus} busy>Novo</Button>
|
|
39
39
|
```
|
|
@@ -39,7 +39,7 @@ de 16, sem transformar esse valor em uma regra da biblioteca.
|
|
|
39
39
|
> vence o conflito. Pra layout local (largura, margem, grid) — não pra repintar o visual da casa.
|
|
40
40
|
|
|
41
41
|
```tsx
|
|
42
|
-
<Button className="w-full">
|
|
42
|
+
<Button className="w-full">Continuar</Button>
|
|
43
43
|
<Card className="max-w-sm" />
|
|
44
44
|
<DialogContent className="sm:max-w-2xl" />
|
|
45
45
|
```
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
## Estados
|
|
2
2
|
|
|
3
3
|
Um lugar só pro erro/carregando/vazio/conteúdo de uma carga. Carregando = Spinner centralizado;
|
|
4
|
-
vazio = texto; erro = aviso calmo (a mensagem técnica não vai
|
|
4
|
+
vazio = texto em uma moldura sólida no modo bloco; erro = aviso calmo (a mensagem técnica não vai
|
|
5
|
+
pra tela). É o "antes" do conteúdo —
|
|
5
6
|
pro "depois" (ação em andamento), use o busy do Button.
|
|
6
7
|
|
|
7
8
|
```tsx preview col
|
|
@@ -20,8 +21,10 @@ pro "depois" (ação em andamento), use o busy do Button.
|
|
|
20
21
|
|
|
21
22
|
## Em tabela (colSpan)
|
|
22
23
|
|
|
23
|
-
Em lista
|
|
24
|
-
que cabe direto no `<tbody>`; o conteúdo são as `<tr>` dos itens.
|
|
24
|
+
Em lista ou tabela já emoldurada, passe colSpan: o estado vira UMA linha de largura cheia
|
|
25
|
+
(`<tr><td colSpan>`) que cabe direto no `<tbody>`; o conteúdo são as `<tr>` dos itens. A tabela
|
|
26
|
+
continua dona da borda, sem uma segunda moldura no vazio. Para uma região disponível para criação
|
|
27
|
+
ou vínculo, com título, descrição ou ação, use `Empty`, cuja moldura é tracejada.
|
|
25
28
|
|
|
26
29
|
```tsx preview col
|
|
27
30
|
<table className="w-full overflow-hidden rounded-lg border border-border text-sm">
|
|
@@ -18,7 +18,7 @@ Content é superfície pura; o espaço mora nos slots (body p-5; header/footer p
|
|
|
18
18
|
</DialogBody>
|
|
19
19
|
<DialogFooter>
|
|
20
20
|
<DialogClose asChild>
|
|
21
|
-
<Button variant="
|
|
21
|
+
<Button variant="ghost" size="sm">Cancelar</Button>
|
|
22
22
|
</DialogClose>
|
|
23
23
|
<Button size="sm">Criar</Button>
|
|
24
24
|
</DialogFooter>
|
|
@@ -42,7 +42,7 @@ showCloseButton={false} esconde o X: o usuário decide pelos botões — pra con
|
|
|
42
42
|
</DialogHeader>
|
|
43
43
|
<DialogFooter>
|
|
44
44
|
<DialogClose asChild>
|
|
45
|
-
<Button variant="
|
|
45
|
+
<Button variant="ghost" size="sm">Cancelar</Button>
|
|
46
46
|
</DialogClose>
|
|
47
47
|
<DialogClose asChild>
|
|
48
48
|
<Button variant="destructive" size="sm">Excluir</Button>
|
|
@@ -38,9 +38,9 @@ side aceita top|right|bottom|left. DrawerFooter ancora as ações no rodapé; Dr
|
|
|
38
38
|
</div>
|
|
39
39
|
<DrawerFooter>
|
|
40
40
|
<DrawerClose asChild>
|
|
41
|
-
<Button variant="
|
|
41
|
+
<Button variant="ghost" size="sm">Cancelar</Button>
|
|
42
42
|
</DrawerClose>
|
|
43
|
-
<Button size="sm">Salvar</Button>
|
|
43
|
+
<Button size="sm">Salvar alterações</Button>
|
|
44
44
|
</DrawerFooter>
|
|
45
45
|
</DrawerContent>
|
|
46
46
|
</Drawer>
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## Quando usar
|
|
2
|
+
|
|
3
|
+
Use `Empty` quando a própria região está disponível para receber ou criar conteúdo. A moldura
|
|
4
|
+
tracejada diferencia esse espaço de uma estrutura de dados já estabelecida e pode combinar título,
|
|
5
|
+
descrição, mídia e ação.
|
|
6
|
+
|
|
7
|
+
Para uma lista ou tabela carregada, mas sem registros, use `DataState` ou `ActionList`: a moldura
|
|
8
|
+
sólida preserva a estrutura. Se a região já estiver emoldurada pelo pai, mantenha a borda somente
|
|
9
|
+
no pai para evitar uma moldura dupla.
|
|
10
|
+
|
|
1
11
|
## Com ícone
|
|
2
12
|
|
|
3
13
|
EmptyMedia variant=icon desenha o quadrado de fundo muted atrás do ícone; o EmptyHeader agrupa mídia, título e descrição no centro.
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Use `Page` para manter título, contexto, ações e conteúdo no mesmo ritmo visual nas telas do
|
|
4
4
|
back-office. As ações ficam à direita e acompanham a base do conjunto formado pelo título e pela
|
|
5
|
-
descrição. O
|
|
6
|
-
|
|
7
|
-
tabelas, cards ou outras composições.
|
|
5
|
+
descrição. O container é centralizado e ocupa a largura disponível até `72rem` (`max-w-6xl`). Use
|
|
6
|
+
`className` somente quando a composição pedir explicitamente outro teto ou largura total. A área
|
|
7
|
+
abaixo do cabeçalho permanece livre para tabelas, cards ou outras composições.
|
|
8
8
|
|
|
9
9
|
```tsx preview col
|
|
10
10
|
render(
|
|
@@ -35,5 +35,5 @@ render(
|
|
|
35
35
|
| `count` | `number` | | Total de itens ao lado do título (mono, esmaecido). |
|
|
36
36
|
| `description` | `ReactNode` | | Linha de contexto sob o título (ex.: "N no total · X ativos"). |
|
|
37
37
|
| `actions` | `ReactNode` | | Ações à direita do cabeçalho, alinhadas à base do título e da descrição. |
|
|
38
|
-
| `className` | `string` |
|
|
38
|
+
| `className` | `string` | `max-w-6xl` | Classes do container para substituir o teto padrão de `72rem`. |
|
|
39
39
|
| `children` | `ReactNode` | | O conteúdo — espaçamento e diagramação são seus. |
|
|
@@ -15,7 +15,7 @@ PopoverHeader agrupa título e descrição; o corpo é livre (form curto, detalh
|
|
|
15
15
|
<div className="mt-3 space-y-2">
|
|
16
16
|
<Label htmlFor="pop-titulo">Título</Label>
|
|
17
17
|
<Input id="pop-titulo" defaultValue="Onboarding do faturamento" />
|
|
18
|
-
<Button size="sm" className="w-full">
|
|
18
|
+
<Button size="sm" className="w-full">Renomear</Button>
|
|
19
19
|
</div>
|
|
20
20
|
</PopoverContent>
|
|
21
21
|
</Popover>
|
package/src/ui/meta.ts
CHANGED
|
@@ -251,7 +251,7 @@ export const componentMeta = {
|
|
|
251
251
|
name: 'empty',
|
|
252
252
|
ancestry: 'shadcn',
|
|
253
253
|
whenToUse:
|
|
254
|
-
'
|
|
254
|
+
'Região disponível para receber ou criar conteúdo: moldura tracejada centrada com `EmptyHeader` (mídia + `EmptyTitle` + `EmptyDescription`) e `EmptyContent` pras ações. Para lista ou tabela carregada sem registros, use DataState ou ActionList, que preservam a moldura sólida da estrutura. `EmptyMedia variant` icon (quadrado muted) ou default (sem fundo). Pra erro inline use Alert; pra carregamento, Skeleton.',
|
|
255
255
|
},
|
|
256
256
|
'field': {
|
|
257
257
|
name: 'field',
|
|
@@ -390,7 +390,7 @@ export const componentMeta = {
|
|
|
390
390
|
name: 'page',
|
|
391
391
|
ancestry: 'opus',
|
|
392
392
|
whenToUse:
|
|
393
|
-
'O esqueleto de página do back-office: <main> + container de
|
|
393
|
+
'O esqueleto de página do back-office: <main> + container centralizado com teto padrão de 72rem (`max-w-6xl`) + header com título, descrição e ação à direita (em geral o criar). `className` substitui o teto quando a composição pede outra largura. Presentacional (a página agrega N fontes); o action-driven mora dentro. Pra listagem em modal, ActionListDialog.',
|
|
394
394
|
},
|
|
395
395
|
'router': {
|
|
396
396
|
name: 'router',
|
|
@@ -402,7 +402,7 @@ export const componentMeta = {
|
|
|
402
402
|
name: 'data-state',
|
|
403
403
|
ancestry: 'opus',
|
|
404
404
|
whenToUse:
|
|
405
|
-
'O estado "carregando" (ANTES do conteúdo): orquestra erro/carregando/vazio/conteúdo de uma carga assíncrona num só lugar — Spinner centralizado no loading, texto no vazio
|
|
405
|
+
'O estado "carregando" (ANTES do conteúdo): orquestra erro/carregando/vazio/conteúdo de uma carga assíncrona num só lugar — Spinner centralizado no loading, texto em moldura sólida no vazio em bloco e aviso calmo no erro. Em tabela emoldurada, `colSpan` mantém a borda somente no pai. Pra uma região disponível para criação ou vínculo, use Empty, cuja moldura é tracejada. Pra "processando" (ação em andamento DEPOIS do clique), use o `busy` do Button. Pra placeholder com forma, Skeleton.',
|
|
406
406
|
},
|
|
407
407
|
'action-list-dialog': {
|
|
408
408
|
name: 'action-list-dialog',
|