@softize/opus 18.0.1 → 18.1.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.
Files changed (129) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/PROMOTED.md +4 -5
  3. package/README.md +5 -4
  4. package/bin/cli.mjs +4 -0
  5. package/docs/adr/0004-page-content-state-is-composed.md +3 -0
  6. package/docs/adr/0005-structural-surfaces-share-an-explicit-anatomy.md +6 -2
  7. package/docs/adr/0011-page-shell-coordinates-persistent-page-chrome.md +6 -1
  8. package/docs/adr/0014-structural-headers-do-not-carry-description.md +2 -2
  9. package/docs/adr/0015-action-size-follows-interaction-density.md +4 -3
  10. package/docs/adr/0017-ui-assumes-a-fixed-desktop-layout.md +54 -0
  11. package/docs/adr/{0012-modal-header-only-names-the-surface.md → 0018-modal-header-only-names-the-surface.md} +4 -1
  12. package/docs/adr/0019-productive-surfaces-use-compact-density.md +65 -0
  13. package/docs/code-style.md +2 -2
  14. package/docs/consumer-upgrade-propagation.md +1 -1
  15. package/docs/data-products.md +5 -3
  16. package/docs/protocol.md +6 -6
  17. package/docs/relative-unit-scale.md +9 -2
  18. package/docs/releasing.md +28 -4
  19. package/package.json +1 -1
  20. package/registry/skills/build-opus-ui/references/evaluations.md +3 -1
  21. package/registry/skills/build-opus-ui/references/ui-patterns.md +20 -4
  22. package/src/auth/drivers/jwt.ts +2 -1
  23. package/src/core/runtime.ts +32 -5
  24. package/src/core/types.ts +16 -7
  25. package/src/mcp/index.ts +13 -1
  26. package/src/ui/components/patterns/action-list-dialog.tsx +2 -2
  27. package/src/ui/components/patterns/content-header.tsx +2 -2
  28. package/src/ui/components/patterns/form-dialog.tsx +7 -2
  29. package/src/ui/components/patterns/form.tsx +1 -1
  30. package/src/ui/components/patterns/list.tsx +239 -47
  31. package/src/ui/components/patterns/presentation.tsx +7 -5
  32. package/src/ui/components/patterns/sidebar.tsx +1 -1
  33. package/src/ui/components/patterns/state-surface.tsx +2 -2
  34. package/src/ui/components/patterns/surface-header.tsx +4 -4
  35. package/src/ui/components/primitives/alert.tsx +2 -2
  36. package/src/ui/components/primitives/breadcrumb.tsx +1 -1
  37. package/src/ui/components/primitives/button-group.tsx +1 -1
  38. package/src/ui/components/primitives/button.tsx +3 -3
  39. package/src/ui/components/primitives/calendar.tsx +1 -1
  40. package/src/ui/components/primitives/card.tsx +1 -1
  41. package/src/ui/components/primitives/close-button.tsx +40 -0
  42. package/src/ui/components/primitives/detail.tsx +68 -30
  43. package/src/ui/components/primitives/dialog.tsx +36 -21
  44. package/src/ui/components/primitives/drawer.tsx +26 -19
  45. package/src/ui/components/primitives/empty-value.tsx +3 -3
  46. package/src/ui/components/primitives/empty.tsx +1 -1
  47. package/src/ui/components/primitives/field.tsx +12 -12
  48. package/src/ui/components/primitives/icon-picker.tsx +1 -1
  49. package/src/ui/components/primitives/input-group.tsx +1 -1
  50. package/src/ui/components/primitives/input.tsx +2 -2
  51. package/src/ui/components/primitives/item.tsx +5 -5
  52. package/src/ui/components/primitives/pagination.tsx +4 -4
  53. package/src/ui/components/primitives/radio-group.tsx +1 -1
  54. package/src/ui/components/primitives/select.tsx +3 -3
  55. package/src/ui/components/primitives/table.tsx +26 -17
  56. package/src/ui/components/primitives/tabs.tsx +80 -23
  57. package/src/ui/components/primitives/textarea.tsx +1 -1
  58. package/src/ui/components/primitives/toggle-group.tsx +9 -2
  59. package/src/ui/docs/content/action-form-dialog.md +11 -4
  60. package/src/ui/docs/content/action-form.md +13 -3
  61. package/src/ui/docs/content/action-list-dialog.md +5 -7
  62. package/src/ui/docs/content/action-list.md +53 -5
  63. package/src/ui/docs/content/action-trigger.md +9 -5
  64. package/src/ui/docs/content/action-view.md +12 -8
  65. package/src/ui/docs/content/actions.md +36 -13
  66. package/src/ui/docs/content/ai.md +26 -7
  67. package/src/ui/docs/content/alert.md +6 -3
  68. package/src/ui/docs/content/aspect-ratio.md +2 -2
  69. package/src/ui/docs/content/auth.md +25 -10
  70. package/src/ui/docs/content/avatar.md +1 -1
  71. package/src/ui/docs/content/badge.md +2 -2
  72. package/src/ui/docs/content/breadcrumb.md +3 -2
  73. package/src/ui/docs/content/button.md +33 -8
  74. package/src/ui/docs/content/calendar.md +1 -1
  75. package/src/ui/docs/content/card.md +1 -1
  76. package/src/ui/docs/content/carousel.md +14 -3
  77. package/src/ui/docs/content/chat.md +1 -1
  78. package/src/ui/docs/content/cli.md +13 -7
  79. package/src/ui/docs/content/command.md +34 -2
  80. package/src/ui/docs/content/composer.md +1 -1
  81. package/src/ui/docs/content/content.md +5 -4
  82. package/src/ui/docs/content/customization.md +12 -2
  83. package/src/ui/docs/content/cycle.md +7 -5
  84. package/src/ui/docs/content/data-state.md +6 -5
  85. package/src/ui/docs/content/data.md +3 -3
  86. package/src/ui/docs/content/detail.md +12 -10
  87. package/src/ui/docs/content/dialog.md +14 -7
  88. package/src/ui/docs/content/dictionary-value.md +1 -1
  89. package/src/ui/docs/content/dock.md +23 -2
  90. package/src/ui/docs/content/dot.md +0 -2
  91. package/src/ui/docs/content/drawer.md +7 -4
  92. package/src/ui/docs/content/empty-value.md +4 -4
  93. package/src/ui/docs/content/empty.md +1 -4
  94. package/src/ui/docs/content/events.md +1 -1
  95. package/src/ui/docs/content/field.md +21 -12
  96. package/src/ui/docs/content/getting-started.md +4 -2
  97. package/src/ui/docs/content/icon-picker.md +2 -2
  98. package/src/ui/docs/content/input-otp.md +2 -0
  99. package/src/ui/docs/content/input.md +2 -3
  100. package/src/ui/docs/content/item.md +6 -3
  101. package/src/ui/docs/content/kbd.md +2 -1
  102. package/src/ui/docs/content/mcp.md +10 -4
  103. package/src/ui/docs/content/menu.md +27 -0
  104. package/src/ui/docs/content/page.md +20 -6
  105. package/src/ui/docs/content/pagination.md +9 -2
  106. package/src/ui/docs/content/popover.md +2 -2
  107. package/src/ui/docs/content/presentation.md +48 -47
  108. package/src/ui/docs/content/progress.md +2 -6
  109. package/src/ui/docs/content/runtime.md +8 -5
  110. package/src/ui/docs/content/scheduler.md +1 -1
  111. package/src/ui/docs/content/select.md +13 -8
  112. package/src/ui/docs/content/sidebar.md +3 -2
  113. package/src/ui/docs/content/skeleton.md +1 -1
  114. package/src/ui/docs/content/slider.md +4 -4
  115. package/src/ui/docs/content/spinner.md +3 -3
  116. package/src/ui/docs/content/tabs.md +22 -12
  117. package/src/ui/docs/content/testing.md +4 -2
  118. package/src/ui/docs/content/toast.md +5 -6
  119. package/src/ui/docs/content/toggle.md +37 -0
  120. package/src/ui/docs/content/tokens.md +45 -2
  121. package/src/ui/docs/content/tooltip.md +4 -3
  122. package/src/ui/docs/content/truncate.md +3 -2
  123. package/src/ui/docs/content/ui.md +3 -1
  124. package/src/ui/docs/content/upgrading.md +43 -13
  125. package/src/ui/docs/doc-client.tsx +1 -1
  126. package/src/ui/docs/registry.tsx +30 -5
  127. package/src/ui/meta.ts +4 -4
  128. package/src/ui/react.tsx +1 -0
  129. package/src/ui/theme.css +3 -0
