@softize/opus 12.10.0 → 13.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 +56 -0
- package/bin/lib/check.mjs +1098 -310
- package/bin/lib/copy.mjs +12 -5
- package/docs/adr/0003-dictionary-presentation-is-declared.md +3 -0
- package/docs/adr/0004-page-content-state-is-composed.md +65 -0
- package/docs/adr/0005-structural-surfaces-share-an-explicit-anatomy.md +180 -0
- package/docs/adr/0006-semantic-context-precedes-visual-variant.md +182 -0
- package/docs/adr/0007-toast-actions-form-an-ordered-collection.md +63 -0
- package/docs/adr/0008-hierarchical-navigation-is-composed-at-the-consumer-boundary.md +71 -0
- package/docs/radius-scale.md +1 -1
- package/package.json +1 -1
- package/registry/instructions/opus.md +5 -0
- package/registry/skills/build-opus-ui/SKILL.md +27 -16
- package/registry/skills/build-opus-ui/references/evaluations.md +16 -5
- package/registry/skills/build-opus-ui/references/ui-patterns.md +38 -15
- package/registry/skills/maintain-opus-docs/SKILL.md +83 -0
- package/registry/skills/maintain-opus-docs/agents/openai.yaml +4 -0
- package/registry/skills/maintain-opus-docs/references/editorial-standard.md +85 -0
- package/registry/skills/maintain-opus-docs/references/evaluations.md +34 -0
- package/registry/skills/maintain-opus-docs/scripts/audit-docs.mjs +81 -0
- package/registry/skills/model-opus-dictionary/SKILL.md +4 -2
- package/registry/skills/model-opus-dictionary/references/evaluations.md +4 -3
- package/registry/templates/app/src/App.tsx +1 -1
- package/src/core/dictionary.ts +52 -14
- package/src/core/index.ts +10 -0
- package/src/core/ui-context.ts +29 -0
- package/src/schema/drivers/zod.ts +17 -8
- package/src/ui/components/patterns/action-form-card.tsx +18 -12
- package/src/ui/components/patterns/confirm.tsx +163 -40
- package/src/ui/components/patterns/content-header.tsx +335 -61
- package/src/ui/components/patterns/data-state.tsx +23 -10
- package/src/ui/components/patterns/list.tsx +1097 -783
- package/src/ui/components/patterns/page-state.tsx +115 -0
- package/src/ui/components/patterns/page.tsx +231 -41
- package/src/ui/components/patterns/sidebar.tsx +357 -83
- package/src/ui/components/patterns/trigger.tsx +37 -30
- package/src/ui/components/patterns/view.tsx +7 -11
- package/src/ui/components/primitives/alert.tsx +298 -110
- package/src/ui/components/primitives/ask.tsx +2 -1
- package/src/ui/components/primitives/badge.tsx +91 -30
- package/src/ui/components/primitives/button.tsx +99 -60
- package/src/ui/components/primitives/calendar.tsx +39 -39
- package/src/ui/components/primitives/card.tsx +96 -23
- package/src/ui/components/primitives/detail.tsx +2 -2
- package/src/ui/components/primitives/dialog.tsx +196 -39
- package/src/ui/components/primitives/dictionary-value.tsx +9 -14
- package/src/ui/components/primitives/dot.tsx +74 -21
- package/src/ui/components/primitives/drawer.tsx +40 -24
- package/src/ui/components/primitives/empty.tsx +3 -3
- package/src/ui/components/primitives/item.tsx +135 -79
- package/src/ui/components/primitives/menu.tsx +11 -3
- package/src/ui/components/primitives/metric-card.tsx +133 -0
- package/src/ui/components/primitives/sonner.tsx +187 -8
- package/src/ui/components/primitives/table.tsx +2 -2
- package/src/ui/docs/DocBrowser.tsx +104 -25
- package/src/ui/docs/changelog.tsx +1 -1
- package/src/ui/docs/content/accordion.md +22 -16
- package/src/ui/docs/content/action-form-card.md +8 -8
- package/src/ui/docs/content/action-form-dialog.md +9 -9
- package/src/ui/docs/content/action-form.md +28 -34
- package/src/ui/docs/content/action-list-dialog.md +11 -6
- package/src/ui/docs/content/action-list.md +64 -39
- package/src/ui/docs/content/action-trigger.md +21 -14
- package/src/ui/docs/content/action-view.md +8 -8
- package/src/ui/docs/content/actions.md +9 -9
- package/src/ui/docs/content/ai.md +3 -3
- package/src/ui/docs/content/alert.md +54 -28
- package/src/ui/docs/content/aspect-ratio.md +4 -4
- package/src/ui/docs/content/audit.md +2 -2
- package/src/ui/docs/content/auth.md +3 -3
- package/src/ui/docs/content/avatar.md +34 -14
- package/src/ui/docs/content/badge.md +21 -22
- package/src/ui/docs/content/breadcrumb.md +13 -8
- package/src/ui/docs/content/button.md +93 -15
- package/src/ui/docs/content/calendar.md +5 -5
- package/src/ui/docs/content/card.md +6 -6
- package/src/ui/docs/content/carousel.md +16 -11
- package/src/ui/docs/content/chat.md +3 -3
- package/src/ui/docs/content/checkbox.md +7 -7
- package/src/ui/docs/content/cli.md +5 -5
- package/src/ui/docs/content/collapsible.md +8 -8
- package/src/ui/docs/content/command.md +16 -8
- package/src/ui/docs/content/composer.md +2 -2
- package/src/ui/docs/content/content.md +44 -0
- package/src/ui/docs/content/copyable.md +4 -3
- package/src/ui/docs/content/customization.md +7 -7
- package/src/ui/docs/content/cycle.md +3 -3
- package/src/ui/docs/content/data-state.md +11 -12
- package/src/ui/docs/content/data.md +26 -33
- package/src/ui/docs/content/detail.md +8 -5
- package/src/ui/docs/content/dialog.md +339 -31
- package/src/ui/docs/content/dictionary-value.md +19 -18
- package/src/ui/docs/content/dock.md +3 -3
- package/src/ui/docs/content/dot.md +7 -7
- package/src/ui/docs/content/drawer.md +32 -16
- package/src/ui/docs/content/empty-value.md +2 -2
- package/src/ui/docs/content/empty.md +19 -12
- package/src/ui/docs/content/events.md +4 -4
- package/src/ui/docs/content/field.md +34 -12
- package/src/ui/docs/content/getting-started.md +1 -1
- package/src/ui/docs/content/icon-picker.md +8 -4
- package/src/ui/docs/content/input-otp.md +20 -12
- package/src/ui/docs/content/input.md +121 -9
- package/src/ui/docs/content/item.md +64 -24
- package/src/ui/docs/content/kbd.md +19 -11
- package/src/ui/docs/content/label.md +5 -3
- package/src/ui/docs/content/log.md +4 -4
- package/src/ui/docs/content/markdown.md +7 -6
- package/src/ui/docs/content/mcp.md +13 -15
- package/src/ui/docs/content/menu.md +36 -17
- package/src/ui/docs/content/metric-card.md +41 -0
- package/src/ui/docs/content/observability.md +2 -2
- package/src/ui/docs/content/page.md +93 -10
- package/src/ui/docs/content/pagination.md +22 -17
- package/src/ui/docs/content/popover.md +16 -8
- package/src/ui/docs/content/progress.md +7 -5
- package/src/ui/docs/content/queue.md +5 -5
- package/src/ui/docs/content/radio-group.md +20 -12
- package/src/ui/docs/content/router.md +11 -6
- package/src/ui/docs/content/scheduler.md +4 -5
- package/src/ui/docs/content/scroll-area.md +12 -7
- package/src/ui/docs/content/select.md +42 -29
- package/src/ui/docs/content/semantic-context.md +63 -0
- package/src/ui/docs/content/separator.md +5 -5
- package/src/ui/docs/content/sidebar.md +325 -56
- package/src/ui/docs/content/skeleton.md +5 -4
- package/src/ui/docs/content/slider.md +8 -7
- package/src/ui/docs/content/spinner.md +8 -8
- package/src/ui/docs/content/split.md +8 -5
- package/src/ui/docs/content/storage.md +6 -8
- package/src/ui/docs/content/switch.md +8 -7
- package/src/ui/docs/content/table.md +16 -6
- package/src/ui/docs/content/tabs.md +28 -14
- package/src/ui/docs/content/testing.md +9 -11
- package/src/ui/docs/content/textarea.md +5 -4
- package/src/ui/docs/content/toast.md +47 -13
- package/src/ui/docs/content/toggle.md +75 -7
- package/src/ui/docs/content/tokens.md +31 -3
- package/src/ui/docs/content/tooltip.md +19 -11
- package/src/ui/docs/content/truncate.md +7 -8
- package/src/ui/docs/content/ui.md +10 -9
- package/src/ui/docs/content/upgrading.md +7 -8
- package/src/ui/docs/doc-client.tsx +2 -2
- package/src/ui/docs/registry.tsx +580 -229
- package/src/ui/lib/semantic-context.ts +30 -0
- package/src/ui/meta.ts +278 -286
- package/src/ui/react.tsx +377 -111
- package/src/ui/theme.css +116 -0
- package/src/ui/components/primitives/alert-dialog.tsx +0 -190
- package/src/ui/docs/content/alert-dialog.md +0 -73
- package/src/ui/docs/content/button-group.md +0 -71
- package/src/ui/docs/content/confirm.md +0 -120
- package/src/ui/docs/content/input-group.md +0 -78
- package/src/ui/docs/content/toggle-group.md +0 -81
|
@@ -7,7 +7,7 @@ title: Autenticação
|
|
|
7
7
|
Quem é o usuário, de qual tenant, e o que ele pode. O contrato é um adapter do core
|
|
8
8
|
(`AuthAdapter`): a cada request o runtime chama `resolveContext` e injeta o resultado no
|
|
9
9
|
handler — `ctx.user`, `ctx.tenantId`, `ctx.can`. O Opus **não** implementa RBAC/ABAC; ele
|
|
10
|
-
delega a decisão
|
|
10
|
+
delega a decisão para o `can` que o driver pluga.
|
|
11
11
|
|
|
12
12
|
## O contrato
|
|
13
13
|
|
|
@@ -31,7 +31,7 @@ política usada por ela.
|
|
|
31
31
|
import { jwtAuth } from '@softize/opus/auth/jwt'
|
|
32
32
|
import { betterAuthSession } from '@softize/opus/auth/better-auth'
|
|
33
33
|
|
|
34
|
-
// JWT: valida o token (HS256 por padrão) e mapeia o payload
|
|
34
|
+
// JWT: valida o token (HS256 por padrão) e mapeia o payload para o User.
|
|
35
35
|
const jwt = jwtAuth({ secret: process.env.JWT_SECRET! })
|
|
36
36
|
|
|
37
37
|
// better-auth: valida a sessão contra um IdP better-auth remoto.
|
|
@@ -44,7 +44,7 @@ const idp = betterAuthSession({
|
|
|
44
44
|
|
|
45
45
|
O `jwt` procura o token no `Authorization: Bearer`, em cookie ou custom (via `getToken`); o
|
|
46
46
|
`secret` pode ser string ou um resolver async por `kid`. O `betterAuthSession` faz fetch da
|
|
47
|
-
sessão no IdP (`timeoutMs`, default 5s) e mapeia
|
|
47
|
+
sessão no IdP (`timeoutMs`, default 5s) e mapeia para o `User`/tenant/can (o `can` default nega
|
|
48
48
|
tudo — plugue o seu).
|
|
49
49
|
|
|
50
50
|
## No runtime
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
##
|
|
1
|
+
## Retrato com imagem
|
|
2
2
|
|
|
3
3
|
AvatarImage com src/alt e AvatarFallback com as iniciais — o fallback aparece enquanto a imagem
|
|
4
4
|
carrega ou se ela falha.
|
|
@@ -12,8 +12,8 @@ carrega ou se ela falha.
|
|
|
12
12
|
|
|
13
13
|
## Fallback de iniciais
|
|
14
14
|
|
|
15
|
-
Sem AvatarImage (ou com src quebrado), só o AvatarFallback renderiza — iniciais
|
|
16
|
-
|
|
15
|
+
Sem AvatarImage (ou com src quebrado), só o AvatarFallback renderiza — iniciais para pessoa, ícone
|
|
16
|
+
para agente.
|
|
17
17
|
|
|
18
18
|
```tsx preview
|
|
19
19
|
<Avatar>
|
|
@@ -28,7 +28,7 @@ pra agente.
|
|
|
28
28
|
|
|
29
29
|
## Tamanhos
|
|
30
30
|
|
|
31
|
-
size sm/default/lg — o fallback acompanha o tamanho. sm
|
|
31
|
+
size sm/default/lg — o fallback acompanha o tamanho. sm para listas densas, lg para cabeçalho de
|
|
32
32
|
workspace.
|
|
33
33
|
|
|
34
34
|
```tsx preview
|
|
@@ -45,8 +45,8 @@ workspace.
|
|
|
45
45
|
|
|
46
46
|
## Com selo de status
|
|
47
47
|
|
|
48
|
-
AvatarBadge é o ponto no canto inferior — verde
|
|
49
|
-
|
|
48
|
+
AvatarBadge é o ponto no canto inferior — verde para o agente developer rodando uma sessão, cinza
|
|
49
|
+
para o ocioso. Tinja com className.
|
|
50
50
|
|
|
51
51
|
```tsx preview
|
|
52
52
|
<Avatar>
|
|
@@ -82,13 +82,33 @@ excedente — os membros do workspace Empresa X.
|
|
|
82
82
|
</AvatarGroup>
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
##
|
|
85
|
+
## Propriedades de Avatar
|
|
86
86
|
|
|
87
|
-
|
|
|
87
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
88
88
|
|---|---|---|---|
|
|
89
|
-
| `size`
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
|
94
|
-
|
|
89
|
+
| `size` | `'sm' \| 'default' \| 'lg'` | `'default'` | Diâmetro do retrato; o fallback e o selo acompanham a escala. |
|
|
90
|
+
|
|
91
|
+
## Propriedades de AvatarImage
|
|
92
|
+
|
|
93
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
94
|
+
|---|---|---|---|
|
|
95
|
+
| `src` | `string` | | URL da imagem. Enquanto ela carrega ou quando falha, `AvatarFallback` ocupa o lugar. |
|
|
96
|
+
| `alt` | `string` | | Texto alternativo que identifica a pessoa ou o agente. |
|
|
97
|
+
|
|
98
|
+
## Propriedades de AvatarFallback
|
|
99
|
+
|
|
100
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
101
|
+
|---|---|---|---|
|
|
102
|
+
| `children` | `React.ReactNode` | | Iniciais ou ícone exibido quando a imagem não está disponível. |
|
|
103
|
+
|
|
104
|
+
## Propriedades de AvatarBadge
|
|
105
|
+
|
|
106
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
107
|
+
|---|---|---|---|
|
|
108
|
+
| `className` | `string` | | Classes usadas para comunicar visualmente o status no selo. |
|
|
109
|
+
|
|
110
|
+
## Propriedades de AvatarGroupCount
|
|
111
|
+
|
|
112
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
113
|
+
|---|---|---|---|
|
|
114
|
+
| `children` | `React.ReactNode` | | Quantidade excedente no fim do grupo, como `+3`. |
|
|
@@ -1,35 +1,33 @@
|
|
|
1
|
-
##
|
|
1
|
+
## Contexto e variante
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Badge é não-interativo — para clique, use Button. `context` comunica o significado; `variant`
|
|
4
|
+
escolhe entre preenchimento sólido, superfície sutil ou contorno.
|
|
5
5
|
|
|
6
6
|
```tsx preview
|
|
7
|
-
<Badge>Agente</Badge>
|
|
8
|
-
<Badge variant="
|
|
9
|
-
<Badge variant="
|
|
10
|
-
<Badge variant="destructive">Arquivado</Badge>
|
|
7
|
+
<Badge context="neutral">Agente</Badge>
|
|
8
|
+
<Badge context="neutral" variant="outline">Monorepo</Badge>
|
|
9
|
+
<Badge context="danger" variant="solid">Arquivado</Badge>
|
|
11
10
|
```
|
|
12
11
|
|
|
13
|
-
##
|
|
12
|
+
## Contextos de status
|
|
14
13
|
|
|
15
|
-
success
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
`DictionaryValue`, que escolhe o tom pela metadata em vez de repetir esta escolha em cada tela.
|
|
14
|
+
`success`, `warning`, `info` e `danger` usam `subtle` por padrão. Valor de dicionário com papel
|
|
15
|
+
declarado usa `DictionaryValue`, que escolhe o contexto pela metadata em vez de repetir esta
|
|
16
|
+
decisão em cada tela.
|
|
19
17
|
|
|
20
18
|
```tsx preview
|
|
21
|
-
<Badge
|
|
22
|
-
<Badge
|
|
23
|
-
<Badge
|
|
24
|
-
<Badge
|
|
19
|
+
<Badge context="success">Ativa</Badge>
|
|
20
|
+
<Badge context="warning">Aguardando revisor</Badge>
|
|
21
|
+
<Badge context="info">Em sessão</Badge>
|
|
22
|
+
<Badge context="danger">Bloqueada</Badge>
|
|
25
23
|
```
|
|
26
24
|
|
|
27
25
|
## Com ícone
|
|
28
26
|
|
|
29
|
-
Um svg filho ganha size-3 automaticamente — bom
|
|
27
|
+
Um svg filho ganha size-3 automaticamente — bom para reforçar o estado sem crescer o rótulo.
|
|
30
28
|
|
|
31
29
|
```tsx preview
|
|
32
|
-
<Badge
|
|
30
|
+
<Badge context="success"><CircleCheck /> Regressão verde</Badge>
|
|
33
31
|
```
|
|
34
32
|
|
|
35
33
|
## Como link (asChild)
|
|
@@ -38,14 +36,15 @@ asChild renderiza o filho (Radix Slot) — um `<a>` com cara de badge, com hover
|
|
|
38
36
|
variantes.
|
|
39
37
|
|
|
40
38
|
```tsx preview
|
|
41
|
-
<Badge asChild variant="
|
|
39
|
+
<Badge asChild context="neutral" variant="solid">
|
|
42
40
|
<a href="#" onClick={(e) => e.preventDefault()}>Empresa X</a>
|
|
43
41
|
</Badge>
|
|
44
42
|
```
|
|
45
43
|
|
|
46
|
-
##
|
|
44
|
+
## Propriedades de Badge
|
|
47
45
|
|
|
48
|
-
|
|
|
46
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
49
47
|
|---|---|---|---|
|
|
50
|
-
| `
|
|
48
|
+
| `context` | `'neutral' \| 'primary' \| 'info' \| 'success' \| 'warning' \| 'danger'` | `'neutral'` | O significado ou destaque contextual. |
|
|
49
|
+
| `variant` | `'solid' \| 'subtle' \| 'outline'` | `'subtle'` | O tratamento visual aplicado ao contexto. |
|
|
51
50
|
| `asChild` | `boolean` | `false` | Renderiza como o filho (Radix Slot) em vez de `<span>` — ex.: um `<a>` com cara de badge. |
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
##
|
|
1
|
+
## Caminho atual
|
|
2
2
|
|
|
3
3
|
A composição é manual: BreadcrumbLink nos níveis navegáveis, BreadcrumbPage no atual (não
|
|
4
4
|
clicável, aria-current=page) e um BreadcrumbSeparator entre cada item.
|
|
@@ -23,7 +23,7 @@ clicável, aria-current=page) e um BreadcrumbSeparator entre cada item.
|
|
|
23
23
|
|
|
24
24
|
## Com ícone e separador custom
|
|
25
25
|
|
|
26
|
-
O primeiro nível pode levar um ícone do lucide. BreadcrumbSeparator aceita children
|
|
26
|
+
O primeiro nível pode levar um ícone do lucide. BreadcrumbSeparator aceita children para trocar o
|
|
27
27
|
chevron padrão por outro glifo (aqui, uma barra).
|
|
28
28
|
|
|
29
29
|
```tsx preview col-start
|
|
@@ -53,7 +53,7 @@ chevron padrão por outro glifo (aqui, uma barra).
|
|
|
53
53
|
|
|
54
54
|
## Colapsado
|
|
55
55
|
|
|
56
|
-
Trilha funda demais
|
|
56
|
+
Trilha funda demais para o espaço: BreadcrumbEllipsis substitui os níveis do meio (que viram um
|
|
57
57
|
menu/popover) e mantém só a raiz e o destino.
|
|
58
58
|
|
|
59
59
|
```tsx preview col-start
|
|
@@ -78,10 +78,15 @@ menu/popover) e mantém só a raiz e o destino.
|
|
|
78
78
|
</Breadcrumb>
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
##
|
|
81
|
+
## Propriedades de BreadcrumbLink
|
|
82
82
|
|
|
83
|
-
|
|
|
83
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
84
84
|
|---|---|---|---|
|
|
85
|
-
| `asChild`
|
|
86
|
-
| `href`
|
|
87
|
-
|
|
85
|
+
| `asChild` | `boolean` | `false` | Repassa as propriedades ao filho para integrar o link do roteador no lugar de `<a>`. |
|
|
86
|
+
| `href` | `string` | | Destino do nível navegável. |
|
|
87
|
+
|
|
88
|
+
## Propriedades de BreadcrumbSeparator
|
|
89
|
+
|
|
90
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
91
|
+
|---|---|---|---|
|
|
92
|
+
| `children` | `React.ReactNode` | `<ChevronRight />` | Elemento entre os itens. Omita para usar o chevron padrão ou passe outro ícone. |
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
##
|
|
1
|
+
## Contexto e variante
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
`context` declara a hierarquia ou o risco da ação; `variant` escolhe o tratamento visual. Use
|
|
4
|
+
`primary` para a ação principal, `neutral` para ações de apoio e `danger` quando a ação tiver uma
|
|
5
|
+
consequência perigosa. `default`, `secondary` e `destructive` permanecem apenas como aliases de
|
|
6
|
+
compatibilidade.
|
|
5
7
|
|
|
6
8
|
```tsx preview
|
|
7
9
|
<Button>Criar workspace</Button>
|
|
8
|
-
<Button variant="
|
|
9
|
-
<Button variant="outline">Ver prévia</Button>
|
|
10
|
-
<Button variant="ghost">Cancelar</Button>
|
|
11
|
-
<Button variant="
|
|
12
|
-
<Button variant="link">Ver documentação</Button>
|
|
10
|
+
<Button context="neutral" variant="solid">Duplicar</Button>
|
|
11
|
+
<Button context="neutral" variant="outline">Ver prévia</Button>
|
|
12
|
+
<Button context="neutral" variant="ghost">Cancelar</Button>
|
|
13
|
+
<Button context="danger" variant="solid">Excluir</Button>
|
|
14
|
+
<Button context="primary" variant="link">Ver documentação</Button>
|
|
13
15
|
```
|
|
14
16
|
|
|
15
17
|
## Tamanhos
|
|
@@ -29,7 +31,7 @@ O tamanho icon exige `aria-label`, porque não há texto visível. Os botões s
|
|
|
29
31
|
|
|
30
32
|
busy = ação em andamento (DEPOIS do clique): o Spinner e o disabled vêm do botão. Com icon, o
|
|
31
33
|
Spinner TROCA o ícone (não soma). Não confunda com carregar conteúdo (ANTES) — isso é Spinner
|
|
32
|
-
centralizado/Skeleton
|
|
34
|
+
centralizado/Skeleton em um nível de página.
|
|
33
35
|
|
|
34
36
|
```tsx preview
|
|
35
37
|
<Button disabled>Desabilitado</Button>
|
|
@@ -41,7 +43,7 @@ centralizado/Skeleton num nível de página.
|
|
|
41
43
|
## Como outro elemento (asChild)
|
|
42
44
|
|
|
43
45
|
Âncora com cara de botão: asChild renderiza o filho (Radix Slot) — sem forkar estilo.
|
|
44
|
-
buttonVariants serve
|
|
46
|
+
buttonVariants serve para o caso sem filho único.
|
|
45
47
|
|
|
46
48
|
```tsx preview
|
|
47
49
|
<Button asChild variant="outline">
|
|
@@ -49,12 +51,88 @@ buttonVariants serve pro caso sem filho único.
|
|
|
49
51
|
</Button>
|
|
50
52
|
```
|
|
51
53
|
|
|
52
|
-
##
|
|
54
|
+
## Propriedades de Button
|
|
53
55
|
|
|
54
|
-
|
|
|
56
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
55
57
|
|---|---|---|---|
|
|
56
|
-
| `
|
|
58
|
+
| `context` | `'neutral' \| 'primary' \| 'danger'` | `'primary'` | A hierarquia ou o risco comunicado pela ação. |
|
|
59
|
+
| `variant` | `'solid' \| 'subtle' \| 'outline' \| 'ghost' \| 'link'` | `'solid'` | O tratamento visual aplicado ao contexto. |
|
|
57
60
|
| `size` | `'default' \| 'sm' \| 'lg' \| 'icon' \| 'icon-sm' \| 'icon-xs'` | `'default'` | O tamanho. Os icon* são quadrados (2.25/2/1.5rem) para botões só de ícone, com `aria-label`. |
|
|
58
|
-
| `asChild` | `boolean` | `false` | Renderiza como o filho (Radix Slot) em vez de `<button>` —
|
|
59
|
-
| `busy` | `boolean` | `false` | Ação em andamento (depois do clique): mostra Spinner + desabilita. Não é "carregando" de conteúdo (que é Spinner/Skeleton
|
|
61
|
+
| `asChild` | `boolean` | `false` | Renderiza como o filho (Radix Slot) em vez de `<button>` — para âncoras e afins. |
|
|
62
|
+
| `busy` | `boolean` | `false` | Ação em andamento (depois do clique): mostra Spinner + desabilita. Não é "carregando" de conteúdo (que é Spinner/Skeleton em um nível de página). |
|
|
60
63
|
| `icon` | `React.ElementType` | | Ícone à esquerda (ex.: icon={Plus}). No busy é trocado pelo Spinner — não soma. |
|
|
64
|
+
|
|
65
|
+
## ButtonGroup
|
|
66
|
+
|
|
67
|
+
Use `ButtonGroup` quando ações relacionadas precisarem formar um bloco contínuo. As bordas internas
|
|
68
|
+
colapsam e somente as pontas externas permanecem arredondadas. Mantenha a mesma variante nos filhos
|
|
69
|
+
para preservar a unidade visual.
|
|
70
|
+
|
|
71
|
+
```tsx preview
|
|
72
|
+
<ButtonGroup>
|
|
73
|
+
<Button variant="outline">Visão geral</Button>
|
|
74
|
+
<Button variant="outline">Sessões</Button>
|
|
75
|
+
<Button variant="outline">Habilidades</Button>
|
|
76
|
+
</ButtonGroup>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Ação dividida
|
|
80
|
+
|
|
81
|
+
Combine a ação principal, um separador e um botão de ícone quando o mesmo comando oferecer
|
|
82
|
+
variações.
|
|
83
|
+
|
|
84
|
+
```tsx preview
|
|
85
|
+
<ButtonGroup>
|
|
86
|
+
<Button icon={Play}>Rodar agente developer</Button>
|
|
87
|
+
<ButtonGroupSeparator />
|
|
88
|
+
<Button size="icon" aria-label="Mais opções">
|
|
89
|
+
<ChevronDown />
|
|
90
|
+
</Button>
|
|
91
|
+
</ButtonGroup>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Com rótulo
|
|
95
|
+
|
|
96
|
+
`ButtonGroupText` adiciona um contexto inerte ao grupo. Ele também aceita `asChild` para assumir a
|
|
97
|
+
semântica de outro elemento, como `label`.
|
|
98
|
+
|
|
99
|
+
```tsx preview
|
|
100
|
+
<ButtonGroup>
|
|
101
|
+
<ButtonGroupText>
|
|
102
|
+
<GitBranch />
|
|
103
|
+
empresa-x-api
|
|
104
|
+
</ButtonGroupText>
|
|
105
|
+
<Button variant="outline" icon={RotateCw}>Sincronizar</Button>
|
|
106
|
+
</ButtonGroup>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Vertical
|
|
110
|
+
|
|
111
|
+
`orientation="vertical"` empilha os filhos e transfere a junção das bordas para o eixo vertical.
|
|
112
|
+
|
|
113
|
+
```tsx preview col-start
|
|
114
|
+
<ButtonGroup orientation="vertical">
|
|
115
|
+
<Button variant="outline" size="icon" aria-label="Rodar sessão"><Play /></Button>
|
|
116
|
+
<Button variant="outline" size="icon" aria-label="Pausar sessão"><Pause /></Button>
|
|
117
|
+
<Button variant="outline" size="icon" aria-label="Reiniciar sessão"><RotateCw /></Button>
|
|
118
|
+
</ButtonGroup>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Propriedades de ButtonGroup
|
|
122
|
+
|
|
123
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
124
|
+
|---|---|---|---|
|
|
125
|
+
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Direção do bloco e do colapso das bordas. |
|
|
126
|
+
| `shape` | `'default' \| 'pill'` | `'default'` | Geometria das extremidades externas do grupo. |
|
|
127
|
+
|
|
128
|
+
### Propriedades de ButtonGroupSeparator
|
|
129
|
+
|
|
130
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
131
|
+
|---|---|---|---|
|
|
132
|
+
| `orientation` | `'horizontal' \| 'vertical'` | `'vertical'` | Direção do traço divisor; use vertical em grupos horizontais. |
|
|
133
|
+
|
|
134
|
+
### Propriedades de ButtonGroupText
|
|
135
|
+
|
|
136
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
137
|
+
|---|---|---|---|
|
|
138
|
+
| `asChild` | `boolean` | `false` | Renderiza como o filho para assumir outra semântica sem perder o estilo. |
|
|
@@ -17,7 +17,7 @@ render(
|
|
|
17
17
|
|
|
18
18
|
## Intervalo
|
|
19
19
|
|
|
20
|
-
mode=range guarda { from, to } — o padrão
|
|
20
|
+
mode=range guarda { from, to } — o padrão para filtrar sessões por janela de datas. O primeiro clique fixa o início; o segundo, o fim.
|
|
21
21
|
|
|
22
22
|
```tsx preview
|
|
23
23
|
const [week, setWeek] = useState<DateRange | undefined>({
|
|
@@ -37,7 +37,7 @@ render(
|
|
|
37
37
|
|
|
38
38
|
## Navegação por dropdown
|
|
39
39
|
|
|
40
|
-
captionLayout=dropdown troca o título do mês por seletores de mês e ano — bom
|
|
40
|
+
captionLayout=dropdown troca o título do mês por seletores de mês e ano — bom para pular para um período distante (ex.: histórico de um repositório) sem clicar mês a mês.
|
|
41
41
|
|
|
42
42
|
```tsx preview
|
|
43
43
|
<Calendar
|
|
@@ -47,16 +47,16 @@ captionLayout=dropdown troca o título do mês por seletores de mês e ano — b
|
|
|
47
47
|
/>
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
##
|
|
50
|
+
## Propriedades de Calendar
|
|
51
51
|
|
|
52
|
-
|
|
|
52
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
53
53
|
|---|---|---|---|
|
|
54
54
|
| `mode` | `'single' \| 'multiple' \| 'range'` | | O tipo de seleção — define o formato de selected/onSelect (Date, Date[] ou { from, to }). |
|
|
55
55
|
| `selected` | `Date \| Date[] \| DateRange` | | A seleção atual no modo controlado — o formato segue o mode. Pareie com onSelect. |
|
|
56
56
|
| `onSelect` | `(selected) => void` | | Chamado quando o usuário escolhe uma data. O argumento segue o mode. |
|
|
57
57
|
| `defaultMonth` | `Date` | | O mês exibido ao montar, sem afetar a seleção. |
|
|
58
58
|
| `captionLayout` | `'label' \| 'dropdown' \| 'dropdown-months' \| 'dropdown-years'` | `'label'` | Como o título do mês aparece — label é texto fixo; dropdown vira seletores de mês e ano. |
|
|
59
|
-
| `numberOfMonths` | `number` | `1` | Quantos meses mostrar lado a lado — útil
|
|
59
|
+
| `numberOfMonths` | `number` | `1` | Quantos meses mostrar lado a lado — útil para escolher um intervalo longo. |
|
|
60
60
|
| `disabled` | `Matcher` | | Datas não selecionáveis — uma Date, um array, um { from, to } ou um predicado (date) => boolean. |
|
|
61
61
|
| `buttonVariant` | `Button['variant']` | `'ghost'` | A variante dos botões de navegação (anterior/próximo). |
|
|
62
62
|
| `showOutsideDays` | `boolean` | `true` | Mostra os dias do mês vizinho que completam a primeira e a última semana. |
|
|
@@ -10,7 +10,7 @@ O uso mais comum: a superfície de conteúdo em repouso (`rounded-xl` + `border`
|
|
|
10
10
|
|
|
11
11
|
## Estruturado (header / conteúdo / rodapé)
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Para painel com estrutura: cada slot é dono do próprio padding (como o Dialog). CardTitle/CardDescription no header; CardFooter alinha as ações.
|
|
14
14
|
|
|
15
15
|
```tsx preview col
|
|
16
16
|
<Card>
|
|
@@ -18,9 +18,9 @@ Pra painel com estrutura: cada slot é dono do próprio padding (como o Dialog).
|
|
|
18
18
|
<CardTitle>Empresa X</CardTitle>
|
|
19
19
|
<CardDescription>2 repositórios · 3 agentes vinculados.</CardDescription>
|
|
20
20
|
</CardHeader>
|
|
21
|
-
<
|
|
21
|
+
<CardBody>
|
|
22
22
|
<p className="text-sm text-muted-foreground">Última sessão concluída há 2 horas.</p>
|
|
23
|
-
</
|
|
23
|
+
</CardBody>
|
|
24
24
|
<CardFooter className="gap-2">
|
|
25
25
|
<Button size="sm">Abrir sessão</Button>
|
|
26
26
|
<Button size="sm" variant="outline">Ver repositórios</Button>
|
|
@@ -38,11 +38,11 @@ Pra painel com estrutura: cada slot é dono do próprio padding (como o Dialog).
|
|
|
38
38
|
<CardTitle>Skill code-style</CardTitle>
|
|
39
39
|
<CardDescription>Padrão softize de código e microcopy.</CardDescription>
|
|
40
40
|
</CardHeader>
|
|
41
|
-
<
|
|
41
|
+
<CardBody>
|
|
42
42
|
<p className="text-sm text-muted-foreground">Vinculada a 4 agentes neste workspace.</p>
|
|
43
|
-
</
|
|
43
|
+
</CardBody>
|
|
44
44
|
<CardFooter className="justify-between border-t">
|
|
45
|
-
<Badge
|
|
45
|
+
<Badge context="success">Publicada</Badge>
|
|
46
46
|
<Button size="sm" variant="outline">Editar skill</Button>
|
|
47
47
|
</CardFooter>
|
|
48
48
|
</Card>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
##
|
|
1
|
+
## Um slide por vez
|
|
2
2
|
|
|
3
|
-
Compõe Carousel>CarouselContent>CarouselItem, com CarouselPrevious/CarouselNext
|
|
3
|
+
Compõe Carousel>CarouselContent>CarouselItem, com CarouselPrevious/CarouselNext para navegar. As setas ficam fora do trilho (-left-12/-right-12), então reserve a margem lateral no entorno.
|
|
4
4
|
|
|
5
5
|
```tsx preview
|
|
6
6
|
<Carousel className="mx-12 w-full max-w-xs">
|
|
@@ -28,7 +28,7 @@ Compõe Carousel>CarouselContent>CarouselItem, com CarouselPrevious/CarouselNext
|
|
|
28
28
|
|
|
29
29
|
## Vários por vista
|
|
30
30
|
|
|
31
|
-
O basis do CarouselItem decide quantos cabem na vista — basis-1/3 mostra três slides por vez. Bom
|
|
31
|
+
O basis do CarouselItem decide quantos cabem na vista — basis-1/3 mostra três slides por vez. Bom para galeria de workspaces ou repositórios.
|
|
32
32
|
|
|
33
33
|
```tsx preview
|
|
34
34
|
<Carousel className="mx-12 w-full max-w-sm" opts={{ align: 'start' }}>
|
|
@@ -48,7 +48,7 @@ O basis do CarouselItem decide quantos cabem na vista — basis-1/3 mostra três
|
|
|
48
48
|
|
|
49
49
|
## Vertical
|
|
50
50
|
|
|
51
|
-
orientation=vertical empilha os slides; as setas migram
|
|
51
|
+
orientation=vertical empilha os slides; as setas migram para cima e para baixo (-top-12/-bottom-12). Dê uma altura ao CarouselContent para delimitar a vista.
|
|
52
52
|
|
|
53
53
|
```tsx preview
|
|
54
54
|
<Carousel className="w-full max-w-xs" orientation="vertical">
|
|
@@ -74,12 +74,17 @@ orientation=vertical empilha os slides; as setas migram pra cima e pra baixo (-t
|
|
|
74
74
|
</Carousel>
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
##
|
|
77
|
+
## Propriedades de Carousel
|
|
78
78
|
|
|
79
|
-
|
|
|
79
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
80
80
|
|---|---|---|---|
|
|
81
|
-
| `orientation
|
|
82
|
-
| `opts
|
|
83
|
-
| `setApi
|
|
84
|
-
| `plugins
|
|
85
|
-
|
|
81
|
+
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Eixo do deslocamento. No modo vertical, os slides são empilhados e as setas apontam para cima e para baixo. |
|
|
82
|
+
| `opts` | `CarouselOptions` | | Opções repassadas ao Embla, como `{ loop: true }` ou `{ align: 'start' }`. |
|
|
83
|
+
| `setApi` | `(api: CarouselApi) => void` | | Recebe a instância para controle externo, como navegar com `scrollTo` ou ler o slide ativo. |
|
|
84
|
+
| `plugins` | `CarouselPlugin[]` | | Plugins do Embla associados ao carrossel, como autoplay. |
|
|
85
|
+
|
|
86
|
+
## Propriedades de CarouselItem
|
|
87
|
+
|
|
88
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
89
|
+
|---|---|---|---|
|
|
90
|
+
| `className` | `string` | | Classes de dimensão; a base define quantos slides cabem na área visível. |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
##
|
|
1
|
+
## Conversa com resposta integral
|
|
2
2
|
|
|
3
|
-
Um chat mínimo: lista de mensagens + composer. A conversa é gerenciada por dentro (estado, loading, auto-scroll; **Enter** envia, **Shift+Enter** quebra linha) — a inteligência vem da prop `send`. Com o composer vazio, **↑** recupera as mensagens anteriores do usuário e **↓** volta em direção ao rascunho; durante a edição, as setas continuam movendo o cursor normalmente. O `greeting` é o estado vazio (centrado; some quando a conversa começa e
|
|
3
|
+
Um chat mínimo: lista de mensagens + composer. A conversa é gerenciada por dentro (estado, loading, auto-scroll; **Enter** envia, **Shift+Enter** quebra linha) — a inteligência vem da prop `send`. Com o composer vazio, **↑** recupera as mensagens anteriores do usuário e **↓** volta em direção ao rascunho; durante a edição, as setas continuam movendo o cursor normalmente. O `greeting` é o estado vazio (centrado; some quando a conversa começa e não entra no transcript). Dê altura ao container.
|
|
4
4
|
|
|
5
5
|
```tsx preview
|
|
6
6
|
<div className="h-96 rounded-lg border">
|
|
@@ -9,7 +9,7 @@ Um chat mínimo: lista de mensagens + composer. A conversa é gerenciada por den
|
|
|
9
9
|
send={async (messages) => {
|
|
10
10
|
await new Promise((r) => setTimeout(r, 500))
|
|
11
11
|
const last = messages[messages.length - 1]
|
|
12
|
-
return `Você disse: "${last.content}". (
|
|
12
|
+
return `Você disse: "${last.content}". (Em um app real, aqui rodaria o agente.)`
|
|
13
13
|
}}
|
|
14
14
|
/>
|
|
15
15
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
##
|
|
1
|
+
## Escolha booleana
|
|
2
2
|
|
|
3
|
-
Sempre em par com Label (htmlFor↔id) — clicar no texto alterna a caixa. defaultChecked
|
|
3
|
+
Sempre em par com Label (htmlFor↔id) — clicar no texto alterna a caixa. defaultChecked para o modo não controlado.
|
|
4
4
|
|
|
5
5
|
```tsx preview
|
|
6
6
|
<div className="flex items-center gap-2">
|
|
@@ -11,7 +11,7 @@ Sempre em par com Label (htmlFor↔id) — clicar no texto alterna a caixa. defa
|
|
|
11
11
|
|
|
12
12
|
## Controlado
|
|
13
13
|
|
|
14
|
-
onCheckedChange recebe boolean | 'indeterminate' — compare com true
|
|
14
|
+
onCheckedChange recebe boolean | 'indeterminate' — compare com true para guardar um boolean.
|
|
15
15
|
|
|
16
16
|
```tsx preview
|
|
17
17
|
const [autoReview, setAutoReview] = useState(true)
|
|
@@ -30,7 +30,7 @@ render(
|
|
|
30
30
|
|
|
31
31
|
## Lista de opções
|
|
32
32
|
|
|
33
|
-
Várias caixas, um estado: o conjunto marcado é a lista de valores — o padrão
|
|
33
|
+
Várias caixas, um estado: o conjunto marcado é a lista de valores — o padrão para anexar skills a um agente.
|
|
34
34
|
|
|
35
35
|
```tsx preview col-start
|
|
36
36
|
const [skills, setSkills] = useState(['clean-code', 'test'])
|
|
@@ -65,11 +65,11 @@ disabled esmaece a caixa e o rótulo em par (peer-disabled no Label) — marcado
|
|
|
65
65
|
</div>
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
##
|
|
68
|
+
## Propriedades de Checkbox
|
|
69
69
|
|
|
70
|
-
|
|
|
70
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
71
71
|
|---|---|---|---|
|
|
72
72
|
| `checked` | `boolean \| 'indeterminate'` | | O estado, no modo controlado — parear com onCheckedChange. |
|
|
73
|
-
| `onCheckedChange` | `(checked: boolean \| 'indeterminate') => void` | | Chamado a cada alternância.
|
|
73
|
+
| `onCheckedChange` | `(checked: boolean \| 'indeterminate') => void` | | Chamado a cada alternância. Para guardar um boolean, compare com true. |
|
|
74
74
|
| `defaultChecked` | `boolean` | `false` | Estado inicial no modo não controlado. |
|
|
75
75
|
| `disabled` | `boolean` | `false` | Esmaece e bloqueia — o Label em par esmaece junto (peer-disabled). |
|
|
@@ -5,7 +5,7 @@ title: CLI opus
|
|
|
5
5
|
# CLI opus
|
|
6
6
|
|
|
7
7
|
O Opus traz um CLI que cobre o ciclo: faz o bootstrap, gera artefatos a partir das declarações,
|
|
8
|
-
valida as convenções e expõe o estado vivo
|
|
8
|
+
valida as convenções e expõe o estado vivo para os agentes via MCP.
|
|
9
9
|
|
|
10
10
|
## Gates
|
|
11
11
|
|
|
@@ -38,7 +38,7 @@ mesma CLI.
|
|
|
38
38
|
## Geração e introspecção
|
|
39
39
|
|
|
40
40
|
> As declarações (`description` de entidades/actions) são a fonte; o `gen` as projeta. O manifest
|
|
41
|
-
> é um lockfile
|
|
41
|
+
> é um lockfile versionado. A diferença do manifest torna a revisão objetiva.
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
44
|
opus gen # manifest / openapi / docs / stubs a partir do opus.config.ts
|
|
@@ -57,17 +57,17 @@ opus create meu-cliente --monorepo # a RAIZ de um workspace (apps/* + packages/
|
|
|
57
57
|
opus create apps/portal # dentro de um workspace: só o app (modo detectado)
|
|
58
58
|
opus setup # grava opus.json e materializa a camada específica do SDK
|
|
59
59
|
opus list # lista os templates disponíveis
|
|
60
|
-
opus add action-form # copia um template do catálogo
|
|
60
|
+
opus add action-form # copia um template do catálogo para o projeto
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
O esqueleto do `create` versiona com o Opus (sai do mesmo pacote que o SDK que ele
|
|
64
64
|
configura) e nasce com os gates verdes: domínio-exemplo canônico, teste, manifest e o dev
|
|
65
|
-
server pronto
|
|
65
|
+
server pronto para o preview do Maestro. O método geral, a memória e a revisão vêm da Base
|
|
66
66
|
depois de `pnpm run setup`. Dois modos, por detecção:
|
|
67
67
|
repo standalone (template inteiro) ou **app em monorepo** (dentro de um workspace pnpm:
|
|
68
68
|
só os arquivos do app; o que a raiz precisa ter vira aviso, sem clobber).
|
|
69
69
|
|
|
70
|
-
## MCP — estado vivo
|
|
70
|
+
## MCP — estado vivo para os agentes
|
|
71
71
|
|
|
72
72
|
> O server MCP expõe introspecção, check e scaffold de action. É como um agente lê a estrutura e cria
|
|
73
73
|
> action no formato canônico sem decorar convenção.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
##
|
|
1
|
+
## Seção recolhível
|
|
2
2
|
|
|
3
3
|
CollapsibleTrigger alterna o CollapsibleContent — o Trigger já é o <button>. defaultOpen deixa o estado com o componente.
|
|
4
4
|
|
|
@@ -18,7 +18,7 @@ CollapsibleTrigger alterna o CollapsibleContent — o Trigger já é o <button>.
|
|
|
18
18
|
|
|
19
19
|
## Controlado
|
|
20
20
|
|
|
21
|
-
open + onOpenChange põem o estado nas suas mãos — dá
|
|
21
|
+
open + onOpenChange põem o estado nas suas mãos — dá para refletir no gatilho (aqui o chevron gira) ou guardar a preferência.
|
|
22
22
|
|
|
23
23
|
```tsx preview col
|
|
24
24
|
const [open, setOpen] = useState(false)
|
|
@@ -54,11 +54,11 @@ disabled no Collapsible trava o gatilho — a seção fica fixa no estado atual
|
|
|
54
54
|
</Collapsible>
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
##
|
|
57
|
+
## Propriedades de Collapsible
|
|
58
58
|
|
|
59
|
-
|
|
|
59
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
60
60
|
|---|---|---|---|
|
|
61
|
-
| `defaultOpen
|
|
62
|
-
| `open
|
|
63
|
-
| `onOpenChange
|
|
64
|
-
| `disabled
|
|
61
|
+
| `defaultOpen` | `boolean` | `false` | Estado inicial no modo não controlado. |
|
|
62
|
+
| `open` | `boolean` | | Estado no modo controlado. Use com `onOpenChange`. |
|
|
63
|
+
| `onOpenChange` | `(open: boolean) => void` | | Chamado a cada abertura ou fechamento. |
|
|
64
|
+
| `disabled` | `boolean` | `false` | Bloqueia o gatilho e mantém a seção no estado atual. |
|