@softize/opus 30.0.0 → 31.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +116 -0
- package/bin/lib/check.mjs +109 -101
- package/bin/lib/copy.mjs +2970 -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/README.md +4 -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 +1 -0
- package/src/ui/components/patterns/form.tsx +2 -0
- package/src/ui/components/patterns/grouped-list.ts +2 -2
- package/src/ui/components/patterns/list.tsx +572 -358
- 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/close-button.tsx +11 -3
- package/src/ui/components/primitives/command.tsx +2 -8
- 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 +2 -1
- package/src/ui/docs/content/action-list.md +134 -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/command.md +62 -50
- package/src/ui/docs/content/compositions.md +129 -459
- 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/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/drivers/context.tsx +11 -4
- package/src/ui/drivers/react.tsx +27 -7
- package/src/ui/meta.ts +5 -5
- package/src/ui/react.tsx +34 -8
- package/src/ui/theme.css +44 -33
|
@@ -22,8 +22,8 @@ A barra distribui os controles `inline` em mais de uma linha quando necessário,
|
|
|
22
22
|
ordem. Ela não move filtros automaticamente para o modal. Seletores de valor único acompanham o
|
|
23
23
|
valor escolhido até `20rem` e truncam o excedente; a busca varia entre `8rem` e `16rem`.
|
|
24
24
|
Declare como `advanced` os filtros que não precisam ficar sempre à vista, como descreve a seção
|
|
25
|
-
“Onde cada filtro aparece”.
|
|
26
|
-
`toolbarActions` acrescenta, depois deles,
|
|
25
|
+
“Onde cada filtro aparece”. As opções da lista e os filtros avançados formam um `ButtonGroup` espaçado;
|
|
26
|
+
`toolbarActions` acrescenta, depois deles, ações da coleção, como criar, importar e exportar.
|
|
27
27
|
|
|
28
28
|
```tsx preview col
|
|
29
29
|
render(
|
|
@@ -41,24 +41,30 @@ render(
|
|
|
41
41
|
|
|
42
42
|
## Coleção nomeada
|
|
43
43
|
|
|
44
|
-
Em uma página,
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
Em uma página, use [`Page`](/ui/page) para o título e ações gerais. Ações da coleção
|
|
45
|
+
ficam na barra do `ActionList`, inclusive a criação, mesmo sem depender dos filtros atuais.
|
|
46
|
+
Em abas, a barra acompanha a lista do painel ativo.
|
|
47
47
|
|
|
48
48
|
```tsx
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
>
|
|
55
|
-
|
|
56
|
-
</
|
|
49
|
+
<Page title="Workspaces" layout="fill">
|
|
50
|
+
<ActionList
|
|
51
|
+
action={workspaceList}
|
|
52
|
+
input={{}}
|
|
53
|
+
toolbarActions={
|
|
54
|
+
<Button aria-label="Criar workspace" onClick={openCreate}>
|
|
55
|
+
Criar
|
|
56
|
+
</Button>
|
|
57
|
+
}
|
|
58
|
+
/>
|
|
59
|
+
</Page>
|
|
57
60
|
```
|
|
58
61
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
O botão exibe “Criar”; seu nome acessível e o formulário identificam o recurso.
|
|
63
|
+
Menu com vários tipos de criação preserva os nomes específicos. Operações sobre a seleção
|
|
64
|
+
usam `batchActions`, e ações de um registro usam `rowActions`.
|
|
65
|
+
|
|
66
|
+
`toolbarActions` recebe os nós já prontos e aparece também em visualizações sem filtros
|
|
67
|
+
ou tabela. Em uma ação somente com ícone, forneça `aria-label` e tooltip.
|
|
62
68
|
|
|
63
69
|
## Barra de filtros compartilhada
|
|
64
70
|
|
|
@@ -228,7 +234,7 @@ Declare `grouping.fields` quando uma dimensão enumerável puder organizar a tab
|
|
|
228
234
|
recorte de negócio. Cada campo precisa ser um filtro `select` ou `lookup`; texto, número e data não
|
|
229
235
|
são dimensões de agrupamento. O filtro pode aceitar uma ou várias opções: cada consulta de grupo
|
|
230
236
|
envia um único valor na forma declarada. A lista continua plana por padrão, e a pessoa escolhe
|
|
231
|
-
**Agrupar por** em **
|
|
237
|
+
**Agrupar por** em **Opções da lista**.
|
|
232
238
|
|
|
233
239
|
```ts
|
|
234
240
|
filters: {
|
|
@@ -261,9 +267,17 @@ aplicados à mesma dimensão restringem os grupos exibidos.
|
|
|
261
267
|
|
|
262
268
|
## Paginação e carregamento
|
|
263
269
|
|
|
264
|
-
|
|
270
|
+
Para coleções pequenas que devem aparecer por inteiro, declare `paginate: false` no
|
|
271
|
+
contrato da list action. ActionList omite `page` e `limit` da consulta, do estado lido
|
|
272
|
+
da URL e dos links gerados; não exibe rodapé nem seletor de quantidade. O handler deve
|
|
273
|
+
devolver todos os itens que atendem à busca e aos filtros. O componente não busca páginas
|
|
274
|
+
adicionais em segundo plano nem aumenta o limite artificialmente. A opção também é
|
|
275
|
+
respeitada pelas listas renderizadas por Presentation, sem configuração visual duplicada.
|
|
276
|
+
|
|
277
|
+
Nos demais modos, `ActionList` envia `limit`, definido por `pageSize`, e `page` no input. O handler aplica o recorte e
|
|
265
278
|
devolve `total` na resposta paginada. Quando existe total, o rodapé mostra a página atual, os links
|
|
266
|
-
disponíveis e a quantidade de itens.
|
|
279
|
+
disponíveis e a quantidade de itens. Com total zero, o rodapé e seu divisor não aparecem:
|
|
280
|
+
a mensagem de vazio permanece como indicação do resultado. Alterar busca, filtro, ordenação ou período retorna à primeira
|
|
267
281
|
página. Durante a primeira consulta, `DataState` apresenta o carregamento; em atualizações
|
|
268
282
|
posteriores, a lista permanece visível com `aria-busy`.
|
|
269
283
|
|
|
@@ -279,20 +293,8 @@ rodapé podem continuar visíveis enquanto só os resultados rolam. Para isso, d
|
|
|
279
293
|
render(
|
|
280
294
|
<DocBrowserActionProvider>
|
|
281
295
|
<div className="h-80 w-full overflow-x-auto overflow-y-hidden rounded-lg border border-border">
|
|
282
|
-
<Page layout="fill">
|
|
283
|
-
<
|
|
284
|
-
<Surface as="section" level={1}>
|
|
285
|
-
<SurfaceHeader>
|
|
286
|
-
<SurfaceTitle>Workspaces</SurfaceTitle>
|
|
287
|
-
<SurfaceActions>
|
|
288
|
-
<Button>Criar workspace</Button>
|
|
289
|
-
</SurfaceActions>
|
|
290
|
-
</SurfaceHeader>
|
|
291
|
-
<SurfaceBody>
|
|
292
|
-
<ActionList action={docWorkspaceList} input={{}} />
|
|
293
|
-
</SurfaceBody>
|
|
294
|
-
</Surface>
|
|
295
|
-
</PageBody>
|
|
296
|
+
<Page title="Workspaces" layout="fill">
|
|
297
|
+
<ActionList action={docWorkspaceList} input={{}} toolbarActions={<Button aria-label="Criar workspace">Criar</Button>} />
|
|
296
298
|
</Page>
|
|
297
299
|
</div>
|
|
298
300
|
</DocBrowserActionProvider>,
|
|
@@ -319,8 +321,8 @@ componentes no caminho. Nos demais casos, a decisão é sua:
|
|
|
319
321
|
|
|
320
322
|
- Para a lista manter a altura dos resultados, como em uma seção secundária cuja rolagem pertence ao
|
|
321
323
|
`PageBody`, declare `layout="flow"`.
|
|
322
|
-
-
|
|
323
|
-
|
|
324
|
+
- `TabsPanel` repassa a altura disponível à lista. Um contêiner próprio sem essa integração
|
|
325
|
+
interrompe a herança: declare `layout="fill"` na lista e dê ao contêiner as classes
|
|
324
326
|
`flex min-h-0 flex-1 flex-col`.
|
|
325
327
|
- Dentro de [`Surface`](/ui/surface), [`Dialog`](/ui/dialog), [`Drawer`](/ui/drawer) ou
|
|
326
328
|
[`Pane`](/ui/pane), a lista não herda o `fill` da página: a altura do corpo pertence à
|
|
@@ -442,13 +444,17 @@ filters: {
|
|
|
442
444
|
|
|
443
445
|
## Exibição e estado na URL
|
|
444
446
|
|
|
445
|
-
O botão
|
|
447
|
+
O botão **Opções da lista** reúne as preferências disponíveis para a visualização. Na tabela, permite
|
|
446
448
|
escolher a ordenação, inverter sua direção, agrupar e mostrar ou ocultar colunas, inclusive as
|
|
447
|
-
declaradas com `hidden`;
|
|
448
|
-
página. Um ponto sinaliza quando alguma preferência diverge do padrão. O rodapé explicita a
|
|
449
|
+
declaradas com `hidden`; nas listas paginadas, permite alterar a quantidade de itens por
|
|
450
|
+
página. Quando não há preferências disponíveis, o botão não aparece. Um ponto sinaliza quando alguma preferência diverge do padrão. O rodapé explicita a
|
|
449
451
|
ordenação e o agrupamento ativos junto da paginação e do total. Busca, ordenação, filtros,
|
|
450
452
|
visualização, colunas e limite podem ser serializados na query string pelos helpers do componente:
|
|
451
453
|
|
|
454
|
+
Operações usam `invalidates` para atualizar os dados, e o consumidor pode manter suas
|
|
455
|
+
assinaturas de eventos. Em caso de falha, o estado de erro oferece **Tentar novamente**
|
|
456
|
+
diretamente. Não há comando de recarga manual no menu nem polling automático no ActionList.
|
|
457
|
+
|
|
452
458
|
Cada campo de `sort.fields` precisa de uma coluna com rótulo textual para aparecer no seletor e no
|
|
453
459
|
resumo do rodapé; a coluna pode estar `hidden`. Campos sem coluna continuam válidos para o handler e
|
|
454
460
|
para uma ordenação padrão, mas o Opus não expõe seu identificador técnico na interface. **Sem
|
|
@@ -468,9 +474,55 @@ restaurá-lo.
|
|
|
468
474
|
|
|
469
475
|
Convenção compacta (defaults omitidos): `?q=…&sort=key:dir&status=…&view=board&cols=a,b,c&limit=25`.
|
|
470
476
|
|
|
477
|
+
## Itens conectados
|
|
478
|
+
|
|
479
|
+
Para coleções que apresentam um nome, uma descrição e ações por registro, declare os campos
|
|
480
|
+
em `item`. O ActionList monta a moldura e os separadores com ItemGroup; mantém carregamento,
|
|
481
|
+
erro, recuperação e vazio. `title` coloca o nome da coleção junto das `toolbarActions`.
|
|
482
|
+
Nome e descrição ocupam uma linha cada, com reticências quando ultrapassam a largura disponível.
|
|
483
|
+
|
|
484
|
+
```tsx preview col
|
|
485
|
+
render(
|
|
486
|
+
<DocBrowserActionProvider>
|
|
487
|
+
<ActionList
|
|
488
|
+
action={docWorkspaceList}
|
|
489
|
+
input={{}}
|
|
490
|
+
title="Workspaces"
|
|
491
|
+
item={{ title: "name", description: "client" }}
|
|
492
|
+
/>
|
|
493
|
+
</DocBrowserActionProvider>
|
|
494
|
+
);
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
Os nomes em `item` são campos diretos do resultado, com valores textuais ou numéricos.
|
|
498
|
+
O objeto é serializável. `rowActions` recebe o registro e um contexto com `items`, `total`,
|
|
499
|
+
`isFetching`, `isError` e `refetch`; `toolbarActions` também pode ser uma função desse contexto.
|
|
500
|
+
O modo de itens não combina `children`, `views` ou seleção em lote. `onRowClick` continua
|
|
501
|
+
restrito à tabela; ações dos itens ficam nos controles explícitos de `rowActions`.
|
|
502
|
+
|
|
503
|
+
Com uma página, esse modo dispensa o rodapé. Com mais resultados, mantém a paginação.
|
|
504
|
+
Depois de remover o último item de uma página, volta à última página válida. A tabela conserva
|
|
505
|
+
seu rodapé e seus controles existentes.
|
|
506
|
+
|
|
507
|
+
### Fonte governada por outro serviço
|
|
508
|
+
|
|
509
|
+
Quando a coleção pertence a uma integração que já possui cliente e autorização, `source`
|
|
510
|
+
conecta esse cliente sem criar uma action artificial. Declare uma chave com o escopo de acesso
|
|
511
|
+
e um `load(input, { signal })` que retorna `{ items, total, cursor }`. A fonte deve respeitar
|
|
512
|
+
`page` e `limit`; se o serviço retorna todos os registros, o adapter pagina o conjunto completo.
|
|
513
|
+
|
|
514
|
+
A fonte substitui `action`, exige QueryClientProvider e dispensa OpusProvider quando não há
|
|
515
|
+
actions nos controles. Seu cache é separado das actions, não reaproveita dados entre escopos e
|
|
516
|
+
é descartado após a desmontagem. Falhas usam a mensagem pública `errorMessage` e oferecem
|
|
517
|
+
recuperação; detalhes técnicos do erro não são exibidos. Dados sensíveis usados pelo cliente
|
|
518
|
+
externo devem permanecer no adapter, fora dos itens retornados.
|
|
519
|
+
|
|
520
|
+
`source` é runtime: seu loader não entra no JSON. Uma definição serializável futura deverá
|
|
521
|
+
referenciar uma fonte registrada, enquanto `item` já descreve a apresentação sem JSX.
|
|
522
|
+
|
|
471
523
|
## Composição dos itens
|
|
472
524
|
|
|
473
|
-
|
|
525
|
+
Quando `item` não representar a composição necessária, passe `children` para substituir a tabela por uma composição própria, como uma lista de
|
|
474
526
|
[`Item`](/ui/item). A barra de filtros e os estados de carregamento, erro e vazio continuam sendo
|
|
475
527
|
tratados por `ActionList`. O contrato não leva o tipo do item até o componente: anote o parâmetro de
|
|
476
528
|
`children` (ou de `render`, em uma visualização) ou declare os genéricos, como em
|
|
@@ -564,32 +616,46 @@ para fora de `toolbarActions`.
|
|
|
564
616
|
|
|
565
617
|
## Propriedades de ActionList
|
|
566
618
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
|
570
|
-
|
|
|
571
|
-
| `
|
|
572
|
-
| `
|
|
573
|
-
| `
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
|
577
|
-
|
|
|
578
|
-
| `
|
|
579
|
-
| `
|
|
580
|
-
| `
|
|
581
|
-
| `
|
|
582
|
-
| `
|
|
583
|
-
| `
|
|
584
|
-
| `
|
|
585
|
-
| `
|
|
586
|
-
| `
|
|
587
|
-
| `
|
|
588
|
-
| `
|
|
589
|
-
| `
|
|
590
|
-
| `
|
|
591
|
-
| `
|
|
592
|
-
| `
|
|
593
|
-
| `
|
|
594
|
-
| `
|
|
595
|
-
| `
|
|
619
|
+
`action` e `source` são alternativas mutuamente exclusivas.
|
|
620
|
+
|
|
621
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
622
|
+
| --- | --- | --- | --- |
|
|
623
|
+
| `source` | `ListDataSource<TItem>` | — | Fonte externa com `key` e `load`; substitui a action. |
|
|
624
|
+
| `title` | `string` | — | Título da coleção, ao lado das ações. |
|
|
625
|
+
| `item` | `ActionListItemSpec` | — | Campos `title` e `description?` da apresentação em itens. |
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
629
|
+
| ----------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
630
|
+
| `action` | `ListActionLike` | | A ListAction do Opus (kind list, output = item). A paginação envia `limit`/`page` e usa o `total` devolvido. |
|
|
631
|
+
| `input` | `TInput` | | O escopo base, como `{ workspaceId }`. A toolbar acrescenta busca, filtros e paginação sem sobrescrever essas chaves. |
|
|
632
|
+
| `layout` | `'flow' \| 'fill'` | `'fill'` como filha direta de `PageBody`, `SurfaceBody` ou do corpo da `Presentation` em uma página `fill`; `'flow'` nos demais casos | Em `fill`, ocupa a altura de um ancestral limitado e rola somente a região de resultados; na tabela, o cabeçalho fica fixo. Sem ancestral limitado, equivale a `flow`. |
|
|
633
|
+
| `cells` | `Record<string, (item) => ReactNode>` | | Células custom por cima das colunas do contrato (chave = column.key). |
|
|
634
|
+
| `filterOptions` | `Record<string, SelectOption[]>` | | Opções de runtime para filtros select/lookup. Em uma dimensão de agrupamento, a coleção precisa ser completa e ter de 1 a 12 itens. |
|
|
635
|
+
| `filterDefaults` | `Record<string, string>` | | Valores de repouso aplicados à consulta; o `X` só aparece quando o filtro diverge deles e retorna a eles. |
|
|
636
|
+
| `filterIcons` | `Record<string, ReactNode>` | | Ícones leading dos filtros, indexados pelo nome declarado no contrato. |
|
|
637
|
+
| `advancedFilters` | `{ columns?: 1 \| 2 \| 3; sectionIcons?: Record<string, ReactNode>; sectionVariant?: 'plain' \| 'framed' }` | `{ columns: 1, sectionVariant: 'plain' }` | Define as colunas, os ícones e o tratamento dos grupos; o Opus deriva a largura correspondente do diálogo. |
|
|
638
|
+
| `periodPosition` | `'before' \| 'after' \| { afterFilter: string }` | `'before'` | Posiciona o período antes, depois ou imediatamente após um filtro inline. |
|
|
639
|
+
| `period` | `{ basisFilter: string }` | | Reúne o período e o filtro inline indicado em um único controle. |
|
|
640
|
+
| `views` | `Record<string, ActionListView<TItem>>` | | Visualizações alternativas `{ label, icon?, render }`; o seletor alterna entre a tabela e estas. |
|
|
641
|
+
| `beforeContent` | `ReactNode \| (input: TInput) => ReactNode` | | Conteúdo entre a toolbar e o corpo; a função recebe o mesmo input efetivo da consulta, para resumos que acompanham o recorte. |
|
|
642
|
+
| `columns` | `ActionListColumn<TItem>[]` | | Tabela explícita, que substitui as colunas declaradas no contrato. |
|
|
643
|
+
| `children` | `(items, refetch) => ReactNode` | | Modo composição: layout livre; a toolbar segue. Tem precedência sobre columns. |
|
|
644
|
+
| `batch` | `ActionListBatchAction[]` | | Ações em lote: `{ label, can?, run, confirm?: { title, message? }, destructive? }` — liga a multi-seleção. |
|
|
645
|
+
| `rowId` | `(item) => string` | `item.id` | Identidade da linha para seleção. |
|
|
646
|
+
| `pageSize` | `number` | `50` | Itens por página padrão (vira `limit`/`page` no input; handler devolve `total`). O usuário troca no popover de exibição. |
|
|
647
|
+
| `state / onStateChange` | `ActionListState / (next) => void` | interno | Estado da toolbar controlado — para quem embala sincronizar com a URL. |
|
|
648
|
+
| `empty` | `(items) => boolean` | `items.length === 0` | Sobrepõe o vazio derivado, por exemplo quando um formulário inline aberto conta como conteúdo. |
|
|
649
|
+
| `loading` | `boolean` | | Carga extra agregada à da consulta, como uma query irmã de que os `children` dependem. |
|
|
650
|
+
| `emptyMessage` | `string` | `'Nenhum resultado.'` | Frase do estado vazio (o `Empty` do `DataState`). |
|
|
651
|
+
| `errorMessage` | `string` | `'Não foi possível carregar.'` | Título do aviso de erro; a ação de tentar de novo refaz a consulta. |
|
|
652
|
+
| `retryLabel` | `string` | `'Tentar de novo'` | Nome acessível e tooltip da ação de recuperação. |
|
|
653
|
+
| `onRowClick` | `(item: TItem) => void` | | Clique na linha (ex.: navegar para o detalhe) — só na tabela. |
|
|
654
|
+
| `viewControls` | `ReactNode` | | Controles da visualização ativa, imediatamente após o seletor de visualização. |
|
|
655
|
+
| `toolbarActions` | `ReactNode \| ((context) => ReactNode)` | | Ações da coleção, incluindo criação, junto ao título quando declarado ou no fim da barra. Os nós são renderizados como recebidos: nome acessível e tooltip de uma ação somente com ícone ficam com o consumidor. |
|
|
656
|
+
| `rowActions` | `(item: TItem, context) => ReactNode` | | Ações por registro, na tabela ou à direita dos itens. Na tabela, a partir de duas, entram em um grupo com intervalo compacto; uma só fica solta, sem grupo. Cliques ali não disparam o `onRowClick`. |
|
|
657
|
+
|
|
658
|
+
Para carregar um detalhe a partir do mesmo recorte da coleção, use
|
|
659
|
+
`listStateToInput(state, action, { input, filterDefaults, pageSize })`. O helper materializa
|
|
660
|
+
busca, filtros, período, ordenação e paginação com a mesma regra usada pelo ActionList.
|
|
661
|
+
`input` transporta o escopo fixo; `filterDefaults` preenche filtros que não vieram no estado.
|
|
@@ -103,6 +103,11 @@ um atalho, um arrastar, um item de menu.
|
|
|
103
103
|
| `disabled` | `boolean` | `false` | Desabilita o botão independentemente da execução em andamento. |
|
|
104
104
|
| `onSuccess` | `(data: TData) => void` | | Pós-sucesso (cache já invalidado pelo action.invalidates). |
|
|
105
105
|
| `onLoadingChange` | `(loading: boolean) => void` | | Informa início e fim da execução a quem coordena bloqueio entre várias actions. |
|
|
106
|
+
| `aria-label` | `string` | | Nome acessível completo quando o texto visível é abreviado. |
|
|
106
107
|
| `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. |
|
|
107
108
|
| `itemLabel` | `string` | | Nome do alvo na pergunta (sai entre aspas, em destaque, antes da mensagem do contrato). |
|
|
108
109
|
| `className` | `string` | | Classes do botão. O tamanho vem de `size` (escala única); com `icon`, o default é `icon-xs`. |
|
|
110
|
+
|
|
111
|
+
Quando `label` abrevia o texto visível, forneça `aria-label` com o nome completo da operação.
|
|
112
|
+
O nome acessível deve conter o texto visível; por exemplo, “Criar” e “Criar cliente”.
|
|
113
|
+
Presentation faz essa associação ao usar um rótulo contextual no comando.
|
|
@@ -32,8 +32,8 @@ há texto visível. O glifo dentro do controle acompanha o tamanho (0.875rem em
|
|
|
32
32
|
| Nome | Medida | Uso |
|
|
33
33
|
| --------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
34
34
|
| `xs` | 1.5rem | Ação dentro de um campo (`InputGroupButton`). |
|
|
35
|
-
| `sm` | 2rem |
|
|
36
|
-
| `default` | 2.25rem |
|
|
35
|
+
| `sm` | 2rem | Criação de coleções e operações densas de toolbar ou seção. |
|
|
36
|
+
| `default` | 2.25rem | Headers, footers de Dialog e Drawer e controles comuns; é também a linha de `Input`. |
|
|
37
37
|
| `lg` | 2.5rem | Chamada principal com mais área de toque. |
|
|
38
38
|
| `icon-xs` | 1.5rem | Ação só de ícone dentro de um campo ou de uma linha densa; é o quadrado de `ActionTrigger` com `icon`. |
|
|
39
39
|
| `icon-sm` | 2rem | 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`. |
|
|
@@ -41,15 +41,14 @@ há texto visível. O glifo dentro do controle acompanha o tamanho (0.875rem em
|
|
|
41
41
|
| `icon-lg` | 2.5rem | Ação só de ícone ao lado de um `lg`. |
|
|
42
42
|
|
|
43
43
|
Escolha o tamanho pela região, não pela importância visual: `variant` e `context` resolvem a
|
|
44
|
-
hierarquia da ação. Headers de Page, Dialog, Drawer e Surface usam `
|
|
44
|
+
hierarquia da ação. Headers de Page, Dialog, Drawer e Surface usam `default`/`icon`. A criação
|
|
45
45
|
no cabeçalho de uma coleção usa `sm` textual, sem ícone. Footers de
|
|
46
46
|
[`Dialog`](/ui/dialog) e [`Drawer`](/ui/drawer) conservam `default`. Operações densas de toolbar ou de seção usam `sm`;
|
|
47
47
|
ações dentro de linha ou célula usam `xs` ou `icon-xs`. Assim a mesma decisão mantém a mesma altura
|
|
48
48
|
mesmo quando uma superfície troca uma ação secundária por uma primária.
|
|
49
49
|
|
|
50
|
-
O retorno de `PageBack` usa `icon
|
|
51
|
-
(`shape="pill"`), `neutral` e `subtle`, no quadrado `icon-
|
|
52
|
-
`closeSize="xs"`.
|
|
50
|
+
O retorno de `PageBack` usa `icon`. O fechamento de Dialog e Drawer é um `CloseButton` circular
|
|
51
|
+
(`shape="pill"`), `neutral` e `subtle`, no quadrado `icon-xs` (`closeSize="xs"`) por padrão.
|
|
53
52
|
|
|
54
53
|
```tsx preview
|
|
55
54
|
<Button size="xs">Mínimo</Button>
|
|
@@ -11,13 +11,21 @@ escolher um valor em um formulário, use [`Select`](/ui/select).
|
|
|
11
11
|
<CommandList>
|
|
12
12
|
<CommandEmpty>Nada encontrado.</CommandEmpty>
|
|
13
13
|
<CommandGroup heading="Sessões">
|
|
14
|
-
<CommandItem
|
|
15
|
-
|
|
14
|
+
<CommandItem>
|
|
15
|
+
<FolderGit2 /> Onboarding do faturamento
|
|
16
|
+
</CommandItem>
|
|
17
|
+
<CommandItem>
|
|
18
|
+
<FolderGit2 /> Integração com o ERP
|
|
19
|
+
</CommandItem>
|
|
16
20
|
</CommandGroup>
|
|
17
21
|
<CommandSeparator />
|
|
18
22
|
<CommandGroup heading="Ações">
|
|
19
|
-
<CommandItem
|
|
20
|
-
|
|
23
|
+
<CommandItem>
|
|
24
|
+
<Plus /> Criar sessão <CommandShortcut>⌘N</CommandShortcut>
|
|
25
|
+
</CommandItem>
|
|
26
|
+
<CommandItem>
|
|
27
|
+
<Play /> Iniciar ambiente
|
|
28
|
+
</CommandItem>
|
|
21
29
|
</CommandGroup>
|
|
22
30
|
</CommandList>
|
|
23
31
|
</Command>
|
|
@@ -26,23 +34,23 @@ escolher um valor em um formulário, use [`Select`](/ui/select).
|
|
|
26
34
|
## Paleta de comandos em modal
|
|
27
35
|
|
|
28
36
|
`CommandDialog` apresenta a mesma lista dentro de um [`Dialog`](/ui/dialog), com um cabeçalho
|
|
29
|
-
|
|
37
|
+
padrão que mostra o título e o botão de fechar. A descrição fica disponível somente para
|
|
30
38
|
tecnologias assistivas. O componente não registra atalho de teclado: para abrir a paleta com
|
|
31
39
|
⌘K, o aplicativo escuta o evento e altera `open`, como no exemplo.
|
|
32
40
|
|
|
33
41
|
```tsx preview
|
|
34
|
-
const [open, setOpen] = useState(false)
|
|
42
|
+
const [open, setOpen] = useState(false);
|
|
35
43
|
|
|
36
44
|
useEffect(() => {
|
|
37
45
|
const onKeyDown = (event: KeyboardEvent): void => {
|
|
38
|
-
if (event.key.toLowerCase() ===
|
|
39
|
-
event.preventDefault()
|
|
40
|
-
setOpen((current) => !current)
|
|
46
|
+
if (event.key.toLowerCase() === "k" && (event.metaKey || event.ctrlKey)) {
|
|
47
|
+
event.preventDefault();
|
|
48
|
+
setOpen((current) => !current);
|
|
41
49
|
}
|
|
42
|
-
}
|
|
43
|
-
document.addEventListener(
|
|
44
|
-
return () => document.removeEventListener(
|
|
45
|
-
}, [])
|
|
50
|
+
};
|
|
51
|
+
document.addEventListener("keydown", onKeyDown);
|
|
52
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
53
|
+
}, []);
|
|
46
54
|
|
|
47
55
|
render(
|
|
48
56
|
<>
|
|
@@ -54,63 +62,67 @@ render(
|
|
|
54
62
|
<CommandList>
|
|
55
63
|
<CommandEmpty>Nada encontrado.</CommandEmpty>
|
|
56
64
|
<CommandGroup heading="IA">
|
|
57
|
-
<CommandItem onSelect={() => setOpen(false)}
|
|
58
|
-
|
|
65
|
+
<CommandItem onSelect={() => setOpen(false)}>
|
|
66
|
+
<Bot /> Chamar agente
|
|
67
|
+
</CommandItem>
|
|
68
|
+
<CommandItem onSelect={() => setOpen(false)}>
|
|
69
|
+
<Sparkles /> Importar skill
|
|
70
|
+
</CommandItem>
|
|
59
71
|
</CommandGroup>
|
|
60
72
|
</CommandList>
|
|
61
73
|
</CommandDialog>
|
|
62
74
|
</>,
|
|
63
|
-
)
|
|
75
|
+
);
|
|
64
76
|
```
|
|
65
77
|
|
|
66
78
|
## Propriedades de Command
|
|
67
79
|
|
|
68
|
-
| Propriedade
|
|
69
|
-
|
|
70
|
-
| `shouldFilter`
|
|
71
|
-
| `filter`
|
|
72
|
-
| `value`
|
|
73
|
-
| `onValueChange` | `(value: string) => void`
|
|
74
|
-
| `loop`
|
|
75
|
-
| `label`
|
|
76
|
-
| `className`
|
|
80
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
81
|
+
| --------------- | ---------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
82
|
+
| `shouldFilter` | `boolean` | `true` | Com `false`, desliga a filtragem e a ordenação automáticas; o aplicativo passa a renderizar somente os itens que correspondem à busca. |
|
|
83
|
+
| `filter` | `(value: string, search: string, keywords?: string[]) => number` | | Pontua cada item para a busca atual, de `0` (oculto) a `1` (melhor resultado). |
|
|
84
|
+
| `value` | `string` | | Item destacado no modo controlado. |
|
|
85
|
+
| `onValueChange` | `(value: string) => void` | | Chamado quando o item destacado muda. |
|
|
86
|
+
| `loop` | `boolean` | `false` | Faz as setas voltarem ao início ou ao fim da lista. |
|
|
87
|
+
| `label` | `string` | | Nome acessível do menu, sem exibição visual. |
|
|
88
|
+
| `className` | `string` | | Classes adicionais aplicadas à raiz. |
|
|
77
89
|
|
|
78
90
|
## Propriedades de CommandInput
|
|
79
91
|
|
|
80
|
-
| Propriedade
|
|
81
|
-
|
|
82
|
-
| `placeholder`
|
|
83
|
-
| `value`
|
|
84
|
-
| `onValueChange` | `(search: string) => void` |
|
|
85
|
-
| `disabled`
|
|
86
|
-
| `className`
|
|
92
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
93
|
+
| --------------- | -------------------------- | ------- | ------------------------------------------------------------------------ |
|
|
94
|
+
| `placeholder` | `string` | | Texto exibido enquanto a busca está vazia. |
|
|
95
|
+
| `value` | `string` | | Texto da busca no modo controlado. |
|
|
96
|
+
| `onValueChange` | `(search: string) => void` | | Chamado quando o texto da busca muda. |
|
|
97
|
+
| `disabled` | `boolean` | `false` | Desabilita o campo de busca. |
|
|
98
|
+
| `className` | `string` | | Classes adicionais aplicadas ao campo; o ícone de busca fica no wrapper. |
|
|
87
99
|
|
|
88
100
|
## Propriedades de CommandDialog
|
|
89
101
|
|
|
90
|
-
| Propriedade
|
|
91
|
-
|
|
92
|
-
| `open`
|
|
93
|
-
| `onOpenChange`
|
|
94
|
-
| `title`
|
|
95
|
-
| `description`
|
|
96
|
-
| `showCloseButton` | `boolean`
|
|
97
|
-
| `className`
|
|
102
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
103
|
+
| ----------------- | ------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------- |
|
|
104
|
+
| `open` | `boolean` | | Estado do modal no modo controlado. |
|
|
105
|
+
| `onOpenChange` | `(open: boolean) => void` | | Atualiza o estado do modal; pode ser conectado ao atalho do aplicativo. |
|
|
106
|
+
| `title` | `string` | `'Paleta de comandos'` | Título exibido no header padrão; também nomeia o diálogo para tecnologias assistivas. |
|
|
107
|
+
| `description` | `string` | `'Busque um comando para executar…'` | Descrição disponível somente para tecnologias assistivas. |
|
|
108
|
+
| `showCloseButton` | `boolean` | `true` | Exibe o botão de fechamento. |
|
|
109
|
+
| `className` | `string` | | Classes do conteúdo do diálogo, como a largura. |
|
|
98
110
|
|
|
99
111
|
## Propriedades de CommandItem
|
|
100
112
|
|
|
101
|
-
| Propriedade | Tipo
|
|
102
|
-
|
|
103
|
-
| `onSelect`
|
|
104
|
-
| `value`
|
|
105
|
-
| `keywords`
|
|
106
|
-
| `disabled`
|
|
113
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
114
|
+
| ----------- | ------------------------- | ------- | ----------------------------------------------------------------------------------------- |
|
|
115
|
+
| `onSelect` | `(value: string) => void` | | Chamado ao selecionar o item por clique ou teclado. |
|
|
116
|
+
| `value` | `string` | | Valor estável usado na busca e no destaque. Sem ele, o valor é inferido do texto do item. |
|
|
117
|
+
| `keywords` | `string[]` | | Termos adicionais considerados na busca. |
|
|
118
|
+
| `disabled` | `boolean` | `false` | Impede a seleção do item. |
|
|
107
119
|
|
|
108
120
|
## Propriedades de CommandGroup
|
|
109
121
|
|
|
110
|
-
| Propriedade | Tipo
|
|
111
|
-
|
|
112
|
-
| `heading`
|
|
113
|
-
| `value`
|
|
122
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
123
|
+
| ----------- | ----------------- | ------ | -------------------------------------------------------------------- |
|
|
124
|
+
| `heading` | `React.ReactNode` | | Título exibido acima dos itens do grupo. |
|
|
125
|
+
| `value` | `string` | | Identificador do grupo; obrigatório e único quando não há `heading`. |
|
|
114
126
|
|
|
115
127
|
`CommandList` limita a altura a `18.75rem` e rola o excedente; `CommandEmpty` aparece somente quando
|
|
116
128
|
nenhum item corresponde à busca; `CommandSeparator` divide grupos; e `CommandShortcut` mostra, à
|