@@ -4,12 +4,14 @@ O Opus cresce por **reincidência, nunca por especulação**. Quando o mesmo com
4
4
 
5
5
  ## Onde você aponta
6
6
 
7
- No seu projeto, uma linha por apontamento em `.opus/issues.jsonl` na raiz do repo. Dois tipos:
7
+ Cada apontamento vira uma Issue no repositório do Opus. Antes de abrir, procure uma Issue existente para o mesmo comportamento e comente nela. Dois tipos:
8
8
 
9
9
  - **`enhancement`** — código genérico que o Opus deveria ganhar (serviria a qualquer projeto). Antes de apontar, confira o que o Opus já tem (o inventário de componentes, os exports, esta doc): se já existe, use.
10
10
  - **`bug`** — um defeito ou limitação no próprio Opus, achado usando-o.
11
11
 
12
- ```json
12
+ Descreva cada apontamento com estes campos — um exemplo de cada tipo:
13
+
14
+ ```text
13
15
  {"type": "enhancement", "behavior": "o comportamento em uma frase.", "file": "src/onde-vive.ts", "kind": "ui|sdk|driver|infra"}
14
16
  {"type": "bug", "behavior": "o que quebra ou falta.", "file": "onde se manifesta.", "note": "repro + o workaround aplicado."}
15
17
  ```
@@ -20,15 +22,15 @@ O ponto do ciclo é **não bloquear a entrega**. Bateu em um gap ou em um bug do
20
22
 
21
23
  1. **Contorne local** — componha um wrapper no seu projeto. O Opus entrega _source_, então dá para embrulhar qualquer superfície dele. Nunca edite `node_modules` (some no próximo install).
22
24
  2. **Entregue** a feature com o workaround.
23
- 3. **Aponte** no `.opus/issues.jsonl` e siga em frente.
25
+ 3. **Aponte** na Issue e siga em frente.
24
26
 
25
27
  O "depois" — o conserto no Opus — corre em paralelo. Ele não segura o seu trabalho; o único custo de demorar é o workaround viver um pouco mais.
26
28
 
27
29
  ## Como fecha
28
30
 
29
- O apontamento é colhido e abre uma **Issue no repositório do Opus**, onde a triagem acontece (deduplicada re-apontar o mesmo é idempotente):
31
+ A triagem acontece em uma **Issue em [github.com/softize-dev/opus](https://github.com/softize-dev/opus/issues)**; procure uma existente antes de abrir. O pacote não coleta apontamentos do seu projeto por conta própria. O desfecho depende do tipo:
30
32
 
31
- - **Enhancement** aceito (com reincidência) → implementado no Opus → sai em um _bump_ → seu projeto atualiza o pin (`opus.json`) e troca o workaround pelo import.
33
+ - **Enhancement** aceito (com reincidência) → implementado no Opus → sai em um _bump_ → seu projeto [atualiza o Opus](upgrading) e troca o workaround pelo import.
32
34
  - **Bug** → vira _fix_ + entrada no `CHANGELOG` → no _bump_, o workaround sai.
33
35
 
34
36
  A régua e a decisão ficam com quem mantém o Opus — hoje, a **Softize**. O registro curado das promoções vive no `PROMOTED.md` do pacote.
@@ -15,7 +15,7 @@ e o tooltip dessa ação. Para uma ação em andamento depois do clique, use `bu
15
15
  <DataState empty emptyMessage="Nenhum papel.">
16
16
  <div />
17
17
  </DataState>
18
- <DataState error={{ message: 'detalhe técnico fica no console' }} onRetry={() => undefined}>
18
+ <DataState error={{ message: 'detalhe técnico que não aparece na tela' }} onRetry={() => undefined}>
19
19
  <div />
20
20
  </DataState>
21
21
  </div>
@@ -28,15 +28,15 @@ tabela continua responsável pela borda: o `Empty` dentro dela vem sem moldura.
28
28
  disponível para criação ou vínculo, use `Empty` diretamente, com a moldura tracejada.
29
29
 
