@softize/opus 23.0.0 → 24.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 +81 -0
- package/bin/cli.mjs +2 -0
- package/bin/lib/check.mjs +241 -42
- package/bin/lib/copy.mjs +16 -34
- package/docs/adr/0023-surfaces-share-one-anatomy-and-two-layouts.md +6 -0
- package/docs/adr/0039-filter-presentation-is-independent-from-filter-type.md +3 -3
- package/docs/adr/0040-tabs-use-a-single-navigation-presentation.md +5 -6
- package/docs/adr/0042-toggle-group-shares-the-grouped-control-grammar.md +79 -0
- package/docs/adr/0043-neutral-surfaces-and-interactions-use-opaque-role-tokens.md +73 -0
- package/docs/adr/0044-neutral-appearance-derives-from-bounded-axes-per-mode.md +133 -0
- package/docs/adr/0045-surface-replaces-content-and-card.md +230 -0
- package/docs/adr/0046-structural-body-owns-content-rhythm.md +103 -0
- package/docs/adr/0047-pane-is-only-a-split-layout-unit.md +71 -0
- package/docs/adr/0048-modal-intro-separates-content-from-chrome.md +34 -0
- package/package.json +5 -1
- package/registry/skills/build-opus-ui/SKILL.md +11 -11
- package/registry/skills/build-opus-ui/references/evaluations.md +10 -9
- package/registry/skills/build-opus-ui/references/ui-patterns.md +17 -16
- package/registry/templates/app/src/App.tsx +24 -12
- package/src/ui/appearance.ts +149 -0
- package/src/ui/components/patterns/action-form-card.tsx +46 -33
- package/src/ui/components/patterns/action-list-dialog.tsx +2 -4
- package/src/ui/components/patterns/confirm.tsx +3 -1
- package/src/ui/components/patterns/fill-region.ts +8 -7
- package/src/ui/components/patterns/form-dialog.tsx +1 -3
- package/src/ui/components/patterns/form.tsx +8 -7
- package/src/ui/components/patterns/list.tsx +15 -19
- package/src/ui/components/patterns/page.tsx +15 -11
- package/src/ui/components/patterns/pane.tsx +9 -240
- package/src/ui/components/patterns/presentation.tsx +14 -14
- package/src/ui/components/patterns/sidebar.tsx +7 -17
- package/src/ui/components/patterns/split.tsx +111 -59
- package/src/ui/components/patterns/{surface-header.tsx → structural-header.tsx} +50 -19
- package/src/ui/components/patterns/structural-media.tsx +26 -0
- package/src/ui/components/patterns/surface-anatomy.ts +71 -61
- package/src/ui/components/patterns/surface-assistant.tsx +2 -4
- package/src/ui/components/patterns/surface.tsx +620 -0
- package/src/ui/components/patterns/trigger.tsx +11 -9
- package/src/ui/components/primitives/ask.tsx +155 -83
- package/src/ui/components/primitives/button.tsx +11 -9
- package/src/ui/components/primitives/checkbox.tsx +8 -8
- package/src/ui/components/primitives/command.tsx +1 -1
- package/src/ui/components/primitives/composer.tsx +47 -45
- package/src/ui/components/primitives/detail.tsx +9 -2
- package/src/ui/components/primitives/dialog.tsx +60 -26
- package/src/ui/components/primitives/drawer.tsx +58 -12
- package/src/ui/components/primitives/icon-picker.tsx +90 -73
- package/src/ui/components/primitives/input-group.tsx +35 -28
- package/src/ui/components/primitives/input-otp.tsx +16 -16
- package/src/ui/components/primitives/input.tsx +20 -10
- package/src/ui/components/primitives/item.tsx +9 -12
- package/src/ui/components/primitives/menu.tsx +44 -65
- package/src/ui/components/primitives/metric-card.tsx +75 -59
- package/src/ui/components/primitives/radio-group.tsx +9 -9
- package/src/ui/components/primitives/select.tsx +344 -209
- package/src/ui/components/primitives/switch.tsx +10 -10
- package/src/ui/components/primitives/table.tsx +29 -24
- package/src/ui/components/primitives/tabs.tsx +4 -2
- package/src/ui/components/primitives/textarea.tsx +6 -6
- package/src/ui/components/primitives/toggle-group-context.ts +24 -0
- package/src/ui/components/primitives/toggle-group.tsx +116 -74
- package/src/ui/components/primitives/toggle.tsx +82 -16
- package/src/ui/docs/DocBrowser.tsx +77 -69
- package/src/ui/docs/content/action-form-card.md +9 -9
- package/src/ui/docs/content/action-list.md +76 -70
- package/src/ui/docs/content/action-view.md +33 -18
- package/src/ui/docs/content/button.md +1 -1
- package/src/ui/docs/content/communication.md +1 -1
- package/src/ui/docs/content/customization.md +64 -11
- package/src/ui/docs/content/detail.md +8 -6
- package/src/ui/docs/content/dialog.md +100 -58
- package/src/ui/docs/content/drawer.md +63 -19
- package/src/ui/docs/content/field.md +14 -15
- package/src/ui/docs/content/icon-tile.md +14 -13
- package/src/ui/docs/content/page.md +34 -26
- package/src/ui/docs/content/pane.md +41 -290
- package/src/ui/docs/content/presentation.md +3 -3
- package/src/ui/docs/content/separator.md +6 -6
- package/src/ui/docs/content/sidebar.md +68 -266
- package/src/ui/docs/content/skeleton.md +20 -18
- package/src/ui/docs/content/split.md +14 -14
- package/src/ui/docs/content/surface.md +513 -0
- package/src/ui/docs/content/tabs.md +20 -20
- package/src/ui/docs/content/toggle.md +117 -65
- package/src/ui/docs/content/tokens.md +124 -40
- package/src/ui/docs/registry.tsx +4 -6
- package/src/ui/index.ts +30 -27
- package/src/ui/meta.ts +15 -27
- package/src/ui/react.tsx +40 -43
- package/src/ui/theme.css +311 -64
- package/src/ui/components/patterns/content-header.tsx +0 -528
- package/src/ui/components/patterns/surface-media.tsx +0 -69
- package/src/ui/components/primitives/card.tsx +0 -191
- package/src/ui/docs/content/card.md +0 -292
- package/src/ui/docs/content/content.md +0 -275
package/src/ui/index.ts
CHANGED
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
* Aqui ficam apenas types/contratos compartilhados.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { ActionError, Paginated } from
|
|
8
|
+
import type { ActionError, Paginated } from "../core/index.ts";
|
|
9
|
+
|
|
10
|
+
// Personalização de aparência (ADR 0044): sem React, também disponível em `./ui/appearance`.
|
|
11
|
+
export * from "./appearance.ts";
|
|
9
12
|
|
|
10
13
|
/**
|
|
11
14
|
* Metadado de descoberta de um componente — cada componente co-localiza um `meta`
|
|
@@ -13,18 +16,18 @@ import type { ActionError, Paginated } from '../core/index.ts'
|
|
|
13
16
|
*/
|
|
14
17
|
export interface ComponentMeta {
|
|
15
18
|
/** Nome canônico (kebab), ex.: 'button', 'dropdown-menu'. */
|
|
16
|
-
name: string
|
|
19
|
+
name: string;
|
|
17
20
|
/** Origem: descendente do shadcn (forkado) ou nativo do Opus. */
|
|
18
|
-
ancestry:
|
|
21
|
+
ancestry: "shadcn" | "opus";
|
|
19
22
|
/** Quando usar / quando não — guia o agente de design a escolher certo. */
|
|
20
|
-
whenToUse: string
|
|
23
|
+
whenToUse: string;
|
|
21
24
|
/** Aviso de retirada no catálogo, com o caminho de migração. */
|
|
22
25
|
deprecated?: {
|
|
23
26
|
/** Alternativa recomendada; aceita `código` inline como `whenToUse`. */
|
|
24
|
-
alternative: string
|
|
27
|
+
alternative: string;
|
|
25
28
|
/** Versão em que a retirada começou, quando houver. */
|
|
26
|
-
since?: string
|
|
27
|
-
}
|
|
29
|
+
since?: string;
|
|
30
|
+
};
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
/**
|
|
@@ -32,23 +35,23 @@ export interface ComponentMeta {
|
|
|
32
35
|
* shape derivado disto.
|
|
33
36
|
*/
|
|
34
37
|
export interface ActionState<TData> {
|
|
35
|
-
data: TData | undefined
|
|
36
|
-
error: ActionError | undefined
|
|
37
|
-
isIdle: boolean
|
|
38
|
-
isLoading: boolean
|
|
39
|
-
isSuccess: boolean
|
|
40
|
-
isError: boolean
|
|
38
|
+
data: TData | undefined;
|
|
39
|
+
error: ActionError | undefined;
|
|
40
|
+
isIdle: boolean;
|
|
41
|
+
isLoading: boolean;
|
|
42
|
+
isSuccess: boolean;
|
|
43
|
+
isError: boolean;
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
export interface ListState<TItem> {
|
|
44
|
-
items: TItem[]
|
|
45
|
-
cursor: { next: string | null; prev?: string | null }
|
|
46
|
-
total: number | undefined
|
|
47
|
-
error: ActionError | undefined
|
|
48
|
-
isIdle: boolean
|
|
49
|
-
isLoading: boolean
|
|
50
|
-
isSuccess: boolean
|
|
51
|
-
isError: boolean
|
|
47
|
+
items: TItem[];
|
|
48
|
+
cursor: { next: string | null; prev?: string | null };
|
|
49
|
+
total: number | undefined;
|
|
50
|
+
error: ActionError | undefined;
|
|
51
|
+
isIdle: boolean;
|
|
52
|
+
isLoading: boolean;
|
|
53
|
+
isSuccess: boolean;
|
|
54
|
+
isError: boolean;
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
/**
|
|
@@ -62,7 +65,7 @@ export function idleAction<T>(): ActionState<T> {
|
|
|
62
65
|
isLoading: false,
|
|
63
66
|
isSuccess: false,
|
|
64
67
|
isError: false,
|
|
65
|
-
}
|
|
68
|
+
};
|
|
66
69
|
}
|
|
67
70
|
|
|
68
71
|
export function idleLookup<T>(): ListState<T> {
|
|
@@ -75,7 +78,7 @@ export function idleLookup<T>(): ListState<T> {
|
|
|
75
78
|
isLoading: false,
|
|
76
79
|
isSuccess: false,
|
|
77
80
|
isError: false,
|
|
78
|
-
}
|
|
81
|
+
};
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
/**
|
|
@@ -83,10 +86,10 @@ export function idleLookup<T>(): ListState<T> {
|
|
|
83
86
|
*/
|
|
84
87
|
export function isPaginated(value: unknown): value is Paginated<unknown> {
|
|
85
88
|
return (
|
|
86
|
-
typeof value ===
|
|
89
|
+
typeof value === "object" &&
|
|
87
90
|
value !== null &&
|
|
88
|
-
|
|
91
|
+
"items" in value &&
|
|
89
92
|
Array.isArray((value as { items: unknown }).items) &&
|
|
90
|
-
|
|
91
|
-
)
|
|
93
|
+
"cursor" in value
|
|
94
|
+
);
|
|
92
95
|
}
|
package/src/ui/meta.ts
CHANGED
|
@@ -11,11 +11,11 @@ import type { ComponentMeta } from "./index.ts";
|
|
|
11
11
|
|
|
12
12
|
/** Todos os metas, chaveados pelo nome canônico (kebab). Fonte única — zero duplicação. */
|
|
13
13
|
export const componentMeta = {
|
|
14
|
-
|
|
15
|
-
name: "
|
|
14
|
+
surface: {
|
|
15
|
+
name: "surface",
|
|
16
16
|
ancestry: "opus",
|
|
17
17
|
whenToUse:
|
|
18
|
-
|
|
18
|
+
'Delimite e nomeie um trecho da tela: uma região da página, um grupo de campos, um registro, um item de grade ou um bloco clicável. `as` escolhe o elemento (`div`, `section`, `article` ou `fieldset`) e `asChild` entrega a superfície a um botão ou link. `framed` acrescenta a moldura, `elevation="raised"` dá fundo próprio e `layout` escolhe entre ritmo contínuo e faixas com divisores. No caso comum, declare `title`, `description`, `count`, `actions` e `media` na própria Surface; componha SurfaceHeader, SurfaceBody e SurfaceFooter quando precisar controlar a estrutura. Numa página centrada em uma coleção, `level={1}` faz da Surface o heading principal; nas demais, ele vem de PageTitle. Para um modal use Dialog, para um painel lateral use Drawer e para uma coluna de layout use Pane.',
|
|
19
19
|
},
|
|
20
20
|
ask: {
|
|
21
21
|
name: "ask",
|
|
@@ -77,17 +77,11 @@ export const componentMeta = {
|
|
|
77
77
|
whenToUse:
|
|
78
78
|
"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, espaçado ou dividido.",
|
|
79
79
|
},
|
|
80
|
-
card: {
|
|
81
|
-
name: "card",
|
|
82
|
-
ancestry: "shadcn",
|
|
83
|
-
whenToUse:
|
|
84
|
-
"Agrupe conteúdo relacionado em uma superfície delimitada. Use Card diretamente para um bloco simples ou componha cabeçalho, corpo e rodapé quando houver hierarquia e ações. CardContent permanece apenas como alias temporário de compatibilidade.",
|
|
85
|
-
},
|
|
86
80
|
"metric-card": {
|
|
87
81
|
name: "metric-card",
|
|
88
82
|
ancestry: "opus",
|
|
89
83
|
whenToUse:
|
|
90
|
-
"Apresente uma medida resumida, como um total ou uma contagem, com rótulo, valor em destaque e descrição opcional. O consumidor calcula e formata os valores. Use `secondaryMetric` para uma segunda leitura da mesma dimensão, exibida como lâmina posterior com rótulo próprio; `context` realça somente o ícone, `action` acrescenta uma ação diretamente relacionada e `loading` substitui rótulo e valor durante a carga. Com `onActivate`, `active` e `activationLabel`, informados juntos, o card vira um controle que aplica o recorte que a medida resume e expõe o estado por `aria-pressed`. Para conteúdo geral ou estrutura livre, use
|
|
84
|
+
"Apresente uma medida resumida, como um total ou uma contagem, com rótulo, valor em destaque e descrição opcional. O consumidor calcula e formata os valores. Use `secondaryMetric` para uma segunda leitura da mesma dimensão, exibida como lâmina posterior com rótulo próprio; `context` realça somente o ícone, `action` acrescenta uma ação diretamente relacionada e `loading` substitui rótulo e valor durante a carga. Com `onActivate`, `active` e `activationLabel`, informados juntos, o card vira um controle que aplica o recorte que a medida resume e expõe o estado por `aria-pressed`. Para conteúdo geral ou estrutura livre, use Surface.",
|
|
91
85
|
},
|
|
92
86
|
chat: {
|
|
93
87
|
name: "chat",
|
|
@@ -119,12 +113,6 @@ export const componentMeta = {
|
|
|
119
113
|
whenToUse:
|
|
120
114
|
"Receba texto para envio sem montar uma conversa completa. Enter envia, Shift+Enter quebra a linha e `actions` acrescenta uma faixa para seletores relacionados. O componente é controlado; use Chat quando também precisar de mensagens e estado da conversa.",
|
|
121
115
|
},
|
|
122
|
-
"content-header": {
|
|
123
|
-
name: "content-header",
|
|
124
|
-
ancestry: "opus",
|
|
125
|
-
whenToUse:
|
|
126
|
-
'Estruture uma região com título e corpo. No caso comum, declare título, mídia, descrição, contador e ações diretamente em Content; use `framed` quando a região precisar de limite próprio, `layout="sectioned"` quando o filho controlar o recuo do body, `frameVariant="legend"` para integrar visualmente o header à borda e `as="fieldset"` somente para agrupar campos sob uma legenda nativa. Componha ContentHeader apenas quando precisar controlar a anatomia.',
|
|
127
|
-
},
|
|
128
116
|
copyable: {
|
|
129
117
|
name: "copyable",
|
|
130
118
|
ancestry: "opus",
|
|
@@ -177,7 +165,7 @@ export const componentMeta = {
|
|
|
177
165
|
name: "separator",
|
|
178
166
|
ancestry: "shadcn",
|
|
179
167
|
whenToUse:
|
|
180
|
-
'Marque a fronteira entre blocos de conteúdo que não pertencem a uma superfície com regiões. A linha horizontal fica entre blocos empilhados; com `orientation="vertical"`, ela separa itens lado a lado e herda a altura do contêiner. A linha é decorativa por padrão e fica fora da árvore de acessibilidade; use `decorative={false}` quando a divisão tiver significado. Não use Separator entre cabeçalho, corpo e rodapé de
|
|
168
|
+
'Marque a fronteira entre blocos de conteúdo que não pertencem a uma superfície com regiões. A linha horizontal fica entre blocos empilhados; com `orientation="vertical"`, ela separa itens lado a lado e herda a altura do contêiner. A linha é decorativa por padrão e fica fora da árvore de acessibilidade; use `decorative={false}` quando a divisão tiver significado. Não use Separator entre cabeçalho, corpo e rodapé de Surface, Dialog ou Drawer: nessas superfícies, os divisores são derivados das regiões com `layout="sectioned"`.',
|
|
181
169
|
},
|
|
182
170
|
skeleton: {
|
|
183
171
|
name: "skeleton",
|
|
@@ -201,7 +189,7 @@ export const componentMeta = {
|
|
|
201
189
|
name: "tabs",
|
|
202
190
|
ancestry: "shadcn",
|
|
203
191
|
whenToUse:
|
|
204
|
-
|
|
192
|
+
"Navegue entre painéis relacionados no mesmo nível. Cada TabsListItem aponta para um TabsPanel pelo mesmo `value`; TabsList usa uma linha para indicar a aba ativa, enquanto Tabs define orientação, escala, distribuição e moldura. Use ToggleGroup para escolher valores sem navegar entre painéis.",
|
|
205
193
|
},
|
|
206
194
|
textarea: {
|
|
207
195
|
name: "textarea",
|
|
@@ -285,7 +273,7 @@ export const componentMeta = {
|
|
|
285
273
|
name: "field",
|
|
286
274
|
ancestry: "shadcn",
|
|
287
275
|
whenToUse:
|
|
288
|
-
'Componha rótulo, controle, ajuda e erro com espaçamento consistente. Use a orientação vertical no caso comum e a horizontal quando controle e texto precisarem ficar lado a lado. FieldGroup organiza vários campos; quando o conjunto precisar de título, componha-o dentro de
|
|
276
|
+
'Componha rótulo, controle, ajuda e erro com espaçamento consistente. Use a orientação vertical no caso comum e a horizontal quando controle e texto precisarem ficar lado a lado. FieldGroup organiza vários campos; quando o conjunto precisar de título, componha-o dentro de Surface com `as="fieldset"`.',
|
|
289
277
|
},
|
|
290
278
|
"input-otp": {
|
|
291
279
|
name: "input-otp",
|
|
@@ -327,19 +315,19 @@ export const componentMeta = {
|
|
|
327
315
|
name: "split",
|
|
328
316
|
ancestry: "opus",
|
|
329
317
|
whenToUse:
|
|
330
|
-
"Divide uma área em panes em sequência horizontal ou vertical. Use `resizable` quando a pessoa deve ajustar a fronteira; o mesmo `<Split>` vira flex simples sem ele. Cada `<Pane>` declara
|
|
318
|
+
"Divide uma área em panes em sequência horizontal ou vertical. Use `resizable` quando a pessoa deve ajustar a fronteira; o mesmo `<Split>` vira flex simples sem ele. Cada `<Pane>` declara apenas dimensão e crescimento; o filho compõe apresentação e rolagem. SurfaceAssistant especializa esse layout para assistência contextual dentro de Page, Dialog ou Drawer.",
|
|
331
319
|
},
|
|
332
320
|
sidebar: {
|
|
333
321
|
name: "sidebar",
|
|
334
322
|
ancestry: "opus",
|
|
335
323
|
whenToUse:
|
|
336
|
-
"Organize navegação global ou contextual em uma coluna lateral. Split e Pane definem posição e largura; Sidebar fornece a
|
|
324
|
+
"Organize navegação global ou contextual em uma coluna lateral. Split e Pane definem posição e largura; Sidebar fornece a coluna e o colapso. Use SidebarNav para grupos planos e componha árvores com SidebarItem e SidebarTreeGroup; quando precisar de header, body ou footer visuais, envolva a Sidebar com Surface.",
|
|
337
325
|
},
|
|
338
326
|
pane: {
|
|
339
327
|
name: "pane",
|
|
340
328
|
ancestry: "opus",
|
|
341
329
|
whenToUse:
|
|
342
|
-
"
|
|
330
|
+
"Declare o tamanho de uma região dentro de Split. Pane cuida somente de dimensão, limites e crescimento; o filho decide superfície, organização e rolagem. Use Surface quando a região precisar de header, body, footer, borda ou elevação, e Sidebar quando ela for uma navegação lateral.",
|
|
343
331
|
},
|
|
344
332
|
"scroll-area": {
|
|
345
333
|
name: "scroll-area",
|
|
@@ -363,7 +351,7 @@ export const componentMeta = {
|
|
|
363
351
|
name: "toggle",
|
|
364
352
|
ancestry: "shadcn",
|
|
365
353
|
whenToUse:
|
|
366
|
-
'Alterne um estado diretamente no contexto atual. ToggleGroup reúne escolhas únicas ou múltiplas
|
|
354
|
+
'Alterne um estado diretamente no contexto atual. ToggleGroup reúne escolhas únicas ou múltiplas com a mesma gramática estrutural de ButtonGroup; `mode="segmented"` mantém alternativas curtas visíveis numa superfície compartilhada, enquanto `variant` trata cada Toggle. Para navegar entre painéis, use Tabs.',
|
|
367
355
|
},
|
|
368
356
|
|
|
369
357
|
confirm: {
|
|
@@ -388,13 +376,13 @@ export const componentMeta = {
|
|
|
388
376
|
name: "action-form-card",
|
|
389
377
|
ancestry: "opus",
|
|
390
378
|
whenToUse:
|
|
391
|
-
"Apresente uma FormAction como seção delimitada da página. ActionFormCard combina a estrutura
|
|
379
|
+
"Apresente uma FormAction como seção delimitada da página. ActionFormCard combina a estrutura de uma Surface elevada com o comportamento de ActionForm. Para um modal, use ActionFormDialog; sem superfície adicional, use ActionForm.",
|
|
392
380
|
},
|
|
393
381
|
"action-list": {
|
|
394
382
|
name: "action-list",
|
|
395
383
|
ancestry: "opus",
|
|
396
384
|
whenToUse:
|
|
397
|
-
"Apresente uma coleção pesquisável a partir de uma ListAction. O contrato declara colunas, filtros, período e busca; ActionList coordena visualizações, paginação, seleção em lote e sincronização com a URL. A tabela derivada não cria moldura própria. Em uma página, envolva a lista com
|
|
385
|
+
"Apresente uma coleção pesquisável a partir de uma ListAction. O contrato declara colunas, filtros, período e busca; ActionList coordena visualizações, paginação, seleção em lote e sincronização com a URL. A tabela derivada não cria moldura própria. Em uma página, envolva a lista com Surface para manter título e criação junto da coleção. Para um único recurso, use ActionView.",
|
|
398
386
|
},
|
|
399
387
|
"action-trigger": {
|
|
400
388
|
name: "action-trigger",
|
|
@@ -412,13 +400,13 @@ export const componentMeta = {
|
|
|
412
400
|
name: "page",
|
|
413
401
|
ancestry: "opus",
|
|
414
402
|
whenToUse:
|
|
415
|
-
"Estruture uma página com cabeçalho, estado e conteúdo na mesma anatomia. Page renderiza o `<main>` com um container centralizado de até 80rem (`max-w-7xl`); PageHeader reúne navegação contextual opcional, título e ações, enquanto PageBody recebe o conteúdo. PageShell pode fornecer navegação e ações conhecidas pela aplicação sem criar uma barra visual. Uma região interna pode fornecer o heading principal com
|
|
403
|
+
"Estruture uma página com cabeçalho, estado e conteúdo na mesma anatomia. Page renderiza o `<main>` com um container centralizado de até 80rem (`max-w-7xl`); PageHeader reúne navegação contextual opcional, título e ações, enquanto PageBody recebe o conteúdo. PageShell pode fornecer navegação e ações conhecidas pela aplicação sem criar uma barra visual. Uma região interna pode fornecer o heading principal com `Surface level={1}`. PageActionsTarget fica restrito a workspaces imersivos. PageState substitui o header e o conteúdo durante carregamento, falha ou ausência, por isso informações indispensáveis entram no corpo, como Alert ou texto. Para uma falha parcial, mantenha o estado na seção com DataState; para uma região disponível para criação ou vínculo, use Empty.",
|
|
416
404
|
},
|
|
417
405
|
presentation: {
|
|
418
406
|
name: "presentation",
|
|
419
407
|
ancestry: "opus",
|
|
420
408
|
whenToUse:
|
|
421
|
-
"Descreva um recurso que precisa manter a mesma anatomia ao aparecer como Page, Dialog ou Drawer. Presentation organiza navegação, título, ações de cabeçalho, body e ações de rodapé sem redefinir o conteúdo para cada superfície. Em Page de listagem,
|
|
409
|
+
"Descreva um recurso que precisa manter a mesma anatomia ao aparecer como Page, Dialog ou Drawer. Presentation organiza navegação, título, ações de cabeçalho, body e ações de rodapé sem redefinir o conteúdo para cada superfície. Em Page de listagem, Surface mantém título e ações junto do ActionList; modais usam o header da superfície. Route pode declarar URL, surface e origem do registro para deep links. A definição persistente liga esses slots a actions Opus; a invocação carrega o estado JSON da execução. PresentationInspector abre um snapshot isolado, enquanto a Lens apresenta o inventário estático projetado no manifest.",
|
|
422
410
|
},
|
|
423
411
|
router: {
|
|
424
412
|
name: "router",
|
package/src/ui/react.tsx
CHANGED
|
@@ -10,6 +10,9 @@ export * from "./drivers/react.tsx";
|
|
|
10
10
|
// Utilitário
|
|
11
11
|
export { cn } from "./lib/cn.ts";
|
|
12
12
|
|
|
13
|
+
// Personalização de aparência (ADR 0044): o mesmo módulo sem React de `./ui/appearance`.
|
|
14
|
+
export * from "./appearance.ts";
|
|
15
|
+
|
|
13
16
|
// Primitivos
|
|
14
17
|
export { Button, buttonVariants } from "./components/primitives/button.tsx";
|
|
15
18
|
export type {
|
|
@@ -90,18 +93,6 @@ export type {
|
|
|
90
93
|
DetailGroupVariant,
|
|
91
94
|
} from "./components/primitives/detail.tsx";
|
|
92
95
|
|
|
93
|
-
export {
|
|
94
|
-
Card,
|
|
95
|
-
CardHeader,
|
|
96
|
-
CardMedia,
|
|
97
|
-
CardTitle,
|
|
98
|
-
CardDescription,
|
|
99
|
-
CardAction,
|
|
100
|
-
CardBody,
|
|
101
|
-
CardContent,
|
|
102
|
-
CardFooter,
|
|
103
|
-
} from "./components/primitives/card.tsx";
|
|
104
|
-
|
|
105
96
|
export { MetricCard } from "./components/primitives/metric-card.tsx";
|
|
106
97
|
export type {
|
|
107
98
|
MetricCardProps,
|
|
@@ -136,6 +127,8 @@ export {
|
|
|
136
127
|
DialogNavigation,
|
|
137
128
|
DialogMedia,
|
|
138
129
|
DialogActions,
|
|
130
|
+
DialogIntro,
|
|
131
|
+
DialogIntroActions,
|
|
139
132
|
DialogBody,
|
|
140
133
|
DialogFooter,
|
|
141
134
|
DialogTitle,
|
|
@@ -146,7 +139,7 @@ export type {
|
|
|
146
139
|
DialogMode,
|
|
147
140
|
} from "./components/primitives/dialog.tsx";
|
|
148
141
|
|
|
149
|
-
// O pacote de anatomia que
|
|
142
|
+
// O pacote de anatomia que Surface, Dialog, Drawer e Pane declaram no root (ADR 0023). As
|
|
150
143
|
// tabelas e o contexto continuam internos; o consumidor escolhe entre os dois nomes.
|
|
151
144
|
export type { SurfaceLayout } from "./components/patterns/surface-anatomy.ts";
|
|
152
145
|
|
|
@@ -278,6 +271,8 @@ export {
|
|
|
278
271
|
export {
|
|
279
272
|
Drawer,
|
|
280
273
|
DrawerActions,
|
|
274
|
+
DrawerIntro,
|
|
275
|
+
DrawerIntroActions,
|
|
281
276
|
DrawerClose,
|
|
282
277
|
DrawerContent,
|
|
283
278
|
DrawerFooter,
|
|
@@ -372,10 +367,16 @@ export {
|
|
|
372
367
|
export { ScrollArea, ScrollBar } from "./components/primitives/scroll-area.tsx";
|
|
373
368
|
export { Slider } from "./components/primitives/slider.tsx";
|
|
374
369
|
export { Switch } from "./components/primitives/switch.tsx";
|
|
375
|
-
export {
|
|
370
|
+
export {
|
|
371
|
+
Toggle,
|
|
372
|
+
type ToggleProps,
|
|
373
|
+
toggleVariants,
|
|
374
|
+
} from "./components/primitives/toggle.tsx";
|
|
376
375
|
export {
|
|
377
376
|
ToggleGroup,
|
|
378
|
-
|
|
377
|
+
type ToggleGroupDistribution,
|
|
378
|
+
type ToggleGroupMode,
|
|
379
|
+
type ToggleGroupProps,
|
|
379
380
|
} from "./components/primitives/toggle-group.tsx";
|
|
380
381
|
export { Truncate } from "./components/primitives/truncate.tsx";
|
|
381
382
|
export type { TruncateProps } from "./components/primitives/truncate.tsx";
|
|
@@ -482,26 +483,30 @@ export type {
|
|
|
482
483
|
PageStateStatus,
|
|
483
484
|
} from "./components/patterns/page-state.tsx";
|
|
484
485
|
|
|
485
|
-
//
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
486
|
+
// Superfície: região de página, grupo de campos, entidade, item ou bloco clicável. A
|
|
487
|
+
// semântica vem de `as`/`asChild`; forma curta e slots compartilham a anatomia (ADR 0045).
|
|
488
|
+
export {
|
|
489
|
+
Surface,
|
|
490
|
+
SurfaceHeader,
|
|
491
|
+
SurfaceMedia,
|
|
492
|
+
SurfaceTitle,
|
|
493
|
+
SurfaceDescription,
|
|
494
|
+
SurfaceMeta,
|
|
495
|
+
SurfaceActions,
|
|
496
|
+
SurfaceBody,
|
|
497
|
+
SurfaceFooter,
|
|
498
|
+
} from "./components/patterns/surface.tsx";
|
|
496
499
|
export type {
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
500
|
+
SurfaceProps,
|
|
501
|
+
SurfaceHeaderProps,
|
|
502
|
+
SurfaceMediaProps,
|
|
503
|
+
SurfaceBodyProps,
|
|
504
|
+
SurfaceElement,
|
|
505
|
+
SurfaceElevation,
|
|
506
|
+
} from "./components/patterns/surface.tsx";
|
|
507
|
+
export type { HeadingLevel } from "./components/patterns/heading-level.ts";
|
|
508
|
+
|
|
509
|
+
// Layout composicional: Split decide a relação espacial; Pane declara somente dimensão.
|
|
505
510
|
export { Split, Pane } from "./components/patterns/split.tsx";
|
|
506
511
|
export type {
|
|
507
512
|
SplitProps,
|
|
@@ -529,16 +534,8 @@ export type {
|
|
|
529
534
|
SurfaceStatusContext,
|
|
530
535
|
} from "./components/patterns/dock.tsx";
|
|
531
536
|
|
|
532
|
-
// Barra lateral composicional
|
|
537
|
+
// Barra lateral composicional e navegação, sem possuir o layout.
|
|
533
538
|
export {
|
|
534
|
-
PaneActions,
|
|
535
|
-
PaneDescription,
|
|
536
|
-
PaneHeader,
|
|
537
|
-
PaneMedia,
|
|
538
|
-
PaneTitle,
|
|
539
|
-
PaneBody,
|
|
540
|
-
PaneContent,
|
|
541
|
-
PaneFooter,
|
|
542
539
|
Sidebar,
|
|
543
540
|
SidebarItem,
|
|
544
541
|
SidebarGroupLabel,
|