@softize/opus 22.2.0 → 24.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +120 -1
- package/bin/cli.mjs +3 -9
- package/bin/lib/check.mjs +242 -49
- package/bin/lib/copy.mjs +17 -35
- package/bin/lib/gen-runner.mjs +2 -0
- package/bin/lib/gen-stubs.mjs +3 -1
- package/docs/adr/0005-structural-surfaces-share-an-explicit-anatomy.md +1 -1
- package/docs/adr/0023-surfaces-share-one-anatomy-and-two-layouts.md +6 -0
- package/docs/adr/0032-tab-baseline-respects-the-container-inset.md +16 -12
- package/docs/adr/0034-tabs-can-own-a-frame-without-owning-a-surface.md +8 -6
- package/docs/adr/0036-tabs-declares-trigger-distribution.md +11 -8
- package/docs/adr/0037-design-data-lives-outside-the-contract.md +1 -1
- package/docs/adr/0038-content-level-defines-primary-presentation.md +62 -0
- package/docs/adr/0039-filter-presentation-is-independent-from-filter-type.md +62 -0
- package/docs/adr/0040-tabs-use-a-single-navigation-presentation.md +59 -0
- package/docs/adr/0042-toggle-group-shares-the-grouped-control-grammar.md +79 -0
- package/docs/adr/0043-neutral-surfaces-and-interactions-use-opaque-role-tokens.md +73 -0
- package/docs/adr/0044-neutral-appearance-derives-from-bounded-axes-per-mode.md +133 -0
- package/docs/adr/0045-surface-replaces-content-and-card.md +230 -0
- package/docs/adr/0046-structural-body-owns-content-rhythm.md +103 -0
- package/docs/adr/0047-pane-is-only-a-split-layout-unit.md +71 -0
- package/docs/adr/0048-modal-intro-separates-content-from-chrome.md +34 -0
- package/docs/code-style.md +1 -1
- package/package.json +5 -1
- package/registry/skills/build-opus-ui/SKILL.md +11 -11
- package/registry/skills/build-opus-ui/references/evaluations.md +10 -9
- package/registry/skills/build-opus-ui/references/ui-patterns.md +17 -16
- package/registry/skills/create-opus-action/references/contract-and-binding.md +3 -3
- package/registry/templates/app/src/App.tsx +24 -12
- package/src/core/contracts.ts +1 -1
- package/src/core/runtime.ts +4 -37
- package/src/core/types.ts +5 -23
- package/src/design/index.ts +14 -3
- package/src/testing/index.ts +6 -26
- package/src/ui/appearance.ts +149 -0
- package/src/ui/components/patterns/action-form-card.tsx +46 -33
- package/src/ui/components/patterns/action-list-dialog.tsx +2 -4
- package/src/ui/components/patterns/confirm.tsx +3 -1
- package/src/ui/components/patterns/fill-region.ts +8 -7
- package/src/ui/components/patterns/form-dialog.tsx +1 -3
- package/src/ui/components/patterns/form.tsx +8 -7
- package/src/ui/components/patterns/list.tsx +64 -14
- package/src/ui/components/patterns/page.tsx +15 -11
- package/src/ui/components/patterns/pane.tsx +9 -240
- package/src/ui/components/patterns/presentation.tsx +14 -14
- package/src/ui/components/patterns/sidebar.tsx +7 -17
- package/src/ui/components/patterns/split.tsx +111 -59
- package/src/ui/components/patterns/{surface-header.tsx → structural-header.tsx} +50 -19
- package/src/ui/components/patterns/structural-media.tsx +26 -0
- package/src/ui/components/patterns/surface-anatomy.ts +71 -61
- package/src/ui/components/patterns/surface-assistant.tsx +2 -4
- package/src/ui/components/patterns/surface.tsx +620 -0
- package/src/ui/components/patterns/trigger.tsx +11 -9
- package/src/ui/components/primitives/ask.tsx +155 -83
- package/src/ui/components/primitives/button.tsx +11 -9
- package/src/ui/components/primitives/checkbox.tsx +8 -8
- package/src/ui/components/primitives/command.tsx +1 -1
- package/src/ui/components/primitives/composer.tsx +47 -45
- package/src/ui/components/primitives/detail.tsx +9 -2
- package/src/ui/components/primitives/dialog.tsx +60 -26
- package/src/ui/components/primitives/drawer.tsx +58 -12
- package/src/ui/components/primitives/icon-picker.tsx +93 -70
- package/src/ui/components/primitives/input-group.tsx +35 -28
- package/src/ui/components/primitives/input-otp.tsx +16 -16
- package/src/ui/components/primitives/input.tsx +20 -10
- package/src/ui/components/primitives/item.tsx +9 -12
- package/src/ui/components/primitives/menu.tsx +44 -65
- package/src/ui/components/primitives/metric-card.tsx +75 -59
- package/src/ui/components/primitives/radio-group.tsx +9 -9
- package/src/ui/components/primitives/select.tsx +344 -209
- package/src/ui/components/primitives/switch.tsx +10 -10
- package/src/ui/components/primitives/table.tsx +29 -24
- package/src/ui/components/primitives/tabs.tsx +58 -88
- package/src/ui/components/primitives/textarea.tsx +6 -6
- package/src/ui/components/primitives/toggle-group-context.ts +24 -0
- package/src/ui/components/primitives/toggle-group.tsx +116 -74
- package/src/ui/components/primitives/toggle.tsx +82 -16
- package/src/ui/docs/DocBrowser.tsx +77 -69
- package/src/ui/docs/content/action-form-card.md +9 -9
- package/src/ui/docs/content/action-list.md +85 -70
- package/src/ui/docs/content/action-view.md +33 -18
- package/src/ui/docs/content/actions.md +6 -7
- package/src/ui/docs/content/button.md +1 -1
- package/src/ui/docs/content/communication.md +1 -1
- package/src/ui/docs/content/customization.md +64 -11
- package/src/ui/docs/content/detail.md +8 -6
- package/src/ui/docs/content/dialog.md +100 -58
- package/src/ui/docs/content/drawer.md +63 -19
- package/src/ui/docs/content/field.md +14 -15
- package/src/ui/docs/content/icon-tile.md +14 -13
- package/src/ui/docs/content/page.md +34 -26
- package/src/ui/docs/content/pane.md +41 -290
- package/src/ui/docs/content/presentation.md +3 -3
- package/src/ui/docs/content/semantic-context.md +0 -1
- package/src/ui/docs/content/separator.md +6 -6
- package/src/ui/docs/content/sidebar.md +68 -266
- package/src/ui/docs/content/skeleton.md +20 -18
- package/src/ui/docs/content/split.md +14 -14
- package/src/ui/docs/content/surface.md +513 -0
- package/src/ui/docs/content/tabs.md +82 -83
- package/src/ui/docs/content/testing.md +2 -3
- package/src/ui/docs/content/toggle.md +120 -63
- package/src/ui/docs/content/tokens.md +124 -40
- package/src/ui/docs/registry.tsx +4 -6
- package/src/ui/drivers/react.tsx +4 -3
- package/src/ui/index.ts +30 -27
- package/src/ui/meta.ts +15 -27
- package/src/ui/react.tsx +42 -46
- package/src/ui/theme.css +311 -64
- package/src/vite/design.ts +23 -21
- package/src/ui/components/patterns/content-header.tsx +0 -532
- package/src/ui/components/patterns/surface-media.tsx +0 -69
- package/src/ui/components/primitives/card.tsx +0 -191
- package/src/ui/docs/content/card.md +0 -292
- package/src/ui/docs/content/content.md +0 -276
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
## Alternar painéis relacionados
|
|
2
2
|
|
|
3
|
-
Use `Tabs` para alternar painéis relacionados no mesmo contexto. O `value` de cada `
|
|
4
|
-
corresponde ao `
|
|
3
|
+
Use `Tabs` para alternar painéis relacionados no mesmo contexto. O `value` de cada `TabsListItem`
|
|
4
|
+
corresponde ao `TabsPanel` que ele abre. `defaultValue` define a aba inicial no modo não
|
|
5
5
|
controlado.
|
|
6
6
|
|
|
7
7
|
`icon` posiciona um ícone decorativo antes do rótulo e normaliza SVGs para `1rem`. Quando a aba
|
|
@@ -10,31 +10,31 @@ mostrar somente o ícone, declare `aria-label` para preservar seu nome acessíve
|
|
|
10
10
|
```tsx preview col
|
|
11
11
|
<Tabs defaultValue="sessions">
|
|
12
12
|
<TabsList>
|
|
13
|
-
<
|
|
13
|
+
<TabsListItem value="overview" icon={<LayoutDashboard />}>
|
|
14
14
|
Visão geral
|
|
15
|
-
</
|
|
16
|
-
<
|
|
15
|
+
</TabsListItem>
|
|
16
|
+
<TabsListItem value="sessions" icon={<History />}>
|
|
17
17
|
Sessões
|
|
18
|
-
</
|
|
19
|
-
<
|
|
18
|
+
</TabsListItem>
|
|
19
|
+
<TabsListItem value="skills" icon={<Settings />}>
|
|
20
20
|
Skills
|
|
21
|
-
</
|
|
21
|
+
</TabsListItem>
|
|
22
22
|
</TabsList>
|
|
23
|
-
<
|
|
23
|
+
<TabsPanel value="overview">
|
|
24
24
|
<p className="text-sm text-muted-foreground">
|
|
25
25
|
Resumo do workspace Empresa X.
|
|
26
26
|
</p>
|
|
27
|
-
</
|
|
28
|
-
<
|
|
27
|
+
</TabsPanel>
|
|
28
|
+
<TabsPanel value="sessions">
|
|
29
29
|
<p className="text-sm text-muted-foreground">
|
|
30
30
|
3 sessões nesta semana, 1 em andamento.
|
|
31
31
|
</p>
|
|
32
|
-
</
|
|
33
|
-
<
|
|
32
|
+
</TabsPanel>
|
|
33
|
+
<TabsPanel value="skills">
|
|
34
34
|
<p className="text-sm text-muted-foreground">
|
|
35
35
|
6 skills vinculadas aos agentes do workspace.
|
|
36
36
|
</p>
|
|
37
|
-
</
|
|
37
|
+
</TabsPanel>
|
|
38
38
|
</Tabs>
|
|
39
39
|
```
|
|
40
40
|
|
|
@@ -42,25 +42,25 @@ mostrar somente o ícone, declare `aria-label` para preservar seu nome acessíve
|
|
|
42
42
|
|
|
43
43
|
Use `framed` quando a navegação e seus painéis precisarem formar um único bloco. A propriedade
|
|
44
44
|
reúne borda, raio e recorte no próprio `Tabs`, mas não aplica fundo: o bloco herda a
|
|
45
|
-
superfície em que foi composto. Por isso, não envolva `Tabs` em um `
|
|
45
|
+
superfície em que foi composto. Por isso, não envolva `Tabs` em um `Surface` somente para obter essa
|
|
46
46
|
moldura.
|
|
47
47
|
|
|
48
48
|
```tsx preview col
|
|
49
49
|
<Tabs defaultValue="overview" framed className="gap-0">
|
|
50
|
-
<TabsList
|
|
51
|
-
<
|
|
52
|
-
<
|
|
50
|
+
<TabsList>
|
|
51
|
+
<TabsListItem value="overview">Visão geral</TabsListItem>
|
|
52
|
+
<TabsListItem value="history">Histórico</TabsListItem>
|
|
53
53
|
</TabsList>
|
|
54
|
-
<
|
|
54
|
+
<TabsPanel value="overview" className="p-4">
|
|
55
55
|
<p className="text-sm text-muted-foreground">
|
|
56
56
|
Resumo do workspace Empresa X.
|
|
57
57
|
</p>
|
|
58
|
-
</
|
|
59
|
-
<
|
|
58
|
+
</TabsPanel>
|
|
59
|
+
<TabsPanel value="history" className="p-4">
|
|
60
60
|
<p className="text-sm text-muted-foreground">
|
|
61
61
|
Alterações recentes do workspace.
|
|
62
62
|
</p>
|
|
63
|
-
</
|
|
63
|
+
</TabsPanel>
|
|
64
64
|
</Tabs>
|
|
65
65
|
```
|
|
66
66
|
|
|
@@ -73,127 +73,126 @@ altera os painéis associados.
|
|
|
73
73
|
|
|
74
74
|
```tsx preview col
|
|
75
75
|
<Tabs defaultValue="overview" distribution="equal">
|
|
76
|
-
<TabsList
|
|
77
|
-
<
|
|
78
|
-
<
|
|
79
|
-
<
|
|
76
|
+
<TabsList>
|
|
77
|
+
<TabsListItem value="overview">Visão geral</TabsListItem>
|
|
78
|
+
<TabsListItem value="contacts">Contatos</TabsListItem>
|
|
79
|
+
<TabsListItem value="history">Histórico</TabsListItem>
|
|
80
80
|
</TabsList>
|
|
81
|
-
<
|
|
82
|
-
<
|
|
83
|
-
<
|
|
81
|
+
<TabsPanel value="overview">Resumo do atendimento.</TabsPanel>
|
|
82
|
+
<TabsPanel value="contacts">Tentativas de contato.</TabsPanel>
|
|
83
|
+
<TabsPanel value="history">Alterações registradas.</TabsPanel>
|
|
84
84
|
</Tabs>
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
##
|
|
87
|
+
## Linha de navegação
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
sem alcançar as laterais da superfície.
|
|
89
|
+
`TabsList` usa uma linha-base porque representa navegação entre painéis, não uma escolha de valor.
|
|
90
|
+
Na orientação horizontal, a lista ocupa toda a largura disponível e a aba ativa é marcada sobre
|
|
91
|
+
essa linha. A linha respeita o recuo do contêiner; dentro de `DrawerBody` e `DialogBody`, ela
|
|
92
|
+
acompanha o alinhamento do restante do corpo sem alcançar as laterais da superfície.
|
|
94
93
|
Cada item contém uma área interativa com a mesma altura de um Button do tamanho correspondente. A
|
|
95
94
|
área permanece transparente e recebe fundo apenas no hover; a aba ativa é indicada pela linha
|
|
96
|
-
primária inferior. Um respiro de `0.375rem` separa o controle dessa linha
|
|
97
|
-
|
|
95
|
+
primária inferior. Um respiro de `0.375rem` separa o controle dessa linha. Em `Tabs framed`, a
|
|
96
|
+
lista recebe `0.25rem` nas laterais e no topo, e a mesma medida separa o controle da linha.
|
|
98
97
|
|
|
99
98
|
```tsx preview col
|
|
100
99
|
<Tabs defaultValue="agents">
|
|
101
|
-
<TabsList
|
|
102
|
-
<
|
|
103
|
-
<
|
|
104
|
-
<
|
|
100
|
+
<TabsList>
|
|
101
|
+
<TabsListItem value="agents">Agentes</TabsListItem>
|
|
102
|
+
<TabsListItem value="repos">Repositórios</TabsListItem>
|
|
103
|
+
<TabsListItem value="settings">Configurações</TabsListItem>
|
|
105
104
|
</TabsList>
|
|
106
|
-
<
|
|
105
|
+
<TabsPanel value="agents">
|
|
107
106
|
<p className="text-sm text-muted-foreground">
|
|
108
107
|
developer, reviewer e designer ativos.
|
|
109
108
|
</p>
|
|
110
|
-
</
|
|
111
|
-
<
|
|
109
|
+
</TabsPanel>
|
|
110
|
+
<TabsPanel value="repos">
|
|
112
111
|
<p className="text-sm text-muted-foreground">
|
|
113
112
|
empresa-x-api e empresa-x-web vinculados.
|
|
114
113
|
</p>
|
|
115
|
-
</
|
|
116
|
-
<
|
|
114
|
+
</TabsPanel>
|
|
115
|
+
<TabsPanel value="settings">
|
|
117
116
|
<p className="text-sm text-muted-foreground">Preferências do workspace.</p>
|
|
118
|
-
</
|
|
117
|
+
</TabsPanel>
|
|
119
118
|
</Tabs>
|
|
120
119
|
```
|
|
121
120
|
|
|
122
121
|
## Vertical
|
|
123
122
|
|
|
124
|
-
Com `orientation="vertical"`, a lista forma uma coluna
|
|
125
|
-
|
|
123
|
+
Com `orientation="vertical"`, a lista forma uma coluna e a marca da aba ativa passa para a lateral
|
|
124
|
+
do gatilho.
|
|
126
125
|
|
|
127
126
|
```tsx preview col
|
|
128
127
|
<Tabs defaultValue="prompt" orientation="vertical">
|
|
129
128
|
<TabsList>
|
|
130
|
-
<
|
|
131
|
-
<
|
|
132
|
-
<
|
|
129
|
+
<TabsListItem value="prompt">Prompt</TabsListItem>
|
|
130
|
+
<TabsListItem value="skills">Skills</TabsListItem>
|
|
131
|
+
<TabsListItem value="history">Histórico</TabsListItem>
|
|
133
132
|
</TabsList>
|
|
134
|
-
<
|
|
133
|
+
<TabsPanel value="prompt">
|
|
135
134
|
<p className="text-sm text-muted-foreground">
|
|
136
135
|
O prompt do agente developer.
|
|
137
136
|
</p>
|
|
138
|
-
</
|
|
139
|
-
<
|
|
137
|
+
</TabsPanel>
|
|
138
|
+
<TabsPanel value="skills">
|
|
140
139
|
<p className="text-sm text-muted-foreground">
|
|
141
140
|
Skills vinculadas a este agente.
|
|
142
141
|
</p>
|
|
143
|
-
</
|
|
144
|
-
<
|
|
142
|
+
</TabsPanel>
|
|
143
|
+
<TabsPanel value="history">
|
|
145
144
|
<p className="text-sm text-muted-foreground">
|
|
146
145
|
Sessões anteriores deste agente.
|
|
147
146
|
</p>
|
|
148
|
-
</
|
|
147
|
+
</TabsPanel>
|
|
149
148
|
</Tabs>
|
|
150
149
|
```
|
|
151
150
|
|
|
152
151
|
## Tamanho
|
|
153
152
|
|
|
154
|
-
`size="sm"` no `Tabs` reduz a
|
|
155
|
-
`Select` para uma fileira densa, como uma toolbar ou um cabeçalho
|
|
156
|
-
mais alto que os elementos vizinhos.
|
|
153
|
+
`size="sm"` no `Tabs` reduz a área interativa de `2.25rem` para `2rem`. É o par do `sm` de `Button` e
|
|
154
|
+
`Select` para uma fileira densa, como uma toolbar ou um cabeçalho.
|
|
157
155
|
|
|
158
156
|
```tsx preview col
|
|
159
157
|
<Tabs defaultValue="preview" size="sm">
|
|
160
158
|
<TabsList>
|
|
161
|
-
<
|
|
162
|
-
<
|
|
163
|
-
<
|
|
159
|
+
<TabsListItem value="preview">Preview</TabsListItem>
|
|
160
|
+
<TabsListItem value="code">Código</TabsListItem>
|
|
161
|
+
<TabsListItem value="ai">IA</TabsListItem>
|
|
164
162
|
</TabsList>
|
|
165
163
|
</Tabs>
|
|
166
164
|
```
|
|
167
165
|
|
|
168
166
|
## Propriedades de Tabs
|
|
169
167
|
|
|
170
|
-
| Propriedade | Tipo | Padrão | Descrição
|
|
171
|
-
| --------------- | ---------------------------- | -------------- |
|
|
172
|
-
| `defaultValue` | `string` | | Aba inicial no modo não controlado.
|
|
173
|
-
| `value` | `string` | | Aba ativa no modo controlado. Use com `onValueChange`.
|
|
174
|
-
| `onValueChange` | `(value: string) => void` | | Chamado quando a pessoa seleciona outra aba.
|
|
175
|
-
| `size` | `'default' \| 'sm'` | `'default'` | Altura da
|
|
176
|
-
| `distribution` | `'content' \| 'equal'` | `'content'` | Preserva a largura dos rótulos ou divide igualmente a largura disponível entre os gatilhos.
|
|
177
|
-
| `framed` | `boolean` | `false` | Aplica borda, raio e recorte ao conjunto sem definir fundo ou foreground.
|
|
178
|
-
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Direção da lista de abas.
|
|
168
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
169
|
+
| --------------- | ---------------------------- | -------------- | --------------------------------------------------------------------------------------------- |
|
|
170
|
+
| `defaultValue` | `string` | | Aba inicial no modo não controlado. |
|
|
171
|
+
| `value` | `string` | | Aba ativa no modo controlado. Use com `onValueChange`. |
|
|
172
|
+
| `onValueChange` | `(value: string) => void` | | Chamado quando a pessoa seleciona outra aba. |
|
|
173
|
+
| `size` | `'default' \| 'sm'` | `'default'` | Altura da área interativa na escala única dos controles (2.25 e 2rem), aplicada aos gatilhos. |
|
|
174
|
+
| `distribution` | `'content' \| 'equal'` | `'content'` | Preserva a largura dos rótulos ou divide igualmente a largura disponível entre os gatilhos. |
|
|
175
|
+
| `framed` | `boolean` | `false` | Aplica borda, raio e recorte ao conjunto sem definir fundo ou foreground. |
|
|
176
|
+
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Direção da lista de abas. |
|
|
179
177
|
|
|
180
178
|
## Propriedades de TabsList
|
|
181
179
|
|
|
182
|
-
| Propriedade
|
|
183
|
-
|
|
|
184
|
-
| `
|
|
180
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
181
|
+
| ------------ | -------- | ------ | ----------------------------------------------------------------- |
|
|
182
|
+
| `aria-label` | `string` | | Nomeia a navegação quando não houver um rótulo visível associado. |
|
|
183
|
+
| `className` | `string` | | Ajusta a composição externa sem substituir a linha de navegação. |
|
|
185
184
|
|
|
186
|
-
## Propriedades de
|
|
185
|
+
## Propriedades de TabsListItem
|
|
187
186
|
|
|
188
187
|
| Propriedade | Tipo | Padrão | Descrição |
|
|
189
188
|
| ----------- | ----------- | ------- | ----------------------------------------------------------------------------------------------- |
|
|
190
|
-
| `value` | `string` | | Identificador que associa o gatilho ao `
|
|
189
|
+
| `value` | `string` | | Identificador que associa o gatilho ao `TabsPanel` correspondente. |
|
|
191
190
|
| `icon` | `ReactNode` | | Ícone decorativo antes do rótulo, em `1rem`. Em uma aba sem texto, declare também `aria-label`. |
|
|
192
191
|
| `disabled` | `boolean` | `false` | Impede a seleção da aba. |
|
|
193
192
|
|
|
194
|
-
## Propriedades de
|
|
193
|
+
## Propriedades de TabsPanel
|
|
195
194
|
|
|
196
|
-
| Propriedade | Tipo | Padrão | Descrição
|
|
197
|
-
| ------------ | -------- | ------ |
|
|
198
|
-
| `value` | `string` | | Identificador do painel, igual ao `value` do `
|
|
199
|
-
| `forceMount` | `true` | | Mantém o painel montado mesmo quando outra aba está ativa.
|
|
195
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
196
|
+
| ------------ | -------- | ------ | ----------------------------------------------------------------------- |
|
|
197
|
+
| `value` | `string` | | Identificador do painel, igual ao `value` do `TabsListItem` que o abre. |
|
|
198
|
+
| `forceMount` | `true` | | Mantém o painel montado mesmo quando outra aba está ativa. |
|
|
@@ -90,9 +90,8 @@ expect(emitted).toEqual([{ event: 'task.done', data: { id: '1' } }])
|
|
|
90
90
|
|
|
91
91
|
Os dados que o modo design mostra não são comportamento da action e não precisam de teste de
|
|
92
92
|
unidade: o plugin `opusDesign()` os gera a partir do contrato (ver
|
|
93
|
-
[Actions](/docs/actions)).
|
|
94
|
-
|
|
95
|
-
handler em vez dele.
|
|
93
|
+
[Actions](/docs/actions)). `runAction` executa somente a action ligada ao handler; use cenários do
|
|
94
|
+
plugin para respostas específicas do modo design.
|
|
96
95
|
|
|
97
96
|
## memStorage
|
|
98
97
|
|
|
@@ -14,24 +14,20 @@ inicial no modo não controlado; o conteúdo pode ser texto ou ícone.
|
|
|
14
14
|
Use `pressed` e `onPressedChange` quando o estado pertencer ao consumidor.
|
|
15
15
|
|
|
16
16
|
```tsx preview
|
|
17
|
-
const [readOnly, setReadOnly] = useState(true)
|
|
17
|
+
const [readOnly, setReadOnly] = useState(true);
|
|
18
18
|
|
|
19
19
|
render(
|
|
20
|
-
<Toggle
|
|
21
|
-
variant="outline"
|
|
22
|
-
pressed={readOnly}
|
|
23
|
-
onPressedChange={setReadOnly}
|
|
24
|
-
>
|
|
20
|
+
<Toggle variant="outline" pressed={readOnly} onPressedChange={setReadOnly}>
|
|
25
21
|
<Eye />
|
|
26
22
|
Somente leitura
|
|
27
23
|
</Toggle>,
|
|
28
|
-
)
|
|
24
|
+
);
|
|
29
25
|
```
|
|
30
26
|
|
|
31
27
|
## Variantes e tamanhos
|
|
32
28
|
|
|
33
|
-
Na variante `default`, o fundo aparece somente quando o controle está ativo
|
|
34
|
-
borda. `size` ajusta a altura.
|
|
29
|
+
Na variante `default`, o fundo aparece somente quando o controle está ativo. `outline` mantém a
|
|
30
|
+
borda e usa um fundo sutil distinto dela no estado ativo. `size` ajusta a altura.
|
|
35
31
|
|
|
36
32
|
```tsx preview
|
|
37
33
|
<Toggle aria-label="Quebra de linha">
|
|
@@ -64,15 +60,15 @@ borda. `size` ajusta a altura.
|
|
|
64
60
|
|
|
65
61
|
## Propriedades de Toggle
|
|
66
62
|
|
|
67
|
-
| Propriedade
|
|
68
|
-
|
|
69
|
-
| `pressed`
|
|
70
|
-
| `onPressedChange` | `(pressed: boolean) => void` |
|
|
71
|
-
| `defaultPressed`
|
|
72
|
-
| `variant`
|
|
73
|
-
| `size`
|
|
74
|
-
| `shape`
|
|
75
|
-
| `disabled`
|
|
63
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
64
|
+
| ----------------- | ---------------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
65
|
+
| `pressed` | `boolean` | | Estado no modo controlado. Use com `onPressedChange`. |
|
|
66
|
+
| `onPressedChange` | `(pressed: boolean) => void` | | Chamado a cada alternância, com o novo estado. |
|
|
67
|
+
| `defaultPressed` | `boolean` | `false` | Estado inicial no modo não controlado. |
|
|
68
|
+
| `variant` | `'default' \| 'outline'` | `'default'` | `default` não tem borda e só ganha fundo quando ativo; `outline` mantém a borda. |
|
|
69
|
+
| `size` | `'sm' \| 'default' \| 'lg'` | `'default'` | Altura na escala única dos controles (2 · 2.25 · 2.5rem) — sm para toolbar densa, lg para alvo mais confortável. |
|
|
70
|
+
| `shape` | `'default' \| 'pill'` | `'default'` | Geometria do controle; `pill` arredonda as extremidades. |
|
|
71
|
+
| `disabled` | `boolean` | `false` | Esmaece e bloqueia o clique, preservando o estado visual. |
|
|
76
72
|
|
|
77
73
|
## ToggleGroup
|
|
78
74
|
|
|
@@ -82,96 +78,157 @@ relacionados. `type="single"` mantém um item ativo; `type="multiple"` aceita v
|
|
|
82
78
|
### Escolha única
|
|
83
79
|
|
|
84
80
|
```tsx preview
|
|
85
|
-
const [view, setView] = useState(
|
|
81
|
+
const [view, setView] = useState("sessions");
|
|
86
82
|
|
|
87
83
|
render(
|
|
88
|
-
<ToggleGroup
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
<ToggleGroup
|
|
85
|
+
type="single"
|
|
86
|
+
value={view}
|
|
87
|
+
onValueChange={(v) => v && setView(v)}
|
|
88
|
+
>
|
|
89
|
+
<Toggle value="overview">Visão geral</Toggle>
|
|
90
|
+
<Toggle value="sessions">Sessões</Toggle>
|
|
91
|
+
<Toggle value="skills">Habilidades</Toggle>
|
|
92
92
|
</ToggleGroup>,
|
|
93
|
-
)
|
|
93
|
+
);
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
### Escolha múltipla
|
|
97
97
|
|
|
98
98
|
```tsx preview
|
|
99
|
-
const [marks, setMarks] = useState([
|
|
99
|
+
const [marks, setMarks] = useState(["bold"]);
|
|
100
100
|
|
|
101
101
|
render(
|
|
102
102
|
<ToggleGroup type="multiple" value={marks} onValueChange={setMarks}>
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
<Toggle value="bold" aria-label="Negrito">
|
|
104
|
+
<Bold />
|
|
105
|
+
</Toggle>
|
|
106
|
+
<Toggle value="italic" aria-label="Itálico">
|
|
107
|
+
<Italic />
|
|
108
|
+
</Toggle>
|
|
109
|
+
<Toggle value="underline" aria-label="Sublinhado">
|
|
110
|
+
<Underline />
|
|
111
|
+
</Toggle>
|
|
106
112
|
</ToggleGroup>,
|
|
107
|
-
)
|
|
113
|
+
);
|
|
108
114
|
```
|
|
109
115
|
|
|
110
116
|
### Itens só com ícone e tooltip
|
|
111
117
|
|
|
112
118
|
Quando o item mostra somente um ícone, mantenha o `aria-label` e acrescente uma dica visual. Envolva o
|
|
113
|
-
`
|
|
119
|
+
`Toggle` em `TooltipTrigger asChild`: o controle preserva o estado selecionado e seus atributos,
|
|
114
120
|
e a dica aparece sem criar outro botão. O `TooltipProvider` da raiz do aplicativo continua necessário.
|
|
115
121
|
|
|
116
122
|
```tsx preview
|
|
117
|
-
const [align, setAlign] = useState(
|
|
123
|
+
const [align, setAlign] = useState("left");
|
|
118
124
|
|
|
119
125
|
render(
|
|
120
|
-
<ToggleGroup
|
|
126
|
+
<ToggleGroup
|
|
127
|
+
type="single"
|
|
128
|
+
value={align}
|
|
129
|
+
onValueChange={(v) => v && setAlign(v)}
|
|
130
|
+
>
|
|
121
131
|
<Tooltip>
|
|
122
132
|
<TooltipTrigger asChild>
|
|
123
|
-
<
|
|
133
|
+
<Toggle value="left" aria-label="Alinhar à esquerda">
|
|
134
|
+
<AlignLeft />
|
|
135
|
+
</Toggle>
|
|
124
136
|
</TooltipTrigger>
|
|
125
137
|
<TooltipContent>Alinhar à esquerda</TooltipContent>
|
|
126
138
|
</Tooltip>
|
|
127
139
|
<Tooltip>
|
|
128
140
|
<TooltipTrigger asChild>
|
|
129
|
-
<
|
|
141
|
+
<Toggle value="center" aria-label="Centralizar">
|
|
142
|
+
<AlignCenter />
|
|
143
|
+
</Toggle>
|
|
130
144
|
</TooltipTrigger>
|
|
131
145
|
<TooltipContent>Centralizar</TooltipContent>
|
|
132
146
|
</Tooltip>
|
|
133
147
|
<Tooltip>
|
|
134
148
|
<TooltipTrigger asChild>
|
|
135
|
-
<
|
|
149
|
+
<Toggle value="right" aria-label="Alinhar à direita">
|
|
150
|
+
<AlignRight />
|
|
151
|
+
</Toggle>
|
|
136
152
|
</TooltipTrigger>
|
|
137
153
|
<TooltipContent>Alinhar à direita</TooltipContent>
|
|
138
154
|
</Tooltip>
|
|
139
155
|
</ToggleGroup>,
|
|
140
|
-
)
|
|
156
|
+
);
|
|
141
157
|
```
|
|
142
158
|
|
|
143
|
-
###
|
|
159
|
+
### Relação entre os controles
|
|
144
160
|
|
|
145
|
-
`
|
|
146
|
-
|
|
161
|
+
`mode` segue a mesma gramática de `ButtonGroup`. `connected`, o padrão, une os controles e remove
|
|
162
|
+
bordas internas duplicadas; `spaced` preserva cada controle com um pequeno intervalo; `divided`
|
|
163
|
+
acrescenta divisores entre eles. `variant`, `size` e `shape` definidos no grupo chegam aos controles
|
|
164
|
+
por contexto.
|
|
147
165
|
|
|
148
166
|
```tsx preview
|
|
149
|
-
<ToggleGroup type="single" variant="outline"
|
|
150
|
-
<
|
|
151
|
-
|
|
152
|
-
|
|
167
|
+
<ToggleGroup type="single" variant="outline" defaultValue="call">
|
|
168
|
+
<Toggle value="call">
|
|
169
|
+
<Phone /> Telefone
|
|
170
|
+
</Toggle>
|
|
171
|
+
<Toggle value="email">
|
|
172
|
+
<Mail /> E-mail
|
|
173
|
+
</Toggle>
|
|
174
|
+
<Toggle value="whatsapp">
|
|
175
|
+
<MessageCircle /> WhatsApp
|
|
176
|
+
</Toggle>
|
|
153
177
|
</ToggleGroup>
|
|
154
178
|
```
|
|
155
179
|
|
|
180
|
+
Use `mode="spaced"` quando cada controle precisar preservar sua própria borda e seu próprio raio.
|
|
181
|
+
Use `mode="divided"` quando a separação também precisar ficar explícita por divisores.
|
|
182
|
+
|
|
183
|
+
### Aparência segmentada
|
|
184
|
+
|
|
185
|
+
Use `mode="segmented"` para escolhas curtas que precisam permanecer visíveis dentro de uma
|
|
186
|
+
superfície compartilhada. O item ativo usa o mesmo fundo de uma superfície elevada; os demais
|
|
187
|
+
permanecem no fundo do grupo. Segmentos inativos vizinhos recebem um divisor sutil; o divisor
|
|
188
|
+
desaparece dos dois lados da seleção. Essa aparência escolhe um valor no contexto atual: para
|
|
189
|
+
navegar entre painéis, use Tabs.
|
|
190
|
+
|
|
191
|
+
```tsx preview
|
|
192
|
+
<ToggleGroup type="single" mode="segmented" defaultValue="sessions">
|
|
193
|
+
<Toggle value="overview">
|
|
194
|
+
<LayoutGrid /> Visão geral
|
|
195
|
+
</Toggle>
|
|
196
|
+
<Toggle value="sessions">
|
|
197
|
+
<History /> Sessões
|
|
198
|
+
</Toggle>
|
|
199
|
+
<Toggle value="skills">
|
|
200
|
+
<Settings /> Habilidades
|
|
201
|
+
</Toggle>
|
|
202
|
+
</ToggleGroup>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
`mode` trata a relação visual entre os controles. `variant` continua tratando cada `Toggle`; por
|
|
206
|
+
isso, a composição segmentada recomendada usa a variante padrão. O recuo fica dentro da altura da
|
|
207
|
+
escala de controles: o conjunto mantém `2rem`, `2.25rem` ou `2.5rem` conforme `size`.
|
|
208
|
+
|
|
209
|
+
### Distribuição e moldura
|
|
210
|
+
|
|
211
|
+
`distribution="content"`, o padrão, preserva a largura dos rótulos. Use `equal` para dividir toda a
|
|
212
|
+
largura disponível igualmente entre os controles. `framed` acrescenta borda e recuo estrutural sem
|
|
213
|
+
mudar o modo de agrupamento.
|
|
214
|
+
|
|
156
215
|
### Propriedades de ToggleGroup
|
|
157
216
|
|
|
158
|
-
| Propriedade
|
|
159
|
-
|
|
160
|
-
| `type`
|
|
161
|
-
| `value`
|
|
162
|
-
| `onValueChange` | `(value: string \| string[]) => void`
|
|
163
|
-
| `defaultValue`
|
|
164
|
-
| `variant`
|
|
165
|
-
| `size`
|
|
166
|
-
| `shape`
|
|
167
|
-
| `
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
| `size` | `'default' \| 'sm' \| 'lg'` | `'default'` | Tamanho do item quando o grupo não declara `size`; o valor do grupo prevalece. |
|
|
177
|
-
| `shape` | `'default' \| 'pill'` | shape do grupo | Geometria deste item; quando informada, prevalece sobre a do grupo. |
|
|
217
|
+
| Propriedade | Tipo | Padrão | Descrição |
|
|
218
|
+
| --------------- | ----------------------------------------------------- | -------------- | ----------------------------------------------------------------------------------------------------- |
|
|
219
|
+
| `type` | `'single' \| 'multiple'` | | Define seleção única (`string`) ou múltipla (`string[]`). |
|
|
220
|
+
| `value` | `string \| string[]` | | Seleção controlada; o tipo acompanha `type`. |
|
|
221
|
+
| `onValueChange` | `(value: string \| string[]) => void` | | Informa a nova seleção. No modo single, uma string vazia representa nenhum item ativo. |
|
|
222
|
+
| `defaultValue` | `string \| string[]` | | Seleção inicial no modo não controlado. |
|
|
223
|
+
| `variant` | `'default' \| 'outline'` | `'default'` | Tratamento visual repassado aos itens. `outline` aplica borda a cada item. |
|
|
224
|
+
| `size` | `'default' \| 'sm' \| 'lg'` | `'default'` | Tamanho repassado aos itens. |
|
|
225
|
+
| `shape` | `'default' \| 'pill'` | `'default'` | Geometria do grupo e de suas extremidades. |
|
|
226
|
+
| `mode` | `'connected' \| 'spaced' \| 'divided' \| 'segmented'` | `'connected'` | Define como os controles se relacionam; `segmented` cria uma superfície compartilhada para a seleção. |
|
|
227
|
+
| `distribution` | `'content' \| 'equal'` | `'content'` | Preserva a largura dos rótulos ou reparte igualmente a largura disponível. |
|
|
228
|
+
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Organiza os controles e os divisores no eixo indicado. |
|
|
229
|
+
| `framed` | `boolean` | `false` | Acrescenta borda, raio e recuo ao grupo sem alterar o modo. |
|
|
230
|
+
|
|
231
|
+
Dentro de `ToggleGroup`, cada `Toggle` exige `value`. O grupo controla o estado selecionado; props
|
|
232
|
+
standalone como `pressed` e `onPressedChange` não participam dessa composição. `disabled`, `variant`,
|
|
233
|
+
No grupo, `variant` e `size` pertencem ao conjunto e chegam a todos os controles. `shape` no item
|
|
234
|
+
pode declarar uma pílula local dentro do grupo.
|