30
30
  ```tsx preview col
31
- <table className="w-full overflow-hidden rounded-lg border border-border text-sm">
32
- <tbody>
31
+ <Table variant="framed">
32
+ <TableBody>
33
33
  <DataState empty emptyMessage="Nenhum usuário." colSpan={3}>
34
34
  <tr>
35
35
  <td />
36
36
  </tr>
37
37
  </DataState>
38
- </tbody>
39
- </table>
38
+ </TableBody>
39
+ </Table>
40
40
  ```
41
41
 
42
42
  ## Propriedades de DataState
@@ -51,3 +51,4 @@ disponível para criação ou vínculo, use `Empty` diretamente, com a moldura t
51
51
  | `onRetry` | `() => void \| Promise<void>` | | Recuperação: mostra a ação de tentar de novo somente com ícone no estado de erro. |
52
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). |
54
+ | `children` | `ReactNode` | | Obrigatório. Conteúdo renderizado quando não há erro, carregamento nem vazio. |
@@ -48,15 +48,15 @@ const db = new Kysely<AdminDB>({
48
48
  await db.selectFrom('agents').select(['isDefault', 'roleId']).where('workspaceId', '=', id).execute()
49
49
  ```
50
50
 
51
- ## Migrações, preparação e seeds
51
+ ## Migrações e seeds
52
52
 
53
53
  Cada etapa possui um papel diferente:
54
54
 
55
55
  - `opus db migrate` — aplica o **schema idempotente** (`config.schema`, um script SQL
56
56
  evolutivo: `IF NOT EXISTS` + guards cobrem nascer do zero e upgrade no mesmo artefato)
57
57
  e roda o drift-check entidade ↔ banco na sequência (exit ≠ 0 se divergir).
58
- - `prepare` — backfill estrutural, prod-safe e idempotente; roda no deploy (depois do migrate).
59
- - `seed` cria dados de desenvolvimento e teste. Não é executado em produção.
58
+ - `opus seed` — aplica datasets de desenvolvimento e teste declarados com `defineSeed` e registrados
59
+ no `opus.config.ts`; conecta com `NODE_ENV=development` ou `test`. Ver [CLI opus](cli).
60
60
 
61
61
  ## Campos JSON
62
62
 
@@ -15,7 +15,7 @@ validação, use `Field`.
15
15
  }
16
16
  />
17
17
  <DetailField
18
- className="sm:col-span-2"
18
+ className="col-span-2"
19
19
  label="E-mail"
20
20
  value="joao.silva@example.com"
21
21
  icon={<Mail />}
@@ -25,8 +25,9 @@ validação, use `Field`.
25
25
 
26
26
  ## Valor ausente
27
27
 
28
- `null`, `undefined`, string vazia ou só com espaços mostram “Não informado”; `empty` troca o
29
- significado no domínio. `0` e `false` seguem como valores. Ver `EmptyValue`.
28
+ `null`, `undefined`, string vazia ou só com espaços mostram um travessão; a leitura assistiva
29
+ recebe “Não informado”. Uma string em `empty` troca esse significado no domínio, enquanto um nó
30
+ React substitui a apresentação. `0` e `false` seguem como valores. Ver `EmptyValue`.
30
31
 
31
32
  ```tsx preview col
32
33
  <DetailGroup columns={2}>
@@ -37,11 +38,12 @@ significado no domínio. `0` e `false` seguem como valores. Ver `EmptyValue`.
37
38
 
38
39
  ## Moldura e divisórias internas
39
40
 
40
- `variant="framed"` adiciona a superfície e a borda externa. `dividers` desenha apenas as
41
+ `variant="framed"` adiciona a borda externa sem preencher o fundo; na orientação horizontal, só a
42
+ coluna de rótulos recebe um fundo sutil. `dividers` desenha apenas as
41
43
  divisórias internas; as duas opções são independentes e podem ser combinadas. `orientation`
42
44
  define se a chave fica sobre o valor ou ao lado dele. Na orientação horizontal, todos os valores
43
- começam depois da mesma coluna de rótulo, com largura padrão de `7rem`. Quando a superfície exigir
44
- mais espaço para os rótulos, ajuste a variável no grupo, por exemplo com
45
+ começam depois da mesma coluna de rótulo, com largura padrão de `7rem` em grupos simples e
46
+ `8.5rem` na moldura horizontal. Quando a superfície exigir mais espaço para os rótulos, ajuste a variável no grupo, por exemplo com
45
47
  `className="[--detail-label-width:9rem]"`.
46
48
 
47
49
  ```tsx preview col
@@ -49,7 +51,7 @@ mais espaço para os rótulos, ajuste a variável no grupo, por exemplo com
49
51
  <DetailField label="Documento" value="Sem documento" />
50
52
  <DetailField label="Fontes" value="NBS e Followize" />
51
53
  <DetailField
52
- className="sm:col-span-2"
54
+ className="col-span-2"
53
55
  label="E-mail"
54
56
  value="cliente@example.com"
55
57
  icon={<Mail />}
@@ -61,9 +63,9 @@ mais espaço para os rótulos, ajuste a variável no grupo, por exemplo com
61
63
 
62
64
  | Propriedade | Tipo | Padrão | Descrição |
63
65
  |---|---|---|---|
64
- | `variant` | `'plain' \| 'framed'` | `'plain'` | `framed` aplica a superfície e a moldura canônicas ao conjunto. |
66
+ | `variant` | `'plain' \| 'framed'` | `'plain'` | `framed` aplica a moldura canônica ao conjunto, com fundo transparente; na orientação horizontal, a coluna de rótulos recebe fundo sutil. |
65
67
  | `dividers` | `boolean` | `false` | Hairlines somente entre os campos, sem exigir moldura externa. |
66
- | `columns` | `1 \| 2 \| 3 \| 4 \| 'auto'` | `1` | Colunas responsivas ou distribuição automática por largura mínima. |
68
+ | `columns` | `1 \| 2 \| 3 \| 4 \| 'auto'` | `1` | Número fixo de colunas ou distribuição automática por largura mínima. |
67
69
  | `orientation` | `'vertical' \| 'horizontal'` | `'vertical'` | Chave sobre o valor ou ao lado dele em cada campo. |
68
70
 
69
71
  ## Propriedades de DetailField
@@ -73,4 +75,4 @@ mais espaço para os rótulos, ajuste a variável no grupo, por exemplo com
73
75
  | `label` | `ReactNode` | | A chave do par. |
74
76
  | `value` | `ReactNode` | | O valor; `null`, `undefined` e string vazia renderizam a ausência, `0` e `false` seguem como valores. |
75
77
  | `icon` | `ReactNode` | | Ícone decorativo antes do par chave/valor. |
76
- | `empty` | `ReactNode` | `“Não informado”` | O que a ausência significa neste campo: um rótulo ou um próprio. |
78
+ | `empty` | `ReactNode` | `“Não informado”` | Uma string significado acessível ao travessão; um próprio substitui a apresentação. |
@@ -16,7 +16,8 @@ Para conteúdo ancorado e não modal, use `Popover`. Para uma lista de ações,
16
16
 
17
17
  `DialogContent` delimita a superfície. `DialogHeader`, `DialogBody` e `DialogFooter` organizam
18
18
  título, conteúdo rolável e ações com o espaçamento da família. A superfície usa o fundo base,
19
- borda semântica, raio `xl` e elevação para permanecer distinta da página.
19
+ borda transparente no tema claro, borda sutil no escuro, raio `xl` e elevação para permanecer
20
+ distinta da página.
20
21
 
21
22
  ```tsx preview
22
23
  <Dialog>
@@ -32,11 +33,11 @@ borda semântica, raio `xl` e elevação para permanecer distinta da página.
32
33
  <Input id="workspace-name" placeholder="Ex.: Empresa X" />
33
34
  </DialogBody>
34
35
  <DialogFooter>
35
- <ButtonGroup mode="spaced" distribution="equal">
36
+ <ButtonGroup mode="spaced">
36
37
  <DialogClose asChild>
37
- <Button variant="outline">Cancelar</Button>
38
+ <Button variant="ghost">Cancelar</Button>
38
39
  </DialogClose>
39
- <Button>Criar workspace</Button>
40
+ <Button>Salvar</Button>
40
41
  </ButtonGroup>
41
42
  </DialogFooter>
42
43
  </DialogContent>
@@ -44,8 +45,12 @@ borda semântica, raio `xl` e elevação para permanecer distinta da página.
44
45
  ```
45
46
 
46
47
  O corpo cresce até o limite da janela e passa a rolar; cabeçalho e rodapé permanecem visíveis.
47
- O `ButtonGroup` divide o espaço entre decisões equivalentes no rodapé. O `DialogFooter` organiza
48
- a faixa, mas não decide a distribuição nem a aparência dos botões.
48
+ O backdrop escurece a página sem aplicar desfoque.
49
+ O fechamento do cabeçalho usa uma ação circular neutra e sutil. `closeSize` escolhe entre `xs` e
50
+ `sm`; o padrão é `sm`.
51
+ O `ButtonGroup` preserva a largura natural das ações por padrão. Use `distribution="equal"`
52
+ somente para decisões deliberadamente equivalentes. O `DialogFooter` organiza a faixa, mas não
53
+ decide a distribuição nem a aparência dos botões.
49
54
  `DialogClose` encerra o modal sem exigir estado controlado. Use `open` e `onOpenChange` quando outra
50
55
  parte da interface também precisar controlar a abertura.
51
56
 
@@ -144,7 +149,7 @@ confirmações e prompts distribuem confirmar e cancelar em duas colunas.
144
149
  Em `dialog.choose`, declare pelo menos uma ação e marque exatamente uma ação habilitada com
145
150
  `initialFocus`. Essa ação representa a saída segura. Os valores de `result` precisam ser únicos.
146
151
  Por padrão, a última ação recebe contexto primário e variante sólida; as anteriores usam contexto
147
- neutro e variante ghost. Defina `context` ou `variant` na própria ação para substituir o padrão.
152
+ neutro e variante outline. Defina `context` ou `variant` na própria ação para substituir o padrão.
148
153
 
149
154
  ### Montar o host
150
155
 
@@ -273,6 +278,8 @@ botão. O texto informa o efeito real, como `Excluir`, `Revogar acesso` ou `Ence
273
278
  | Propriedade | Tipo | Padrão | Descrição |
274
279
  | ----------------- | ----------- | ------ | --------------------------------------------------------------------------------------------------------- |
275
280
  | `showCloseButton` | `boolean` | `true` | No modo padrão, inclui a ação de fechamento no header; o modo de alerta exige uma resposta identificável. |
281
+ | `closeDisabled` | `boolean` | `false` | Mantém a ação visível e impede o fechamento enquanto a tarefa está bloqueada. |
282
+ | `closeSize` | `"xs" \| "sm"` | `"sm"` | Define o tamanho da ação circular de fechar. |
276
283
  | `className` | `string` | | Ajusta a superfície. |
277
284
  | `children` | `ReactNode` | | Cabeçalho, corpo, rodapé ou conteúdo próprio. |
278
285
 
@@ -120,7 +120,7 @@ resultado é vazio e a resolução cai na meta do `t.dict` que viaja no schema.
120
120
  | `dict` | `DictType \| LogicalTypeMeta \| DictionaryDescriptor` | — | O dicionário (`t.dict`), a meta lida do schema ou um descritor normalizado. |
121
121
  | `value` | `string \| null \| undefined` | — | O código. Vazio renderiza `fallback`. |
122
122
  | `presentation` | `'classification' \| 'status' \| 'stage' \| 'plain'` | do dicionário | Sobrepõe o papel só nesta ocorrência. |
123
- | `context` | contexto de `Badge` | pelo dicionário | Sobrepõe o significado semântico e promove texto a badge. |
123
+ | `context` | contexto de `Badge` | pelo dicionário | Sobrepõe o significado semântico quando a ocorrência já é badge; sozinho, não promove texto a badge. |
124
124
  | `variant` | variante de `Badge` | pelo papel | Sobrepõe a variante e promove texto a badge. |
125
125
  | `icon` | `boolean \| ReactNode` | `true` | `false` esconde o ícone declarado; um nó substitui. |
126
126
  | `icons` | `Record<string, LucideIcon>` | `iconPickerIcons` | Catálogo nome → componente. |
@@ -1,5 +1,3 @@
1
- # Dock
2
-
3
1
  Ferramentas ancoradas à superfície de trabalho. Um canvas ou um editor raramente comporta mais
4
2
  uma faixa de chrome no topo: a trilha da aplicação já ocupa esse papel, e um segundo cabeçalho
5
3
  empilha duas faixas com a mesma função. A Dock coloca as ações sobre a própria superfície,
@@ -63,10 +61,33 @@ A barra é uma `toolbar`: as setas andam entre as ações e Home/End vão às po
63
61
  por tooltip, então `<TooltipProvider>` precisa existir na raiz do app — o esqueleto do `opus create`
64
62
  já monta.
65
63
 
64
+ ## Propriedades de Dock
65
+
66
66
  | Propriedade | Tipo | Padrão | Descrição |
67
67
  | --- | --- | --- | --- |
68
68
  | `position` | `'bottom' \| 'bottom-left' \| 'bottom-right'` | `'bottom'` | Aresta do contêiner onde a barra se ancora. |
69
69
  | `label` | `string` | | Nome acessível da barra. |
70
+ | `children` | `ReactNode` | | Os grupos de ações, em `DockGroup`. |
71
+ | `className` | `string` | | Classes adicionais da barra. |
72
+
73
+ ## Propriedades de DockGroup
74
+
75
+ | Propriedade | Tipo | Padrão | Descrição |
76
+ | --- | --- | --- | --- |
77
+ | `children` | `ReactNode` | | As ações do grupo, em `DockAction`. A divisória antes do grupo é aplicada automaticamente, exceto no primeiro. |
78
+ | `className` | `string` | | Classes adicionais do grupo. |
79
+
80
+ ## Propriedades de DockAction
81
+
82
+ | Propriedade | Tipo | Padrão | Descrição |
83
+ | --- | --- | --- | --- |
84
+ | `icon` | `ReactNode` | | Ícone exibido no botão. |
85
+ | `label` | `string` | | Nome da ação; vira o nome acessível e o tooltip quando não há `hint`. |
86
+ | `pressed` | `boolean` | | Presente quando a ação liga um modo: aplica o preenchimento e expõe `aria-pressed`. Ausente quando a ação apenas executa. |
87
+ | `disabled` | `boolean` | `false` | Desabilita a ação e a tira da navegação por setas. |
88
+ | `hint` | `ReactNode` | `label` | Conteúdo do tooltip quando ele precisa dizer mais que o rótulo. |
89
+ | `onClick` | `() => void` | | Executa a ação ou alterna o modo. |
90
+ | `className` | `string` | | Classes adicionais do botão. |
70
91
 
71
92
  ## Propriedades de SurfaceStatus
72
93
 
@@ -1,5 +1,3 @@
1
- # Dot
2
-
3
1
  Indicador visual compacto para estados que já têm contexto. O tamanho permanece fixo; `context`
4
2
  seleciona o significado e `variant` escolhe ponto sólido ou contornado. Quando a cor reforça significado, `label` fornece o nome
5
3
  acessível. Sem `label`, o ponto é decorativo.
@@ -11,7 +11,7 @@ entra pela direita e pode ser fechado por Esc, pelo overlay ou pelo botão de fe
11
11
  </DrawerTrigger>
12
12
  <DrawerContent side="right">
13
13
  <DrawerHeader>
14
- <DrawerTitle>criarTicket</DrawerTitle>
14
+ <DrawerTitle>Criar ticket</DrawerTitle>
15
15
  </DrawerHeader>
16
16
  <DrawerBody className="text-sm text-muted-foreground">
17
17
  <p>Ação · domínio Suporte</p>
@@ -26,7 +26,8 @@ entra pela direita e pode ser fechado por Esc, pelo overlay ou pelo botão de fe
26
26
  `side` aceita `top`, `right`, `bottom` e `left`. `DrawerFooter` mantém as ações no rodapé;
27
27
  `DrawerClose` fecha o painel sem exigir controle manual de estado. Como no `Dialog`, o cabeçalho
28
28
  recebe um divisor inferior e o rodapé usa um divisor superior. O corpo preserva o mesmo alinhamento
29
- horizontal entre título, conteúdo e ações.
29
+ horizontal entre título, conteúdo e ações. O fechamento do cabeçalho usa uma ação circular neutra
30
+ e sutil; `closeSize` escolhe entre `xs` e `sm`, com `sm` como padrão.
30
31
 
31
32
  ```tsx preview
32
33
  <Drawer>
@@ -42,9 +43,9 @@ horizontal entre título, conteúdo e ações.
42
43
  <Input id="ws-nome" defaultValue="Empresa X" />
43
44
  </DrawerBody>
44
45
  <DrawerFooter>
45
- <ButtonGroup mode="spaced" distribution="equal">
46
+ <ButtonGroup mode="spaced">
46
47
  <DrawerClose asChild>
47
- <Button variant="outline">Cancelar</Button>
48
+ <Button variant="ghost">Cancelar</Button>
48
49
  </DrawerClose>
49
50
  <Button>Salvar</Button>
50
51
  </ButtonGroup>
@@ -66,6 +67,8 @@ horizontal entre título, conteúdo e ações.
66
67
  | ----------------- | ---------------------------------------- | --------- | ------------------------------------------------------------------------------------------ |
67
68
  | `side` | `'top' \| 'right' \| 'bottom' \| 'left'` | `'right'` | Borda de onde o painel aparece. |
68
69
  | `showCloseButton` | `boolean` | `true` | Inclui a ação de fechamento no header. Desative quando o painel exigir uma ação explícita. |
70
+ | `closeDisabled` | `boolean` | `false` | Mantém a ação visível e impede fechar enquanto o painel está bloqueado. |
71
+ | `closeSize` | `"xs" \| "sm"` | `"sm"` | Define o tamanho da ação circular de fechar. |
69
72
 
70
73
  ## Propriedades de DrawerBody
71
74
 
@@ -1,7 +1,7 @@
1
- Valor ausente tem uma representação padrão. Em célula compacta de tabela aparece o travessão,
2
- e a leitura assistiva recebe “Não informado”; em texto corrido, como no `DetailField`, aparece o
3
- próprio rótulo. As colunas de `ActionList` e o `DetailField` já fazem isso sozinhos; um renderer
4
- customizado reutiliza a primitiva em vez de repetir a condicional.
1
+ Valor ausente tem uma representação padrão. Nas células de tabela e nos pares de `DetailField`
2
+ aparece o travessão, enquanto a leitura assistiva recebe “Não informado”. As colunas de
3
+ `ActionList` e o `DetailField` já fazem isso sozinhos; um renderer customizado reutiliza a
4
+ primitiva em vez de repetir a condicional.
5
5
 
6
6
  ```tsx preview
7
7
  <div className="flex items-center gap-6 text-sm">
@@ -43,10 +43,7 @@ título e descrição agrupados no centro.
43
43
  </EmptyDescription>
44
44
  </EmptyHeader>
45
45
  <EmptyActions>
46
- <Button>
47
- <Plus />
48
- Anexar skill
49
- </Button>
46
+ <Button icon={<Plus />}>Anexar skill</Button>
50
47
  </EmptyActions>
51
48
  </Empty>
52
49
  ```
@@ -46,7 +46,7 @@ const runtime = createRuntime({
46
46
  // No handler: emite pelo tipo declarado; o core preenche id/timestamp/actor/source.
47
47
  handler: async (ctx, input) => {
48
48
  const nota = await repo.create(input)
49
- ctx.emit('nota.emitida', { id: nota.id, valor: nota.valor })
49
+ await ctx.emit('nota.emitida', { id: nota.id, valor: nota.valor })
50
50
  return nota
51
51
  }
52
52
  ```
@@ -1,29 +1,33 @@
1
1
  ## Campo empilhado
2
2
 
3
3
  Use `Field` para manter rótulo, controle, ajuda e erro com espaçamento consistente. Na orientação
4
- vertical, `FieldLabel`, o controle e `FieldDescription` ficam empilhados. Quando o controle usa
5
- `aria-invalid`, o rótulo acompanha o contexto de erro.
4
+ vertical, `FieldLabel` e o controle ficam empilhados. A ajuda fica junto ao rótulo, com `LabelHelp`,
5
+ o mesmo ícone que o `ActionForm` usa para `FieldSpec.help`. Use `FieldDescription` somente quando a
6
+ frase precisar ficar visível o tempo todo abaixo do controle.
6
7
 
7
8
  ```tsx preview col md
8
9
  <Field>
9
- <FieldLabel htmlFor="workspace-slug">Slug do workspace</FieldLabel>
10
+ <FieldLabel htmlFor="workspace-slug" className="items-center gap-1.5">
11
+ <span>Slug do workspace</span>
12
+ <LabelHelp help="Vira o subdomínio do preview: empresa-x.preview.softize.com.br." />
13
+ </FieldLabel>
10
14
  <Input id="workspace-slug" defaultValue="empresa-x" />
11
- <FieldDescription>Vira o subdomínio do preview: empresa-x.preview.softize.com.br.</FieldDescription>
12
15
  </Field>
13
16
  ```
14
17
 
15
18
  ## Horizontal com toggle
16
19
 
17
20
  `orientation="horizontal"` posiciona o controle ao lado do texto. `FieldContent` agrupa título e
18
- descrição; `FieldTitle` nomeia o campo quando o texto não puder ser um `<label>`.
21
+ descrição; `FieldTitle` exibe o título quando o texto não puder ser um `<label>`. Como ele não se
22
+ vincula ao controle, ligue-o ao controle por `aria-labelledby` para manter o nome acessível.
19
23
 
20
24
  ```tsx preview col md
21
25
  <Field orientation="horizontal">
22
26
  <FieldContent>
23
- <FieldTitle>Acionar o revisor no handoff</FieldTitle>
27
+ <FieldTitle id="auto-review-title">Acionar o revisor no handoff</FieldTitle>
24
28
  <FieldDescription>Ao abrir o handoff, o agente reviewer entra na sessão automaticamente.</FieldDescription>
25
29
  </FieldContent>
26
- <Switch id="auto-review" defaultChecked />
30
+ <Switch id="auto-review" aria-labelledby="auto-review-title" defaultChecked />
27
31
  </Field>
28
32
  ```
29
33
 
@@ -31,21 +35,25 @@ descrição; `FieldTitle` nomeia o campo quando o texto não puder ser um `<labe
31
35
 
32
36
  `FieldSet` agrupa campos sob uma `FieldLegend`; `FieldGroup` define o espaçamento e
33
37
  `FieldSeparator` marca uma divisão. `FieldError` aparece somente quando existe mensagem de erro.
38
+ Declare `data-invalid="true"` no `Field` para que o rótulo acompanhe o contexto de erro;
39
+ `aria-invalid` marca apenas o controle. O `ActionForm` define os dois atributos sozinho.
34
40
 
35
41
  ```tsx preview col md
36
42
  <FieldSet>
37
43
  <FieldLegend>Novo agente</FieldLegend>
38
44
  <FieldGroup>
39
- <Field>
45
+ <Field data-invalid="true">
40
46
  <FieldLabel htmlFor="agent-name">Nome</FieldLabel>
41
47
  <Input id="agent-name" defaultValue="" aria-invalid placeholder="Ex.: developer" />
42
48
  <FieldError>Informe um nome para o agente.</FieldError>
43
49
  </Field>
44
50
  <FieldSeparator />
45
51
  <Field>
46
- <FieldLabel htmlFor="agent-prompt">Prompt</FieldLabel>
52
+ <FieldLabel htmlFor="agent-prompt" className="items-center gap-1.5">
53
+ <span>Prompt</span>
54
+ <LabelHelp help="A síntese vira a primeira mensagem da sessão." />
55
+ </FieldLabel>
47
56
  <Textarea id="agent-prompt" rows={3} defaultValue="Veste o papel de developer no workspace Empresa X." />
48
- <FieldDescription>A síntese vira a primeira mensagem da sessão.</FieldDescription>
49
57
  </Field>
50
58
  </FieldGroup>
51
59
  </FieldSet>
@@ -55,7 +63,8 @@ descrição; `FieldTitle` nomeia o campo quando o texto não puder ser um `<labe
55
63
 
56
64
  | Propriedade | Tipo | Padrão | Descrição |
57
65
  |---|---|---|---|
58
- | `orientation` | `'vertical' \| 'horizontal' \| 'responsive'` | `'vertical'` | Direção do campo; `responsive` se torna horizontal a partir do container médio. |
66
+ | `orientation` | `'vertical' \| 'horizontal' \| 'responsive'` | `'vertical'` | Direção fixa do campo. `responsive` permanece como alias compatível de `horizontal`. |
67
+ | `data-invalid` | `boolean \| 'true' \| 'false'` | | Com `true`, aplica o contexto de erro ao campo e ao rótulo. O `ActionForm` define o atributo sozinho. |
59
68
 
60
69
  ## Propriedades de FieldLegend
61
70
 
@@ -67,7 +76,7 @@ descrição; `FieldTitle` nomeia o campo quando o texto não puder ser um `<labe
67
76
 
68
77
  | Propriedade | Tipo | Padrão | Descrição |
69
78
  |---|---|---|---|
70
- | `errors` | `Array<{ message?: string }>` | | Deduplica e apresenta uma lista de erros; sem conteúdo, o componente não renderiza. |
79
+ | `errors` | `Array<{ message?: string } \| undefined>` | | Deduplica e apresenta uma lista de erros; sem conteúdo, o componente não renderiza. |
71
80
  | `children` | `ReactNode` | | Mensagem literal, com prioridade sobre `errors`. |
72
81
 
73
82
  ## Propriedades de FieldSeparator
@@ -75,8 +75,10 @@ pnpm add @softize/opus
75
75
  pnpm add -D @softize/base
76
76
  pnpm exec opus setup
77
77
  pnpm exec base setup
78
+ ```
78
79
 
79
- # index.css do app — o tema canônico + os componentes do Opus no scan do Tailwind.
80
+ ```css
81
+ /* index.css do app — o tema canônico + os componentes do Opus no scan do Tailwind. */
80
82
  @import '@softize/opus/ui/theme.css';
81
83
  @source '../node_modules/@softize/opus/src/ui/**/*.{ts,tsx}';
82
84
  ```
@@ -111,4 +113,4 @@ await runtime.start()
111
113
 
112
114
  - `CLAUDE.md` do repo e do app — o índice local: mapa, gates, gotchas.
113
115
  - As `description` das entidades/actions — a spec de negócio, projetada no manifest pelo `opus gen`.
114
- - Gate de build: `opus check` (convenções das actions) + `opus db check` (drift entidade ↔ banco). Rode antes de entregar.
116
+ - Gate de build: `opus check` (convenções das actions e da UI) + `opus copy --check` e `base copy check` (inventário e política de copy) + `opus db check` (drift entidade ↔ banco). Rode antes de entregar.
@@ -22,13 +22,13 @@ salvo em listas, cards e árvores.
22
22
 
23
23
  ```tsx preview col md
24
24
  const [icon, setIcon] = useState('store')
25
- const Icon = iconPickerIcons[icon] ?? FileText
25
+ const SelectedIcon = iconPickerIcons[icon] ?? FileText
26
26
 
27
27
  render(
28
28
  <div className="flex items-center gap-3">
29
29
  <IconPicker value={icon} onChange={setIcon} className="w-56" />
30
30
  <span className="flex items-center gap-2 rounded-md border px-3 py-2 text-sm">
31
- <Icon className="size-4 text-muted-foreground" />
31
+ <SelectedIcon className="size-4 text-muted-foreground" />
32
32
  Painel comercial
33
33
  </span>
34
34
  </div>,
@@ -71,6 +71,8 @@ render(
71
71
  | `maxLength` | `number` | | Quantidade de posições do código. Defina um `InputOTPSlot` para cada posição. |
72
72
  | `value` | `string` | | Código no modo controlado. Use com `onChange`. |
73
73
  | `onChange` | `(value: string) => void` | | Chamado a cada entrada com o código acumulado. |
74
+ | `onComplete` | `(value: string) => void` | | Chamado quando o código atinge `maxLength`. |
75
+ | `pattern` | `string` | | Expressão regular que o código precisa satisfazer; entradas que não casam são descartadas. Sem `pattern`, qualquer caractere é aceito, inclusive letras. Para somente dígitos, use `'^\\d+$'`. |
74
76
  | `disabled` | `boolean` | `false` | Desabilita a digitação em todo o conjunto. |
75
77
 
76
78
  ## Propriedades de InputOTPSlot
@@ -21,7 +21,6 @@ como calendário em uma data; o `Label` continua responsável pelo nome acessív
21
21
 
22
22
  Quando o campo precisar combinar vários adornos, prefixos ou botões, use `InputGroup`.
23
23
 
24
-
25
24
  ## Ação no fim do campo (trailing)
26
25
 
27
26
  `trailing` posiciona no fim do campo uma ação relacionada ao valor, como limpar ou mostrar uma
@@ -37,7 +36,7 @@ function Demo() {
37
36
  onChange={(e) => setQ(e.target.value)}
38
37
  trailing={
39
38
  q ? (
40
- <Button variant="ghost" size="icon-xs" onClick={() => setQ('')}>
39
+ <Button variant="ghost" size="icon-xs" aria-label="Limpar busca" onClick={() => setQ('')}>
41
40
  <X />
42
41
  </Button>
43
42
  ) : undefined
@@ -167,7 +166,7 @@ Com `InputGroupTextarea`, um addon em `block-end` forma uma região de ações a
167
166
  | Propriedade | Tipo | Padrão | Descrição |
168
167
  |---|---|---|---|
169
168
  | `size` | `'xs' \| 'sm' \| 'icon-xs' \| 'icon-sm'` | `'xs'` | O subconjunto da escala única que cabe num campo (1.5 · 2 · 1.5 · 1.75rem); os `icon-*` são quadrados. |
170
- | `context` | `'neutral' \| 'primary' \| 'danger'` | `'primary'` | Contexto semântico herdado de Button. |
169
+ | `context` | `'neutral' \| 'primary' \| 'danger'` | `'neutral'` | Contexto semântico herdado de Button. Com `variant` `solid` ou `subtle` sem contexto declarado, o padrão passa a `'primary'`. |
171
170
  | `variant` | `'solid' \| 'subtle' \| 'outline' \| 'ghost' \| 'link'` | `'ghost'` | Tratamento visual; use `solid` quando a ação precisar de ênfase. |
172
171
 
173
172
  ### Propriedades de InputGroupInput
@@ -3,6 +3,9 @@
3
3
  A composição completa usa `ItemMedia` à esquerda, `ItemHeader` (`ItemTitle` +
4
4
  `ItemDescription`) no meio e `ItemActions` à direita. Ícone e imagem mantêm uma moldura quadrada
5
5
  alinhada ao topo, mesmo quando a descrição ocupa mais linhas. `variant="outline"` desenha a borda.
6
+ O tamanho padrão usa corpo produtivo, `0.75rem` de padding e `0.75rem` entre regiões. `size="sm"`
7
+ mantém o padding horizontal, reduz o padding vertical para `0.5rem` e o espaço entre regiões para
8
+ `0.625rem` em listas densas.
6
9
 
7
10
  ```tsx preview col
8
11
  <Item variant="outline">
@@ -59,7 +62,7 @@ alinhada ao topo, mesmo quando a descrição ocupa mais linhas. `variant="outlin
59
62
 
60
63
  ## Clicável e compacto
61
64
 
62
- asChild funde o Item em um <a> — a linha inteira vira alvo (hover no fundo). size=sm aperta o respiro; ItemMedia variant=image ancora um avatar.
65
+ `asChild` funde o Item em um `<a>` — a linha inteira vira alvo (hover no fundo). `size="sm"` aperta o respiro; `ItemMedia` na variante padrão recebe um `Avatar`, que já traz a própria moldura.
63
66
 
64
67
  ```tsx preview col
65
68
  <Item asChild size="sm" variant="outline">
@@ -97,7 +100,7 @@ Use `ItemBody` quando a linha também apresenta um valor ou controle que não pe
97
100
  </Item>
98
101
  ```
99
102
 
100
- `ItemContent` permanece exportado somente para compatibilidade durante a versão 12. Código novo
103
+ `ItemContent` permanece exportado apenas por compatibilidade e está obsoleto. Código novo
101
104
  usa `ItemHeader` ou `ItemBody` conforme o papel do conteúdo.
102
105
 
103
106
  ## Propriedades de Item
@@ -122,4 +125,4 @@ usa `ItemHeader` ou `ItemBody` conforme o papel do conteúdo.
122
125
 
123
126
  `ItemHeader`, `ItemTitle`, `ItemDescription`, `ItemBody`, `ItemActions`, `ItemFooter` e
124
127
  `ItemSeparator` aceitam as props nativas dos respectivos elementos e não adicionam propriedades
125
- próprias. `ItemContent` preserva esse mesmo contrato somente durante a migração da versão 12.
128
+ próprias. O `ItemContent` obsoleto preserva esse mesmo contrato por compatibilidade.
@@ -27,7 +27,7 @@ reconhecível que o nome da tecla.
27
27
  ```tsx preview col-start
28
28
  <KbdGroup>
29
29
  <Kbd>
30
- <Command />
30
+ <CommandIcon />
31
31
  </Kbd>
32
32
  <Kbd>
33
33
  <CornerDownLeft />
@@ -49,6 +49,7 @@ ação antes de informar seu atalho.
49
49
  Buscar workspace
50
50
  <KbdGroup>
51
51
  <Kbd>⌘</Kbd>
52
+ <span>+</span>
52
53
  <Kbd>K</Kbd>
53
54
  </KbdGroup>
54
55
  </TooltipContent>
@@ -17,16 +17,22 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
17
17
  const server = createOpusMcpServer(runtime, {
18
18
  name: 'meu-app',
19
19
  // Valida a identidade da requisição (IdP) → contexto do runtime. Sem isso, roda anônimo
20
- // (o `can` nega → só actions públicas). Com isso, o agente age COMO O USUÁRIO.
20
+ // (sem usuário, só actions `public` rodam). Com isso, o agente age COMO O USUÁRIO.
21
21
  resolveContext: async (extra) => auth.resolveFromMcp(extra),
22
22
  })
23
23
 
24
24
  await server.connect(new StdioServerTransport()) // local; HTTP/SSE para remoto
25
25
  ```
26
26
 
27
- `ListTools` devolve as actions `ai:enabled` (nome + descrição + JSON Schema do input);
28
- `CallTool` executa a action pelo `runtime.execute` validação, auth (`ctx.can`) e audit,
29
- tudo igual a uma chamada normal. Read-only? Marque actions de leitura com `ai:enabled`.
27
+ actions marcadas com `ai: { enabled: true }` ficam disponíveis, tanto para listar quanto para
28
+ executar. `ListTools` devolve cada uma com `name` (identificador técnico), `title` (a `label`
29
+ legível, quando existe), descrição, JSON Schema do input e, em `_meta`, os Produtos de Dados
30
+ relacionados: `com.softize.opus/data-products` (identificadores) e
31
+ `com.softize.opus/data-product-labels` (nome legível por identificador). `CallTool` recusa, com
32
+ erro, qualquer nome fora dessa lista; os demais seguem pelo `runtime.execute` — validação,
33
+ autorização e audit, tudo igual a uma chamada normal. Read-only? Marque só actions de leitura
34
+ com `ai:enabled`: a marcação decide o que o cliente MCP pode executar, e a autorização do
35
+ contexto continua valendo por cima.
30
36
 
31
37
  ## Escolher entre integração interna e MCP
32
38
 
@@ -104,6 +104,14 @@ MenuSub aninha um nível; inset alinha itens sem ícone com os que têm.
104
104
  </Menu>
105
105
  ```
106
106
 
107
+ ## Propriedades de Menu
108
+
109
+ | Propriedade | Tipo | Padrão | Descrição |
110
+ |---|---|---|---|
111
+ | `open` | `boolean` | | Estado do painel no modo controlado, como no menu de contexto. |
112
+ | `onOpenChange` | `(open: boolean) => void` | | Chamado quando o painel abre ou fecha. |
113
+ | `defaultOpen` | `boolean` | `false` | Estado inicial no modo não controlado. |
114
+
107
115
  ## Propriedades de MenuItem
108
116
 
109
117
  | Propriedade | Tipo | Padrão | Descrição |
@@ -137,3 +145,22 @@ próprias além das de DOM.
137
145
  |---|---|---|---|
138
146
  | `value` | `string` | | Valor selecionado no grupo. |
139
147
  | `onValueChange` | `(value: string) => void` | | Chamado quando a pessoa seleciona outro `MenuRadioItem`. |
148
+
149
+ ## Propriedades de MenuRadioItem
150
+
151
+ | Propriedade | Tipo | Padrão | Descrição |
152
+ |---|---|---|---|
153
+ | `value` | `string` | | Valor que o item entrega ao `MenuRadioGroup` quando é selecionado. |
154
+ | `disabled` | `boolean` | `false` | Impede a seleção do item. |
155
+
156
+ ## Propriedades de MenuLabel
157
+
158
+ | Propriedade | Tipo | Padrão | Descrição |
159
+ |---|---|---|---|
160
+ | `inset` | `boolean` | | Alinha o rótulo com itens que possuem ícone. |
161
+
162
+ ## Propriedades de MenuSubTrigger
163
+
164
+ | Propriedade | Tipo | Padrão | Descrição |
165
+ |---|---|---|---|
166
+ | `inset` | `boolean` | | Alinha o gatilho do submenu sem ícone com os itens que possuem ícone. |