@1doc/1ds-react 2.7.2 → 2.9.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.
Files changed (302) hide show
  1. package/CHANGELOG.md +1280 -0
  2. package/dist/components/AIContent/AIContent.d.ts +10 -0
  3. package/dist/components/AIContent/AIContent.js +1 -1
  4. package/dist/components/AILabel/AILabel.d.ts +4 -0
  5. package/dist/components/AILabel/AILabel.js +2 -2
  6. package/dist/components/Accordion/Accordion.d.ts +6 -2
  7. package/dist/components/Alert/Alert.css +2 -0
  8. package/dist/components/Alert/Alert.d.ts +3 -1
  9. package/dist/components/Alert/Alert.js +7 -1
  10. package/dist/components/AppHeader/AppHeader.css +82 -8
  11. package/dist/components/AppHeader/AppHeader.d.ts +12 -1
  12. package/dist/components/AppHeader/AppHeader.js +186 -1
  13. package/dist/components/AppNavItem/AppNavItem.css +11 -3
  14. package/dist/components/AppShell/AppShell.css +9 -0
  15. package/dist/components/AppShell/AppShell.d.ts +8 -0
  16. package/dist/components/AppShell/AppShell.js +4 -1
  17. package/dist/components/AppSidebar/AppSidebar.css +1 -1
  18. package/dist/components/AppSidebar/AppSidebar.d.ts +4 -0
  19. package/dist/components/AppSidebar/AppSidebar.js +3 -1
  20. package/dist/components/AttachmentCard/AttachmentCard.css +17 -1
  21. package/dist/components/AttachmentCard/AttachmentCard.d.ts +29 -2
  22. package/dist/components/AttachmentCard/AttachmentCard.js +88 -20
  23. package/dist/components/Avatar/Avatar.css +7 -2
  24. package/dist/components/Avatar/AvatarGroup.d.ts +27 -0
  25. package/dist/components/Avatar/AvatarGroup.js +28 -4
  26. package/dist/components/Badge/Badge.css +61 -3
  27. package/dist/components/Badge/Badge.d.ts +14 -4
  28. package/dist/components/Badge/Badge.js +1 -0
  29. package/dist/components/BottomSheet/BottomSheet.css +1 -0
  30. package/dist/components/BottomSheet/BottomSheet.d.ts +8 -0
  31. package/dist/components/BottomSheet/BottomSheet.js +14 -2
  32. package/dist/components/Box/Box.css +83 -0
  33. package/dist/components/Box/Box.d.ts +82 -2
  34. package/dist/components/Box/Box.js +42 -2
  35. package/dist/components/Button/Button.css +29 -0
  36. package/dist/components/Button/Button.d.ts +4 -4
  37. package/dist/components/Button/Button.js +4 -1
  38. package/dist/components/Calendar/Calendar.css +245 -0
  39. package/dist/components/Calendar/Calendar.d.ts +125 -0
  40. package/dist/components/Calendar/Calendar.js +320 -0
  41. package/dist/components/Chart/BarChart.d.ts +6 -0
  42. package/dist/components/Chart/BarChart.js +3 -1
  43. package/dist/components/Chart/LineChart.d.ts +6 -0
  44. package/dist/components/Chart/LineChart.js +3 -1
  45. package/dist/components/Checkbox/Checkbox.css +4 -1
  46. package/dist/components/Chips/Chips.css +39 -0
  47. package/dist/components/Chips/Chips.d.ts +7 -2
  48. package/dist/components/Chips/Chips.js +6 -2
  49. package/dist/components/Coachmark/Coachmark.css +118 -0
  50. package/dist/components/Coachmark/Coachmark.d.ts +75 -0
  51. package/dist/components/Coachmark/Coachmark.js +321 -0
  52. package/dist/components/CodeBlock/CodeBlock.css +96 -0
  53. package/dist/components/CodeBlock/CodeBlock.d.ts +47 -0
  54. package/dist/components/CodeBlock/CodeBlock.js +103 -0
  55. package/dist/components/ColorPicker/ColorPicker.css +133 -0
  56. package/dist/components/ColorPicker/ColorPicker.d.ts +73 -0
  57. package/dist/components/ColorPicker/ColorPicker.js +219 -0
  58. package/dist/components/Combobox/Combobox.css +11 -3
  59. package/dist/components/ConfirmAIAction/ConfirmAIAction.d.ts +11 -1
  60. package/dist/components/ConfirmAIAction/ConfirmAIAction.js +6 -1
  61. package/dist/components/ConfirmDialog/ConfirmDialog.css +3 -0
  62. package/dist/components/ConfirmDialog/ConfirmDialog.d.ts +14 -0
  63. package/dist/components/ConfirmDialog/ConfirmDialog.js +2 -2
  64. package/dist/components/DataTable/DataTable.css +80 -0
  65. package/dist/components/DataTable/DataTable.d.ts +23 -4
  66. package/dist/components/DataTable/DataTable.js +61 -15
  67. package/dist/components/DatePicker/DatePicker.css +8 -0
  68. package/dist/components/DatePicker/DatePicker.d.ts +4 -0
  69. package/dist/components/DatePicker/DatePicker.js +14 -1
  70. package/dist/components/DescriptionList/DescriptionList.css +113 -0
  71. package/dist/components/DescriptionList/DescriptionList.d.ts +59 -0
  72. package/dist/components/DescriptionList/DescriptionList.js +51 -0
  73. package/dist/components/Drawer/Drawer.css +1 -0
  74. package/dist/components/Dropdown/Dropdown.js +47 -29
  75. package/dist/components/FileInput/FileInput.css +24 -4
  76. package/dist/components/FileInput/FileInput.d.ts +22 -2
  77. package/dist/components/FileInput/FileInput.js +23 -2
  78. package/dist/components/Grid/Grid.js +5 -5
  79. package/dist/components/IconPicker/IconPicker.css +107 -0
  80. package/dist/components/IconPicker/IconPicker.d.ts +74 -0
  81. package/dist/components/IconPicker/IconPicker.js +194 -0
  82. package/dist/components/Input/Input.css +41 -3
  83. package/dist/components/Input/Input.d.ts +14 -1
  84. package/dist/components/Input/Input.js +72 -6
  85. package/dist/components/Kanban/Kanban.css +5 -0
  86. package/dist/components/Kanban/Kanban.d.ts +41 -0
  87. package/dist/components/Kanban/Kanban.js +59 -27
  88. package/dist/components/Kanban/KanbanCard.d.ts +2 -0
  89. package/dist/components/Kanban/KanbanCard.js +1 -1
  90. package/dist/components/Kanban/KanbanColumn.d.ts +2 -0
  91. package/dist/components/Kanban/KanbanColumn.js +3 -0
  92. package/dist/components/Kbd/Kbd.css +66 -0
  93. package/dist/components/Kbd/Kbd.d.ts +32 -0
  94. package/dist/components/Kbd/Kbd.js +40 -0
  95. package/dist/components/Link/Link.css +1 -1
  96. package/dist/components/List/List.css +136 -0
  97. package/dist/components/List/List.d.ts +82 -0
  98. package/dist/components/List/List.js +53 -0
  99. package/dist/components/List/ListItem.d.ts +85 -0
  100. package/dist/components/List/ListItem.js +81 -0
  101. package/dist/components/Modal/Modal.css +93 -8
  102. package/dist/components/Modal/Modal.d.ts +45 -7
  103. package/dist/components/Modal/Modal.js +106 -6
  104. package/dist/components/MultiSelect/MultiSelect.css +9 -1
  105. package/dist/components/MultiSelect/MultiSelect.js +45 -8
  106. package/dist/components/OrgChart/OrgChart.css +149 -0
  107. package/dist/components/OrgChart/OrgChart.d.ts +83 -0
  108. package/dist/components/OrgChart/OrgChart.js +297 -0
  109. package/dist/components/OtpInput/OtpInput.css +93 -0
  110. package/dist/components/OtpInput/OtpInput.d.ts +60 -0
  111. package/dist/components/OtpInput/OtpInput.js +215 -0
  112. package/dist/components/Pagination/Pagination.d.ts +6 -0
  113. package/dist/components/Pagination/Pagination.js +9 -1
  114. package/dist/components/PhoneInput/PhoneInput.css +9 -1
  115. package/dist/components/PhoneInput/PhoneInput.d.ts +10 -0
  116. package/dist/components/PhoneInput/PhoneInput.js +20 -3
  117. package/dist/components/Popover/Popover.d.ts +7 -0
  118. package/dist/components/Popover/Popover.js +11 -1
  119. package/dist/components/RichTextEditor/RichTextEditor.css +203 -0
  120. package/dist/components/RichTextEditor/RichTextEditor.d.ts +83 -0
  121. package/dist/components/RichTextEditor/RichTextEditor.js +494 -0
  122. package/dist/components/SegmentedControl/SegmentedControl.d.ts +2 -0
  123. package/dist/components/SegmentedControl/SegmentedControl.js +21 -8
  124. package/dist/components/Select/Select.css +71 -1
  125. package/dist/components/Select/Select.d.ts +12 -0
  126. package/dist/components/Select/Select.js +93 -10
  127. package/dist/components/SidePanel/SidePanel.css +4 -4
  128. package/dist/components/SidePanelItem/SidePanelItem.css +7 -5
  129. package/dist/components/SidePanelSearch/SidePanelSearch.css +2 -2
  130. package/dist/components/SidePanelSection/SidePanelSection.css +7 -5
  131. package/dist/components/Stack/Stack.css +49 -0
  132. package/dist/components/Stack/Stack.d.ts +65 -7
  133. package/dist/components/Stack/Stack.js +30 -2
  134. package/dist/components/StatCard/StatCard.css +73 -0
  135. package/dist/components/StatCard/StatCard.d.ts +17 -0
  136. package/dist/components/StatCard/StatCard.js +4 -1
  137. package/dist/components/Stepper/Stepper.css +4 -1
  138. package/dist/components/Stepper/Stepper.d.ts +8 -0
  139. package/dist/components/Stepper/Stepper.js +4 -4
  140. package/dist/components/Switch/Switch.css +1 -0
  141. package/dist/components/Tabs/Tab.d.ts +15 -0
  142. package/dist/components/Tabs/Tab.js +30 -1
  143. package/dist/components/Tabs/Tabs.css +132 -0
  144. package/dist/components/Tabs/Tabs.d.ts +7 -0
  145. package/dist/components/Tabs/Tabs.js +13 -2
  146. package/dist/components/Tag/Tag.css +85 -2
  147. package/dist/components/Tag/Tag.d.ts +13 -6
  148. package/dist/components/Tag/Tag.js +1 -0
  149. package/dist/components/Text/Text.d.ts +9 -1
  150. package/dist/components/Text/Text.js +2 -2
  151. package/dist/components/Textarea/Textarea.css +11 -3
  152. package/dist/components/TimePicker/TimePicker.css +8 -0
  153. package/dist/components/TimePicker/TimePicker.d.ts +6 -0
  154. package/dist/components/TimePicker/TimePicker.js +1 -1
  155. package/dist/components/Tooltip/Tooltip.css +40 -0
  156. package/dist/components/Tooltip/Tooltip.d.ts +11 -0
  157. package/dist/components/Tooltip/Tooltip.js +114 -11
  158. package/dist/index.d.ts +25 -0
  159. package/dist/index.js +14 -0
  160. package/dist/teste/AILabel.test.d.ts +1 -0
  161. package/dist/teste/AILabel.test.js +33 -0
  162. package/dist/teste/AccordionConteudoLivre.test.d.ts +1 -0
  163. package/dist/teste/AccordionConteudoLivre.test.js +29 -0
  164. package/dist/teste/Alert.test.d.ts +1 -0
  165. package/dist/teste/Alert.test.js +27 -0
  166. package/dist/teste/AtributosRepassados.test.d.ts +1 -0
  167. package/dist/teste/AtributosRepassados.test.js +52 -0
  168. package/dist/teste/AttachmentCardIA.test.d.ts +1 -0
  169. package/dist/teste/AttachmentCardIA.test.js +89 -0
  170. package/dist/teste/AvatarGroupOverlap.test.d.ts +1 -0
  171. package/dist/teste/AvatarGroupOverlap.test.js +56 -0
  172. package/dist/teste/BadgeTag.test.d.ts +1 -0
  173. package/dist/teste/BadgeTag.test.js +42 -0
  174. package/dist/teste/BottomSheet.test.d.ts +1 -0
  175. package/dist/teste/BottomSheet.test.js +23 -0
  176. package/dist/teste/BoxItemFlex.test.d.ts +1 -0
  177. package/dist/teste/BoxItemFlex.test.js +54 -0
  178. package/dist/teste/BoxLayout.test.d.ts +1 -0
  179. package/dist/teste/BoxLayout.test.js +35 -0
  180. package/dist/teste/Button.test.d.ts +1 -0
  181. package/dist/teste/Button.test.js +27 -0
  182. package/dist/teste/Calendar.test.d.ts +1 -0
  183. package/dist/teste/Calendar.test.js +221 -0
  184. package/dist/teste/ChipsXs.test.d.ts +1 -0
  185. package/dist/teste/ChipsXs.test.js +31 -0
  186. package/dist/teste/Coachmark.test.d.ts +1 -0
  187. package/dist/teste/Coachmark.test.js +149 -0
  188. package/dist/teste/ColorPicker.test.d.ts +1 -0
  189. package/dist/teste/ColorPicker.test.js +132 -0
  190. package/dist/teste/ConfirmAIAction.test.d.ts +1 -0
  191. package/dist/teste/ConfirmAIAction.test.js +33 -0
  192. package/dist/teste/DataTableCelulaLivre.test.d.ts +1 -0
  193. package/dist/teste/DataTableCelulaLivre.test.js +76 -0
  194. package/dist/teste/DataTableDocumento.test.d.ts +1 -0
  195. package/dist/teste/DataTableDocumento.test.js +92 -0
  196. package/dist/teste/DatePicker.test.js +23 -0
  197. package/dist/teste/Dropdown.test.js +111 -0
  198. package/dist/teste/FileInputTrigger.test.d.ts +1 -0
  199. package/dist/teste/FileInputTrigger.test.js +53 -0
  200. package/dist/teste/IconPicker.test.d.ts +1 -0
  201. package/dist/teste/IconPicker.test.js +130 -0
  202. package/dist/teste/InputMascaraEAfins.test.d.ts +1 -0
  203. package/dist/teste/InputMascaraEAfins.test.js +99 -0
  204. package/dist/teste/KbdCodeBlock.test.d.ts +1 -0
  205. package/dist/teste/KbdCodeBlock.test.js +95 -0
  206. package/dist/teste/List.test.d.ts +1 -0
  207. package/dist/teste/List.test.js +153 -0
  208. package/dist/teste/Modal.test.d.ts +1 -0
  209. package/dist/teste/Modal.test.js +26 -0
  210. package/dist/teste/ModalVariantes.test.d.ts +1 -0
  211. package/dist/teste/ModalVariantes.test.js +151 -0
  212. package/dist/teste/MultiSelectErro.test.d.ts +1 -0
  213. package/dist/teste/MultiSelectErro.test.js +62 -0
  214. package/dist/teste/NomeAcessivelSsr.test.d.ts +1 -0
  215. package/dist/teste/NomeAcessivelSsr.test.js +88 -0
  216. package/dist/teste/OrgChart.test.d.ts +1 -0
  217. package/dist/teste/OrgChart.test.js +162 -0
  218. package/dist/teste/OtpInput.test.d.ts +1 -0
  219. package/dist/teste/OtpInput.test.js +143 -0
  220. package/dist/teste/PopoverMaxHeight.test.d.ts +1 -0
  221. package/dist/teste/PopoverMaxHeight.test.js +38 -0
  222. package/dist/teste/RichTextEditor.test.d.ts +1 -0
  223. package/dist/teste/RichTextEditor.test.js +287 -0
  224. package/dist/teste/RotulosTraduziveis.test.d.ts +1 -0
  225. package/dist/teste/RotulosTraduziveis.test.js +405 -0
  226. package/dist/teste/SegmentedControl.test.js +33 -0
  227. package/dist/teste/Select.test.d.ts +1 -0
  228. package/dist/teste/Select.test.js +62 -0
  229. package/dist/teste/SelectPlacementFiltro.test.d.ts +1 -0
  230. package/dist/teste/SelectPlacementFiltro.test.js +88 -0
  231. package/dist/teste/Stack.test.d.ts +1 -0
  232. package/dist/teste/Stack.test.js +57 -0
  233. package/dist/teste/StatCardRotuloTopo.test.d.ts +1 -0
  234. package/dist/teste/StatCardRotuloTopo.test.js +34 -0
  235. package/dist/teste/TabsContadorFechavel.test.d.ts +1 -0
  236. package/dist/teste/TabsContadorFechavel.test.js +79 -0
  237. package/dist/teste/Tooltip.test.d.ts +1 -0
  238. package/dist/teste/Tooltip.test.js +109 -0
  239. package/dist/teste/TooltipDark.test.d.ts +1 -0
  240. package/dist/teste/TooltipDark.test.js +31 -0
  241. package/dist/utils/calendario.d.ts +28 -0
  242. package/dist/utils/calendario.js +73 -0
  243. package/dist/utils/chart.d.ts +4 -0
  244. package/dist/utils/chart.js +3 -2
  245. package/dist/utils/html-seguro.d.ts +27 -0
  246. package/dist/utils/html-seguro.js +97 -0
  247. package/dist/utils/id.d.ts +2 -0
  248. package/dist/utils/id.js +23 -0
  249. package/dist/utils/paleta-de-cores.d.ts +26 -0
  250. package/dist/utils/paleta-de-cores.js +10 -0
  251. package/dist/utils/texto.d.ts +5 -0
  252. package/dist/utils/texto.js +5 -0
  253. package/package.json +3 -3
  254. package/src/index.ts +26 -0
  255. package/src/teste/AILabel.test.tsx +41 -0
  256. package/src/teste/AccordionConteudoLivre.test.tsx +39 -0
  257. package/src/teste/Alert.test.tsx +32 -0
  258. package/src/teste/AtributosRepassados.test.tsx +73 -0
  259. package/src/teste/AttachmentCardIA.test.tsx +126 -0
  260. package/src/teste/AvatarGroupOverlap.test.tsx +74 -0
  261. package/src/teste/BadgeTag.test.tsx +64 -0
  262. package/src/teste/BottomSheet.test.tsx +25 -0
  263. package/src/teste/BoxItemFlex.test.tsx +81 -0
  264. package/src/teste/BoxLayout.test.tsx +50 -0
  265. package/src/teste/Button.test.tsx +39 -0
  266. package/src/teste/Calendar.test.tsx +282 -0
  267. package/src/teste/ChipsXs.test.tsx +41 -0
  268. package/src/teste/Coachmark.test.tsx +198 -0
  269. package/src/teste/ColorPicker.test.tsx +153 -0
  270. package/src/teste/ConfirmAIAction.test.tsx +41 -0
  271. package/src/teste/DataTableCelulaLivre.test.tsx +103 -0
  272. package/src/teste/DataTableDocumento.test.tsx +102 -0
  273. package/src/teste/DatePicker.test.tsx +38 -0
  274. package/src/teste/Dropdown.test.tsx +146 -0
  275. package/src/teste/FileInputTrigger.test.tsx +89 -0
  276. package/src/teste/IconPicker.test.tsx +145 -0
  277. package/src/teste/InputMascaraEAfins.test.tsx +124 -0
  278. package/src/teste/KbdCodeBlock.test.tsx +106 -0
  279. package/src/teste/List.test.tsx +269 -0
  280. package/src/teste/Modal.test.tsx +28 -0
  281. package/src/teste/ModalVariantes.test.tsx +173 -0
  282. package/src/teste/MultiSelectErro.test.tsx +97 -0
  283. package/src/teste/NomeAcessivelSsr.test.tsx +110 -0
  284. package/src/teste/OrgChart.test.tsx +183 -0
  285. package/src/teste/OtpInput.test.tsx +163 -0
  286. package/src/teste/PopoverMaxHeight.test.tsx +47 -0
  287. package/src/teste/RichTextEditor.test.tsx +329 -0
  288. package/src/teste/RotulosTraduziveis.test.tsx +545 -0
  289. package/src/teste/SegmentedControl.test.tsx +57 -0
  290. package/src/teste/Select.test.tsx +97 -0
  291. package/src/teste/SelectPlacementFiltro.test.tsx +110 -0
  292. package/src/teste/Stack.test.tsx +80 -0
  293. package/src/teste/StatCardRotuloTopo.test.tsx +44 -0
  294. package/src/teste/TabsContadorFechavel.test.tsx +144 -0
  295. package/src/teste/Tooltip.test.tsx +219 -0
  296. package/src/teste/TooltipDark.test.tsx +51 -0
  297. package/src/utils/calendario.ts +78 -0
  298. package/src/utils/chart.ts +7 -2
  299. package/src/utils/html-seguro.ts +94 -0
  300. package/src/utils/id.ts +24 -0
  301. package/src/utils/paleta-de-cores.ts +34 -0
  302. package/src/utils/texto.ts +5 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,1285 @@
1
1
  # @1doc/1ds-react
2
2
 
3
+ ## 2.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 704af0c: feat(accordion): conteúdo livre por item no Vue (slot `content-<id>`)
8
+
9
+ No React o `content` do item já aceitava qualquer nó. No Vue ele era interpolado
10
+ como texto, então o painel só aceitava string. Agora, no Vue, cada item pode ter
11
+ um slot com o próprio conteúdo.
12
+
13
+ - `#content-<id>`: slot com escopo por item (`<id>` é o `id` do item), que recebe
14
+ `{ item }` e vale sobre o `content` de texto daquele item. Itens sem slot
15
+ continuam mostrando o texto. O `postbuild` liga o slot ao `Accordion.vue`
16
+ gerado, como já faz com o `DataTable`, e falha o build se o gerado mudar de
17
+ forma.
18
+ - Título: o título do item **já é neutro** no 1DS (14/600, `neutral-dark-pure`;
19
+ só o chevron fica azul quando abre), então não há opção de cor a acrescentar.
20
+ Se o CrisDoc mediu azul de 16px, era outra peça ou uma versão antiga.
21
+
22
+ ```vue
23
+ <Accordion :items="[{ id: 'campos', title: 'Seção 01', content: '' }]">
24
+ <template #content-campos>
25
+ <Input label="Nome" fullWidth />
26
+ </template>
27
+ </Accordion>
28
+ ```
29
+
30
+ - 3d9472d: feat(attachmentcard): `status="ai"`, painel livre (`panel`), `panelWidth` e `closePanelOnAction`
31
+
32
+ Opt-in; sem as props novas o cartão é o mesmo.
33
+
34
+ - `status="ai"`: selo de recurso de IA, no roxo da IA (`ai-light` / `ai-dark`, os
35
+ mesmos tokens do `AILabel`), com a varinha como ícone padrão (`statusIcon`
36
+ continua mandando). O ícone do painel também é a varinha.
37
+ - `panel`: conteúdo livre do painel do selo, no lugar do resultado da conferência
38
+ (ações, campos, texto). React: o elemento; Vue: o slot `panel`. Com ele o selo
39
+ vira botão mesmo sem `statusDetails`. Sem título interno, o painel é nomeado
40
+ pelo selo (o mesmo nome que o botão tem, "Recursos IA: conferência de ...").
41
+ - `panelWidth` (px): largura do painel; padrão 300.
42
+ - `closePanelOnAction`: ao acionar um botão ou link de dentro do painel (o
43
+ "Aplicar sugestão"), o painel fecha e o foco volta ao selo. A ação do app roda
44
+ antes. O botão de copiar um campo não conta. Sem a prop, o painel fica aberto
45
+ até Esc, clique fora ou o foco sair.
46
+
47
+ Por baixo, o `postbuild` ganhou `slotsNoScriptVue`: o Vue que recebe só o slot
48
+ enxergava `props.panel` como `undefined` no script e o selo não virava botão. O
49
+ gancho troca `props.<prop>` por `(props.<prop> || slots['<slot>'])` nos arquivos
50
+ listados e falha o build se o gerado não tiver o formato esperado.
51
+
52
+ ```vue
53
+ <AttachmentCard
54
+ fileName="Protocolo 104-2026.pdf"
55
+ status="ai"
56
+ statusLabel="Recursos IA"
57
+ :panelWidth="280"
58
+ :closePanelOnAction="true"
59
+ >
60
+ <template #panel>
61
+ <Text>A IA sugere "Recurso Administrativo".</Text>
62
+ <Button size="sm" @click="aplicar">Aplicar sugestão</Button>
63
+ </template>
64
+ </AttachmentCard>
65
+ ```
66
+
67
+ - 2c0dafb: feat(avatargroup): `overlap`, `ring` e `overflowCount`
68
+
69
+ Opt-in; sem as props novas o grupo é o mesmo.
70
+
71
+ - `overflowCount`: quantas pessoas existem além das de `avatars`. O "+N" deixa de
72
+ exigir N itens-fantasma: com 16 responsáveis, passe os 4 primeiros e
73
+ `overflowCount={12}`. Soma com o que passar de `max` dentro de `avatars`, e os
74
+ textos traduzíveis (`overflowTitle`, `overflowAriaLabel`) recebem o total.
75
+ - `overlap` (px): quanto cada avatar avança sobre o anterior. O padrão segue 8
76
+ (`spacing-nano`); 6 é o do CrisDoc e corta menos as iniciais. O recuo do
77
+ último item acompanha.
78
+ - `ring` (px): largura do anel (a borda da cor do fundo). O padrão segue 1,5; 1 é
79
+ o do CrisDoc.
80
+
81
+ As duas últimas escrevem `--umds-avatar-group-overlap` e `--umds-avatar-group-ring`
82
+ no próprio grupo (os padrões vivem no CSS), então só aparece `style` quando você
83
+ as usa.
84
+
85
+ ```vue
86
+ <AvatarGroup
87
+ :avatars="primeiros4"
88
+ :max="4"
89
+ :overlap="6"
90
+ :ring="1"
91
+ :overflowCount="12"
92
+ />
93
+ ```
94
+
95
+ - 8ff3652: feat(badge, tag): tamanhos compactos, `Tag soft` e `pill`, variante `new` e `Badge attached`
96
+
97
+ Tudo opt-in: sem as props novas, o HTML e o visual são os mesmos.
98
+
99
+ **Badge**
100
+
101
+ - `size="2xs"`: 16px de altura, fonte de 10px, raio 4. A fonte de 10px não está
102
+ na escala do DS (o menor degrau é 12px), então é um literal comentado no CSS;
103
+ se o mínimo de 12px for decisão de acessibilidade, o 2xs é o que sai.
104
+ - `variant="new"` (a "novidade" do CrisDoc): amarelo, caixa alta, 800, pílula.
105
+ Solid e soft usam o fundo amarelo; outlined, o contorno. O DS não tem token
106
+ semântico de amarelo, então usa os primitivos `yellow-*` (com o `yellow-light`
107
+ já corrigido) e `gray-darkest` para o texto, que não mudam com o tema
108
+ (contraste 8:1). Candidato a token semântico de destaque.
109
+ - `attached`: rótulo colado no canto superior esquerdo de um card, com os cantos
110
+ de baixo arredondados e os de cima retos. Posiciona em `absolute`: o pai
111
+ precisa de `position: relative`.
112
+
113
+ **Tag**
114
+
115
+ - `size="xs"`: 18px (`line-height: 1`, padding 2 e 8, fonte 12, ícone 12). Foi
116
+ criado um tamanho novo em vez de mexer no `sm` (27px), para não encolher quem
117
+ já usa `sm`. O × e o ícone clicável mantêm o alvo de 24px com margem negativa.
118
+ - `appearance="soft"`: fundo claro da cor da variante, sem contorno.
119
+ - `pill`: cantos totalmente arredondados, em qualquer aparência e tamanho.
120
+ - `variant="new"`: amarelo, nas três aparências (soft = `yellow-light` com texto
121
+ `yellow-dark`).
122
+
123
+ ```vue
124
+ <Badge size="2xs" appearance="solid">SOBR</Badge>
125
+ <Badge variant="new" size="xs">Novidade</Badge>
126
+ <div
127
+ style="position: relative"
128
+ ><Badge attached variant="info" appearance="solid">Tarefa pendente</Badge></div>
129
+ <Tag size="xs" appearance="soft" variant="primary" pill label="SEFIN" />
130
+ <Tag size="xs" appearance="soft" variant="new" pill label="Dado simulado" />
131
+ ```
132
+
133
+ - dd0e159: feat(box): item flex (`grow`, `shrink`, `basis`...) e prop `as`
134
+
135
+ O `Box` ganha as props de item flex do `Stack` e a troca de elemento, com os
136
+ mesmos nomes e valores. Sem as props novas, o HTML e as classes são os mesmos.
137
+
138
+ - `as`: `div` (padrão), `span`, `ul`, `ol`, `li`, `section`, `nav`, `header`,
139
+ `footer`, `form`. `ul` e `ol` saem sem marcador, margem e recuo (o padding do
140
+ Box continua valendo) e com `role="list"`. Com `as="form"`, `onSubmit` recebe
141
+ o evento. Uma linha com borda e fundo dentro de uma lista é `<Box as="li">`.
142
+ - Item flex: `grow`, `shrink` (`"0"` | `"1"`), `basis` (`"auto"`, `"0"`, `"25"`,
143
+ `"33"`, `"50"`, `"66"`, `"75"`, `"100"`; os números são %), `minWidth` (`"0"`
144
+ | `"auto"`; o Box já nasce com `min-width: 0`), `overflow`, `overflowX`,
145
+ `overflowY` e `fullHeight` (o `fullWidth` já existia).
146
+
147
+ Vue: com `as`, o Box passa a ter raiz múltipla, e o Vue não repassa atributos
148
+ de fallthrough a esse tipo de componente. Por isso `class` entra no mesmo
149
+ repasse de `style`, `title`, `role`, `data-*` e `aria-*` (o `Stack` também). Ouvintes
150
+ (`@click`) não caem mais no raiz: ponha-os num filho.
151
+
152
+ ```tsx
153
+ <Box direction="horizontal" gap="xxxs" padding="md">
154
+ <Box shrink="0" basis="25">Filtros</Box>
155
+ <Box grow overflowY="auto" fullHeight>Resultados</Box>
156
+ </Box>
157
+ <Box as="ul" aria-label="Setores"><Box as="li" bordered padding="xxxs">SADM</Box></Box>
158
+ ```
159
+
160
+ - a6872d9: feat(box): `direction`, `gap`, `align`, `justify` e `wrap` (a caixa também é layout)
161
+
162
+ Uma linha, cartão ou região com borda, fundo e padding passa a ser UM componente,
163
+ sem `Stack` por dentro nem flex no CSS do produto. As cinco props têm os mesmos
164
+ nomes e valores do `Stack`; qualquer uma delas liga o `display: flex`. Sem
165
+ nenhuma, o `Box` segue sendo um bloco comum (API antiga intacta).
166
+
167
+ - `direction`: `"vertical"` (padrão quando o flex está ligado) | `"horizontal"`.
168
+ - `gap`: degraus da escala, mais `"none"`. Diferente do `Stack`, não tem valor
169
+ padrão: sem `gap` os filhos ficam colados.
170
+ - `align`, `justify`, `wrap`: como no `Stack`.
171
+ - Também passam a ir para o elemento raiz: `id`, `style`, `title`, `role`,
172
+ `tabIndex`, `data-*` e `aria-*` (uma região pede `role` e `aria-label`).
173
+
174
+ ```tsx
175
+ <Box
176
+ direction="horizontal"
177
+ gap="xxxs"
178
+ align="center"
179
+ justify="between"
180
+ padding="xs"
181
+ background="surface"
182
+ radius="sm"
183
+ bordered
184
+ >
185
+ <Text variant="body2">
186
+ Reforma da cobertura do Ginásio Poliesportivo Municipal
187
+ </Text>
188
+ <Button variant="secondary" size="sm">
189
+ Abrir
190
+ </Button>
191
+ </Box>
192
+ ```
193
+
194
+ Para o elemento semântico (`ul`, `nav`, `section`), continue usando `Stack` com `as`.
195
+
196
+ - d466e57: feat(button): variante `neutral-text` e tamanho `xs`
197
+
198
+ Para barra de ações (editor, filtros, linha de card), onde nenhum botão é a
199
+ ação principal e o azul atrapalha. Sem as props novas, nada muda.
200
+
201
+ - `variant="neutral-text"`: texto cinza (`neutral-dark-down`), sem borda e sem
202
+ fundo; hover em `neutral-light-medium`. O `neutral` continua sendo o
203
+ contornado cinza, então "neutro" cobre os dois: contornado (`neutral`) e
204
+ texto (`neutral-text`). O nome segue o par `negative` / `negative-outlined`.
205
+ - `size="xs"`: 26px de altura, padding lateral 12, fonte 12 e ícone de 12px
206
+ (também no `variant="icon"`, que fica 26 x 26). Os 26px do CrisDoc não estão
207
+ na escala de espaço, então a altura é `calc(spacing-xxs + spacing-micro)`
208
+ (24 + 2), sem token novo.
209
+
210
+ ```vue
211
+ <Button
212
+ variant="neutral-text"
213
+ size="xs"
214
+ :start-icon="faPlus"
215
+ >Nova linha</Button>
216
+ <Button variant="neutral" size="xs">Ordenar: mais recentes</Button>
217
+ <Button size="xs">Resolver</Button>
218
+ ```
219
+
220
+ - d278363: feat(calendar): novo `Calendar`, a agenda com eventos por dia
221
+
222
+ Peça nova: visão de mês e de semana, com eventos por dia, sem biblioteca de
223
+ datas (o `Intl` escreve os nomes de mês e de dia).
224
+
225
+ - `events`: lista plana `{ date, title, color?, time?, id? }`. `date` é
226
+ `YYYY-MM-DD`, data-hora ISO ou `Date`. A grade agrupa por dia e ordena por
227
+ `time`.
228
+ - Cor de DADO por token: `color="--umds-primitive-blue-pure"` (o mesmo valor do
229
+ `ColorPicker`), num chip de fundo suave (a cor a 16% sobre o branco) com barra
230
+ do lado. O texto é sempre escuro: a cor nunca é a única informação e o contraste
231
+ não depende do tom. Sem `color`, o primário.
232
+ - Mês: até `maxVisible` (3) eventos por dia e um "+N" (`onMoreClick(dia,
233
+ escondidos)`). O corte é por QUANTIDADE, não por altura. Semana: sete colunas
234
+ com todos os eventos.
235
+ - Grade acessível (`role="grid"`): um Tab entra no dia em foco (hoje, ou o
236
+ primeiro) e depois nos eventos dele; setas movem de dia (e trocam de mês ou de
237
+ semana na borda), Home e End vão às pontas da semana, PageUp e PageDown trocam
238
+ de mês (ou de semana), Enter e Espaço acionam `onDayClick`. Cada dia tem nome
239
+ ("segunda-feira, 11 de maio de 2026, 2 eventos", `dayLabel` troca) e o de hoje
240
+ leva `aria-current="date"`.
241
+ - `date` e `view` controláveis (`onDateChange`, `onViewChange`) ou internos
242
+ (`defaultDate`, `defaultView`); `selectedDate` marca um dia; `today` fixa o
243
+ "hoje" (testes, demonstração); `weekStartsOn` 0 (domingo) ou 1.
244
+ - Cabeçalho com anterior, próximo, "Hoje" e o seletor Mês/Semana
245
+ (`hideViewSwitcher` esconde), mais dois slots: `headerStart` (filtro de escopo)
246
+ e `headerEnd` (legenda). No Vue são `#header-start` e `#header-end`.
247
+ - Textos por prop: `previousLabel`, `nextLabel`, `todayLabel`, `monthLabel`,
248
+ `weekLabel`, `viewLabel`, `moreLabel` (`{count}`), `moreAriaLabel` (`{count}` e
249
+ `{date}`); `locale` (padrão `pt-BR`).
250
+
251
+ Não faz: eixo de horas (é agenda por dia, não por hora), evento que atravessa
252
+ vários dias e arrastar para reagendar.
253
+
254
+ ```vue
255
+ <Calendar
256
+ :events="[
257
+ {
258
+ date: '2026-05-04',
259
+ title: 'Proc. Administrativo 002/2020',
260
+ color: '--umds-primitive-blue-pure',
261
+ },
262
+ {
263
+ date: '2026-05-11',
264
+ title: 'Ofício 001/2020',
265
+ color: '--umds-primitive-red-pure',
266
+ time: '08:00',
267
+ },
268
+ ]"
269
+ :onEventClick="abrir"
270
+ >
271
+ <template #header-start><Select … /></template>
272
+ <template #header-end><Button variant="secondary" size="sm">Legenda</Button></template>
273
+ </Calendar>
274
+ ```
275
+
276
+ - 33719b6: feat(chips): `size="xs"` e × com moldura circular (`circularRemove`)
277
+
278
+ Opt-in; sem as props novas o `Chips` é o mesmo.
279
+
280
+ - `size="xs"`: 20px de altura, padding lateral 8, fonte de 12px e × de 8px. A
281
+ altura é `calc(spacing-xxxs + spacing-quarck)` (16 + 4), sem token novo. O
282
+ CrisDoc usa fonte de 11px, que não está na escala do DS; fica o degrau de 12px.
283
+ - `circularRemove`: o × dos chips removíveis vai dentro de um círculo de 14px
284
+ tingido da cor do texto do chip (o `::before` usa `currentColor` com 15% de
285
+ opacidade, então acompanha todas as variantes e os temas). É o mesmo botão,
286
+ com o mesmo nome acessível ("Remover <rótulo>") e o mesmo clique; só vale com
287
+ `removable`.
288
+
289
+ ```vue
290
+ <Chips
291
+ label="Processos Inteligentes"
292
+ size="xs"
293
+ variant="primary"
294
+ removable
295
+ circularRemove
296
+ :onRemove="remover"
297
+ />
298
+ ```
299
+
300
+ - 80904af: feat(coachmark): novo `Coachmark`, o tour guiado
301
+
302
+ Peça nova: uma sequência de passos, cada um apontando um elemento da tela com
303
+ um cartão, enquanto o resto da página escurece e o alvo fica destacado num
304
+ recorte (uma caixa transparente cuja sombra escurece o resto, sem máscara nem
305
+ SVG).
306
+
307
+ - `steps`: `{ target?, title, content?, placement? }`. `target` é um seletor CSS
308
+ (`"#aba-fluxos"`), um elemento, uma ref do React (`{ current }`), uma ref do Vue
309
+ (`{ value }`) ou uma função que devolve um deles. Sem alvo (ou alvo que não
310
+ existe), o cartão fica no centro e a página inteira escurece.
311
+ - Posição por `@floating-ui/dom` (já era dependência): `placement` com inversão
312
+ automática, e o recorte e o cartão acompanham rolagem, redimensionamento e
313
+ mudança de tamanho do alvo. O alvo é trazido à tela se estiver fora dela.
314
+ - Controlado por `open`; `onClose(motivo)` com `"finish"` (Concluir no último
315
+ passo), `"skip"` (Sair do tour) ou `"escape"` (Esc). Passo atual interno
316
+ (`defaultStep`) ou controlado (`step` + `onStepChange`). Reabrir recomeça do
317
+ primeiro passo.
318
+ - Acessibilidade: cartão `role="dialog"` com `aria-modal`, nomeado pelo título e
319
+ descrito pelo texto. O foco entra no cartão, o Tab fica preso nele, Esc sai,
320
+ setas esquerda e direita voltam e avançam, e o foco volta ao elemento de antes
321
+ ao fechar. A cada passo o leitor de tela ouve "2 de 8: título" (`aria-live`).
322
+ - Textos por prop: `nextLabel`, `previousLabel`, `finishLabel`, `skipLabel`,
323
+ `counterLabel` ("{current} de {total}"). `hideSkip` esconde o Sair do tour.
324
+ - `padding` (px) é a folga do recorte em torno do alvo (padrão 8).
325
+
326
+ Limite: a página atrás fica inerte durante o tour (o véu captura o clique), então
327
+ o alvo não é clicável. O scrim usa o mesmo `rgba` do Modal, que ainda não tem
328
+ token (candidato a novo token).
329
+
330
+ ```vue
331
+ <Coachmark
332
+ :open="tourAberto"
333
+ :steps="[
334
+ {
335
+ target: '#aba-fluxos',
336
+ title: 'Cada item aberto é uma aba',
337
+ content: 'Fluxos e formulários abrem em abas.',
338
+ },
339
+ { title: 'Pronto', content: 'Sem alvo: o cartão fica no centro.' },
340
+ ]"
341
+ :onClose="() => (tourAberto = false)"
342
+ />
343
+ ```
344
+
345
+ - 390c707: feat(colorpicker): novo `ColorPicker`, as amostras da paleta do 1DS
346
+
347
+ Peça nova. Uma grade de amostras dos primitivos de cor (6 famílias de 4 tons e os
348
+ 7 cinzas, 31 no total), uma linha por família. O valor é o NOME DO TOKEN
349
+ (`--umds-primitive-blue-pure`): guarde o nome e pinte com `var(${valor})`. Como
350
+ primitivo não muda com o tema, a cor escolhida é a mesma no claro e no escuro, o
351
+ que é o certo para cor de dado (marcador, tipo de documento, setor).
352
+
353
+ - `radiogroup`: Tab entra na amostra escolhida (ou na primeira), setas movem a
354
+ escolha, Home e End vão às pontas, amostra desabilitada é pulada. Cada amostra
355
+ tem nome acessível ("Azul escuro") e a escolhida ganha ícone de marcação e anel
356
+ duplo, então a seleção não depende só da cor.
357
+ - `value` / `defaultValue` / `onChange(valor)`; `label` ou `ariaLabel`.
358
+ - `allowCustom` (desligado por padrão): campo de cor livre em hexadecimal
359
+ `#RRGGBB`, que sai em maiúsculas. Textos por prop: `customLabel` e
360
+ `customErrorMessage`.
361
+ - `families` recorta a paleta (`["blue", "gray"]`); `swatches` troca a lista
362
+ inteira (nomes traduzidos, recorte livre). `COLOR_PALETTE` e `isHexColor` saem
363
+ exportados.
364
+ - `size` `sm` (24px) ou `md` (32px, padrão); raio 8px, anel de 1px na amostra.
365
+
366
+ Requer `@1doc/1ds-tokens` com `yellow-light` e `purple-pure` corrigidos (ver o
367
+ changeset `tokens-primitivos-amarelo-roxo`): a paleta lista os 31 primitivos, e
368
+ com o tokens 0.4.3 essas duas amostras saem na cor errada.
369
+
370
+ ```vue
371
+ <ColorPicker
372
+ label="Cor do marcador"
373
+ :value="cor"
374
+ :onChange="(c) => (cor = c)"
375
+ allowCustom
376
+ />
377
+ ```
378
+
379
+ - e3d82fc: feat(datatable): célula livre por coluna, linha de grupo e tipos exportados no Vue
380
+
381
+ A `DataTable` passa a aceitar markup na célula nos dois frameworks. API antiga
382
+ intacta: sem as props e slots novos, o HTML e as classes são os mesmos.
383
+
384
+ - Célula livre. No React, `column.render(row, rowIndex)` já devolvia nó e
385
+ continua assim (o docblock agora diz). No Vue, o retorno do `render` continua
386
+ sendo tratado como texto, e a célula com markup vem do slot `#cell-<key>`,
387
+ que recebe `{ row, value, rowIndex }`. Com `render` e slot na mesma coluna, o
388
+ slot vale.
389
+ - Linha de grupo: `rowGroup` (nome do campo ou função `(row, rowIndex) =>
390
+ rótulo`) abre um `<th scope="rowgroup">` que atravessa a tabela antes de cada
391
+ sequência de linhas com o mesmo rótulo. A tabela não reordena: passe `data` já
392
+ ordenada pelo grupo. O conteúdo do grupo é o rótulo, ou `renderRowGroup(label,
393
+ row, rowIndex)` no React, ou o slot `#row-group` (`{ label, row, rowIndex }`)
394
+ no Vue. A linha de grupo não entra na seleção nem no `onRowClick`.
395
+ - Vue (tipos): o `index.d.ts` do pacote passa a trazer todo tipo exportado pelos
396
+ componentes. Antes só saíam as `*Props`, `*Action` e `*Option`, e a `DataTableProps`
397
+ apontava para um `DataTableColumn` que não existia no arquivo. Agora
398
+ `DataTableColumn`, `DropdownItem`, `AccordionItemData` (e os demais, como
399
+ `StackSpacing`, `BoxSpacing` e `ChartDatum`) podem ser importados de
400
+ `@1doc/1ds-vue`. No React eles já eram exportados.
401
+
402
+ ```vue
403
+ <DataTable :columns="colunas" :data="usuarios" rowGroup="setor">
404
+ <template #cell-nome="{ row }">
405
+ <Avatar type="letter" size="sm">{{ row.nome[0] }}</Avatar> {{ row.nome }}
406
+ </template>
407
+ <template #cell-setores="{ value }">
408
+ <Tag v-for="setor in value" :key="setor" :label="setor" size="sm" />
409
+ </template>
410
+ <template #row-group="{ label }">Setor {{ label }}</template>
411
+ </DataTable>
412
+ ```
413
+
414
+ - a5fe6fe: feat(datatable,descriptionlist): `DataTable variant="document"` e novo `DescriptionList`
415
+
416
+ Para o que é CONTEÚDO de documento (se lê e se imprime), não interface.
417
+
418
+ **`DataTable variant="document"`** (padrão `default`, nada muda sem a prop):
419
+ tabela sem interação, com grade de bordas finas em todas as células, sem hover,
420
+ sem cabeçalho grudado e sem raio. `sortable`, `selectable` e `onRowClick` são
421
+ ignorados: sem botão de ordenar, sem `aria-sort`, sem checkbox, linha fora da
422
+ ordem de Tab. Na impressão (`@media print`) o cabeçalho se repete a cada página,
423
+ uma linha nunca é cortada ao meio e as cores saem (`print-color-adjust`).
424
+ `columns`, `data`, `align`, `width`, `render`/`#cell-<key>` e `density` valem
425
+ como sempre.
426
+
427
+ **`DescriptionList`**, para os pares rótulo/valor (o `DocPares` do CrisDoc não
428
+ cabia na tabela: não tem cabeçalho de coluna). `<dl>` com `<dt>` e `<dd>`:
429
+
430
+ - `items`: `{ label, value, id? }`. Valor vazio mostra "—" (`emptyValue`).
431
+ - `layout="inline"` (padrão): grade de bordas finas, rótulo pintado e sem quebra
432
+ à esquerda, valor à direita; `fit` encolhe até o conteúdo.
433
+ - `layout="stacked"`: rótulo pequeno em cima, valor embaixo, `columns` de 1 a 4
434
+ (vira 1 em tela estreita); `bordered` põe o valor na caixa de um campo
435
+ somente leitura.
436
+ - `ariaLabel` ou `ariaLabelledby`. No Vue o `value` é texto (valor com marcação:
437
+ monte com `Stack` e `Text`).
438
+
439
+ ```vue
440
+ <DataTable variant="document" :columns="colunas" :data="itens" />
441
+ <DescriptionList
442
+ ariaLabel="Dados de empenho"
443
+ :items="[
444
+ { label: 'Empenho', value: '2026NE000184' },
445
+ { label: 'Valor empenhado', value: 'R$ 51.840,00' },
446
+ ]"
447
+ />
448
+ ```
449
+
450
+ - 801c5c2: feat(fileinput): `variant="trigger"`, o seletor aberto por outro controle
451
+
452
+ Para o "Anexar arquivo" de um botão ou o "Alterar foto" de um link, sem a caixa
453
+ de arrastar. Opt-in; `base` e `card` não mudam.
454
+
455
+ - `variant="trigger"`: o conteúdo que você passa (React: `children`; Vue: slot
456
+ padrão) é o gatilho. O clique nele abre o seletor (o clique sobe até o
457
+ envoltório, então o Enter num `Button` também funciona), e `accept`,
458
+ `multiple`, `name`, `files`, `onChange` e `onRemove` funcionam igual. O input
459
+ nativo fica oculto ao lado, fora do Tab (o gatilho é quem recebe o foco) e
460
+ com nome acessível (`label` ou `selectFileLabel`). `disabled` não abre.
461
+ - O `label` visível não aparece no `trigger`: o gatilho é o próprio conteúdo; o
462
+ `label` serve de nome acessível do input.
463
+ - Não há `open()` exposto: o Mitosis não tem como expor método imperativo nos
464
+ dois frameworks. O `trigger` cobre o caso (botão ou link que abre o seletor).
465
+
466
+ ```vue
467
+ <FileInput
468
+ variant="trigger"
469
+ accept=".pdf,.docx"
470
+ :multiple="true"
471
+ :onChange="anexar"
472
+ >
473
+ <Button variant="secondary" startIcon="paperclip">Anexar arquivo</Button>
474
+ </FileInput>
475
+ ```
476
+
477
+ - 0e89b88: feat(iconpicker): novo `IconPicker`, a grade de ícones com busca
478
+
479
+ Peça nova, sem dependência: os ícones vêm por prop.
480
+
481
+ - `icons`: objetos do Font Awesome importados (`faUser`, `faFolder`...), ou
482
+ `{ icon, label?, keywords? }` quando o nome ou a busca precisam de ajuda. O nome
483
+ de um ícone sem `label` é o `iconName` sem hífen ("file lines"); `iconLabel`
484
+ traduz.
485
+ - O valor é o NOME do ícone (`"user"`, `"file-lines"`): `value`/`defaultValue`,
486
+ `onChange(nome, item)`. Guarde o nome e resolva de volta para o objeto na hora de
487
+ desenhar.
488
+ - `radiogroup`: Tab entra no ícone escolhido (ou no primeiro); setas movem a
489
+ escolha (esquerda e direita um ícone, cima e baixo uma linha: `columns`, padrão
490
+ 8), Home e End vão às pontas. O escolhido ganha fundo e borda do primário e
491
+ `aria-checked`.
492
+ - Busca (ligada; `hideSearch` esconde) por nome, rótulo e palavras-chave, sem
493
+ acento nem caixa. A seta para baixo no campo leva à grade, e o número de
494
+ resultados é anunciado (`role="status"`). Sem resultado, mostra `emptyText`.
495
+ - `maxHeight` (px) limita a grade e rola dentro dela; `size` `sm` ou `md`;
496
+ `disabled`.
497
+ - Textos por prop: `searchLabel`, `searchPlaceholder`, `emptyText`, `resultsLabel`
498
+ (`{count}`).
499
+
500
+ ```vue
501
+ <IconPicker
502
+ label="Ícone da categoria"
503
+ :icons="[
504
+ faFolder,
505
+ faFileLines,
506
+ { icon: faBuilding, label: 'Órgão', keywords: ['prefeitura'] },
507
+ ]"
508
+ :value="icone"
509
+ :onChange="(nome) => (icone = nome)"
510
+ />
511
+ ```
512
+
513
+ - 4d0cb08: feat(input): `onChange` a cada tecla no Vue, `mask`, `iconRight` e `borderless`
514
+
515
+ - **`onChange` a cada tecla no Vue (paridade com o React).** O campo passa a
516
+ escutar `input` além de `change`. Antes, no Vue, `onChange` só disparava quando
517
+ o campo perdia o foco (o evento `change` nativo). Os dois eventos entram no
518
+ mesmo tratador, que descarta o repetido: no React os dois disparam para o
519
+ mesmo evento nativo, e no Vue o `change` do blur repete o valor que o `input`
520
+ da última tecla já entregou. O resultado é uma chamada por tecla nos dois
521
+ frameworks. Um `change` disparado à mão com valor novo (testes de quem
522
+ consome) também chega. `onBlur` segue sendo o evento de saída do campo.
523
+ Quem contornava o blur no Vue com `@input` por fora pode tirar o contorno.
524
+ - `mask`: `"cpf"`, `"cnpj"`, `"cep"` ou `"phone"` (10 ou 11 dígitos). O valor
525
+ exibido e o que chega em `onChange` já vêm formatados; para só os dígitos,
526
+ `valor.replace(/\D/g, "")`. Aceita só dígitos, limita o tamanho (`maxlength`) e
527
+ abre o teclado numérico no celular (`inputmode="numeric"`). Valor controlado
528
+ só com dígitos também aparece formatado. Cursor: reformatar no meio do texto
529
+ leva o cursor ao fim (suficiente para digitar do início ao fim).
530
+ - `iconRight`: ícone decorativo à direita, `aria-hidden`, sem clique. Para ação,
531
+ continua `iconsRight`.
532
+ - `borderless`: sem borda, fundo e raio, para o campo dentro de um grupo que já
533
+ tem a moldura (um `Select` e um `Input` lado a lado numa caixa). O foco não
534
+ some: vira contorno de 2px para dentro. Com erro, a borda vermelha fica.
535
+
536
+ ```vue
537
+ <Input label="CPF" mask="cpf" :onChange="(v) => (cpf = v)" />
538
+ <Input
539
+ ariaLabel="Número"
540
+ placeholder="Número"
541
+ borderless
542
+ fullWidth
543
+ iconRight="search"
544
+ />
545
+ ```
546
+
547
+ - cfb8c4a: feat(kbd,codeblock): novos `Kbd` e `CodeBlock`, e o token de fonte monoespaçada
548
+
549
+ **Token novo** (`@1doc/1ds-tokens`): `--umds-primitive-font-family-mono` e o
550
+ semântico `--umds-semantic-font-family-mono` (`ui-monospace, SFMono-Regular,
551
+ Menlo, Consolas, 'Liberation Mono', monospace`). É a pilha de fontes do sistema:
552
+ nenhuma fonte baixada, então nenhum pedido de rede novo. O produto cita o
553
+ semântico; os dois componentes abaixo já o usam.
554
+
555
+ **`Kbd`**: uma tecla ou uma combinação, em `<kbd>`.
556
+
557
+ - Uma tecla vai como conteúdo (`<Kbd>Esc</Kbd>`); uma combinação em `keys`
558
+ (`["Ctrl", "Shift", "P"]`), com `separator` entre as teclas (padrão `+`). Cada
559
+ tecla é um `<kbd>` dentro do `<kbd>` do conjunto, que é como o HTML diz
560
+ "combinação". O leitor de tela lê "Ctrl + Shift + P".
561
+ - Caixa cinza com borda e base mais grossa, fonte monoespaçada; `size` `sm` ou
562
+ `md`. Raiz única: `title`, `data-*`, `aria-*` e ouvintes chegam ao elemento.
563
+
564
+ **`CodeBlock`**: trecho de código, JSON ou log, com borda, rolagem e cópia.
565
+
566
+ - O texto vem por `code` ou como conteúdo, com espaços e quebras mantidos. Linha
567
+ longa rola na horizontal, ou quebra com `wrap`; `maxHeight` (px) limita a
568
+ altura e rola na vertical.
569
+ - A área de rolagem é `role="region"` focável (Tab) e nomeada (`ariaLabel`, senão
570
+ a `language`, senão "Código"): quem usa o teclado consegue rolar.
571
+ - `copyable` mostra o botão de copiar no cabeçalho: copia o texto inteiro (não só
572
+ o que está à vista), troca para "Copiado" por dois segundos e anuncia ao leitor
573
+ de tela. Usa `navigator.clipboard`, e recorre a `execCommand("copy")` quando ele falha.
574
+ `onCopy(texto)` avisa. `copyLabel` e `copiedLabel` por prop.
575
+ - `language` é só rótulo no topo. Não colore sintaxe (pede uma biblioteca); fundo
576
+ claro e texto escuro nos dois temas.
577
+
578
+ ```vue
579
+ <Kbd :keys="['Ctrl', 'K']" size="sm" />
580
+ <CodeBlock language="JSON" :code="envio" copyable />
581
+ ```
582
+
583
+ - fcd9c32: feat(list): estado vazio dentro da lista (`isEmpty`)
584
+
585
+ O `List` passa a trazer o estado vazio. Com `isEmpty`, as linhas dão lugar a um
586
+ `EmptyState` DENTRO da lista: o título do cartão, a busca, os filtros e a
587
+ paginação ao redor continuam montados (e o foco no campo de busca não se perde),
588
+ porque só o miolo troca. A lista não conta filhos: `isEmpty` é a decisão de
589
+ quem a usa (`:is-empty="!itens.length"`).
590
+
591
+ - Texto: `emptyTitle` (padrão "Nenhum item encontrado"), `emptyDescription`,
592
+ `emptyIcon` (objeto do Font Awesome), `emptySize` (`sm` padrão, `md`, `lg`).
593
+ - Ação: `emptyActionLabel` com `onEmptyAction`. Sem o callback o botão não
594
+ aparece.
595
+ - Conteúdo próprio: slot `empty` (no React, a prop `empty`) no lugar do
596
+ `EmptyState`.
597
+ - Acessibilidade: o bloco vazio é `role="status"`, então a lista esvaziar é
598
+ anunciada. Sem itens não há `ul` vazia no DOM.
599
+
600
+ ```vue
601
+ <List
602
+ ariaLabelledby="titulo"
603
+ :isEmpty="!docs.length"
604
+ emptyTitle="Nenhum documento"
605
+ emptyDescription="Tudo em dia."
606
+ :emptyIcon="faInbox"
607
+ emptyActionLabel="Atualizar"
608
+ @emptyAction="recarregar"
609
+ >
610
+ <ListItem v-for="d in docs" :key="d.id" :title="d.titulo" />
611
+ </List>
612
+ ```
613
+
614
+ - 4b57ca7: feat(list): novos `ListItem` e `List`, a linha de lista inteira clicável
615
+
616
+ Peça nova. O `ListItem` é a linha cujo alvo de clique e de foco é a linha
617
+ toda, com conteúdo livre. Renderiza um `<li>` com UM `button`, `a` ou `div`
618
+ dentro, por isso vive num `List` (ou num `ul`/`ol`, como `Stack as="ul"`).
619
+
620
+ - `as`: `button` | `a` | `div`. Sem `as`, vira `a` quando há `href` e `button`
621
+ nos outros casos. `div` é a linha que só mostra; com `onClick` ganha
622
+ role="button", tabindex 0, Enter e Espaço. `target="_blank"` põe
623
+ `rel="noopener noreferrer"` sozinho.
624
+ - Conteúdo: `start`, `title`, `subtitle`, `meta`, `end` e o conteúdo padrão (abaixo
625
+ de `meta`). `title`, `subtitle` e `meta` aceitam texto por prop ou nó por slot.
626
+ No Vue os slots se chamam igual (`#start`, `#title`...); no React são as
627
+ props. Região vazia não desenha nada.
628
+ - Estados: hover e foco visível (anel interno), `selected` (fundo de seleção e
629
+ `aria-current="true"`), `disabled` (button desabilitado; link perde o `href` e
630
+ ganha `aria-disabled`).
631
+ - `id`, `style`, `role`, `tabIndex`, `data-*` e `aria-*` vão para o elemento
632
+ interativo (é nele que entra o `aria-label`). `title` é o título da linha, não
633
+ o atributo HTML.
634
+ - `List`: `ul` (padrão) ou `ol`, sempre com `role="list"` (o Safari tira a
635
+ semântica de `list-style: none`), `gap` na escala do DS (padrão `quarck`),
636
+ `ariaLabel` ou `ariaLabelledby`.
637
+
638
+ Medidas: padding 8 12 (o 10 12 do CrisDoc não existe na escala), raio 8, título
639
+ 14/600, subtítulo 14 e meta 12, todos pelo `Text`.
640
+
641
+ ```vue
642
+ <List ariaLabel="Documentos não lidos" gap="nano">
643
+ <ListItem selected title="Memorando 114/2025" subtitle="Novo contrato - Governo"
644
+ meta="23 de agosto de 2025" @click="abrir(doc)">
645
+ <template #start><Avatar type="letter" size="sm">I</Avatar></template>
646
+ <template #end><Badge variant="info" size="sm">novo</Badge></template>
647
+ </ListItem>
648
+ </List>
649
+ ```
650
+
651
+ - eeb6a16: feat(modal): `variant="primary"`, `width`/`maxWidth`, `windowControls` em lista e `responsive`; o Esc respeita quem já o usou
652
+
653
+ Tudo opt-in; sem as props novas o modal é o mesmo.
654
+
655
+ - `variant="primary"`: cabeçalho cheio na cor primária (título, subtítulo e
656
+ controles em `neutral-light-pure`, hover em `primary-dark`). É o modal base com
657
+ as três faixas, não o diálogo de feedback.
658
+ - `width` e `maxWidth`: qualquer valor CSS. `width` sozinho solta o teto do
659
+ `size` (o 498px do `md` não segura mais) e passa a ser limitado pela tela.
660
+ Com `windowControls`, valem só no modo normal.
661
+ - `windowControls` aceita `true` (o conjunto inteiro, como antes) ou uma lista
662
+ com os controles que quiser: `["expand", "fullscreen"]`. Nomes: `normal`,
663
+ `expand`, `fullscreen`, `minimize`. Em lista, sem `normal`, clicar de novo no
664
+ modo ativo volta ao normal, e o modo normal usa o tamanho do próprio modal
665
+ (não os 780px do conjunto inteiro). O divisor só aparece com algum controle e
666
+ com o ×. `onMinimize` só existe se `minimize` estiver na lista.
667
+ - `responsive` e `responsiveBreakpoint` (padrão 640, lido na montagem): abaixo
668
+ da largura, o modal vira um painel que sobe pela borda de baixo (largura
669
+ total, cantos de cima arredondados, alça, entrada por baixo), como o
670
+ `BottomSheet`; acima, continua centralizado. É o mesmo componente reorganizado
671
+ (não monta um `BottomSheet` por dentro, porque o Mitosis não repassa slot de
672
+ um componente a outro), então não tem o gesto de arrastar. No painel os
673
+ controles de janela e a largura livre somem.
674
+ - Esc: o ouvinte do `document` passa a rodar no borbulho e a ignorar a tecla se
675
+ `defaultPrevented`. `Select`, `Combobox`, `Popover` e `Dropdown` já faziam
676
+ `preventDefault`; `DatePicker` e `MultiSelect` passaram a fazer. Resultado: um
677
+ `Select` ou `DatePicker` aberto dentro do modal fecha só a lista, e o modal
678
+ fica. Quem tinha contorno para isso pode tirá-lo.
679
+
680
+ ```vue
681
+ <Modal
682
+ open
683
+ variant="primary"
684
+ width="600px"
685
+ :window-controls="['expand', 'fullscreen']"
686
+ title="Verificar rotas e quilometragem"
687
+ responsive
688
+ >
689
+ ...
690
+ </Modal>
691
+ ```
692
+
693
+ - 56229f0: feat(orgchart): novo `OrgChart`, o organograma com conectores
694
+
695
+ Peça nova: uma árvore desenhada de cima para baixo, com linhas ligando cada pai
696
+ aos filhos, em que os nós com filhos expandem e recolhem. Sem dependência.
697
+
698
+ - `nodes`: lista de nós raiz `{ id, title, subtitle?, children? }`. Mais de uma
699
+ raiz funciona (floresta).
700
+ - O desenho é calculado, não aninhado (o Mitosis não gera componente recursivo de
701
+ forma confiável): cada nó tem largura e altura fixas (`nodeWidth` 176,
702
+ `nodeHeight` 64, em px), os filhos se distribuem sob o pai (`gapX` 16) e o pai se
703
+ centra sobre eles; um nível desce `gapY` (40). Os conectores são um SVG de uma
704
+ linha por pai. O container rola quando o organograma passa da largura.
705
+ - Visual: a raiz cheia na cor primária, os demais em tom claro; `selectedId` marca
706
+ um nó. O título e o subtítulo cortam com reticências (o texto inteiro vai no
707
+ tooltip).
708
+ - Conteúdo livre do nó: no React `renderNode(nó, { level, expanded })`; no Vue o
709
+ slot `node` com escopo `{ node, level, expanded }` (ligado no `postbuild.js`,
710
+ como o do `DataTable`). O conteúdo precisa caber na caixa do nó.
711
+ - Expandir e recolher: tudo aberto por padrão; `defaultCollapsedIds` (ou
712
+ `collapsedIds` controlado) escolhe o que começa recolhido, e
713
+ `onCollapsedChange(ids)` avisa. O botão +/− no pé do nó é para o mouse.
714
+ - Acessibilidade: `role="tree"` com nós `treeitem` (`aria-level`,
715
+ `aria-posinset`, `aria-setsize`, `aria-expanded`, `aria-selected`). Um Tab entra
716
+ no nó em foco; Baixo vai ao primeiro filho (e abre o nó, se recolhido), Cima ao
717
+ pai, Esquerda e Direita aos irmãos, Home e End ao primeiro e ao último irmão,
718
+ Espaço expande ou recolhe, Enter aciona `onNodeClick`.
719
+ - Textos por prop: `ariaLabel` ("Organograma"), `expandLabel`, `collapseLabel`.
720
+
721
+ Limites do primeiro corte: só de cima para baixo; sem zoom nem arrastar; nó de
722
+ altura variável não cabe (use `nodeHeight` para o maior). Para navegar e escolher
723
+ em hierarquias grandes, o `Tree` é mais denso e acessível.
724
+
725
+ ```vue
726
+ <OrgChart :nodes="setores" ariaLabel="Setores da COPIRN" :onNodeClick="abrir">
727
+ <template #node="{ node }"><Avatar size="sm">{{ node.title }}</Avatar></template>
728
+ </OrgChart>
729
+ ```
730
+
731
+ - e8453bc: feat(otpinput): novo `OtpInput`, o código de verificação em caixas
732
+
733
+ Peça nova para códigos curtos recebidos por outro canal (autenticação em duas
734
+ etapas, confirmação de e-mail ou telefone).
735
+
736
+ - `length` caixas (6 por padrão). Digitar avança o foco; Backspace apaga e, em
737
+ caixa vazia, volta e apaga a anterior; setas, Home e End movem.
738
+ - Colar o código inteiro em qualquer caixa distribui os caracteres (um pedaço
739
+ entra a partir da caixa atual). O preenchimento automático do SMS também,
740
+ porque a primeira caixa leva `autocomplete="one-time-code"`.
741
+ - Sem buraco: focar uma caixa à frente da primeira vazia manda o foco de volta a
742
+ ela.
743
+ - Valor em string: `value`/`defaultValue`, `onChange(codigo)` a cada mudança e
744
+ `onComplete(codigo)` quando as caixas enchem (uma vez por código novo).
745
+ - `type="numeric"` (padrão, teclado numérico no celular) ou `"alphanumeric"`
746
+ (letras e dígitos, em maiúsculas).
747
+ - Acessibilidade: `role="group"` nomeado por `label` ou `ariaLabel`; cada caixa
748
+ tem nome próprio (`digitLabel`, padrão "Dígito {n} de {total}", traduzível);
749
+ `errorMessage`/`invalid` ligam `aria-invalid` e `aria-describedby`.
750
+ - `size` `sm` ou `md`; foco e erro seguem os tokens de campo.
751
+
752
+ ```vue
753
+ <OtpInput
754
+ label="Código de verificação"
755
+ :length="6"
756
+ :onComplete="(codigo) => verificar(codigo)"
757
+ errorMessage="Código inválido ou expirado."
758
+ />
759
+ ```
760
+
761
+ - d89ebe3: feat(popover): `maxHeight` para o corpo do painel
762
+
763
+ - `maxHeight`: altura máxima do corpo, que rola além dela. Número vira px; texto
764
+ vai como CSS (`"60vh"`). `"none"` deixa o corpo crescer com o conteúdo, como
765
+ no painel "Colunas do card" do CrisDoc.
766
+ - Sem a prop, **o teto de 300px continua**: tirá-lo por padrão faria todo painel
767
+ existente com lista longa estourar a tela sem rolagem. Quem quer o corpo livre
768
+ passa `maxHeight="none"`. O cabeçalho e o × não rolam junto, como antes.
769
+
770
+ ```vue
771
+ <Popover title="Colunas do card" maxHeight="none" :width="260">
772
+ <Button>Personalizar</Button>
773
+ <template #content>...</template>
774
+ </Popover>
775
+ ```
776
+
777
+ - 3c482fa: feat(richtexteditor): novo `RichTextEditor`, texto rico leve sem biblioteca
778
+
779
+ Peça nova, sobre `contenteditable` e `document.execCommand`. Sem dependência
780
+ nova: o primeiro corte é o que as telas de despacho, resposta e descrição de
781
+ serviço pedem.
782
+
783
+ - Ferramentas: negrito, itálico, sublinhado, tachado, lista com marcadores, lista
784
+ numerada, link, desfazer, refazer e limpar formatação. A barra se escolhe por
785
+ `toolbar` (a ordem do array é a da tela, `"|"` é um separador): a padrão traz
786
+ negrito, itálico, sublinhado, listas, link, desfazer e refazer;
787
+ `["bold", "italic", "underline", "ul", "ol", "link"]` é a compacta e
788
+ `["bold", "italic"]` a mínima.
789
+ - `value`/`defaultValue`/`onChange` em HTML. O HTML é SEMPRE higienizado, tanto o
790
+ que entra por `value` quanto o que se cola: ficam só `a`, `b`/`strong`,
791
+ `i`/`em`, `u`, `s`/`strike`/`del`, `ul`, `ol`, `li`, `p`, `br`, `div`, `span`,
792
+ títulos e citação; `script`, `style`, `onerror`, `class` e `javascript:` saem.
793
+ Colar entra como texto puro. Link só aceita `http(s)`, `mailto`, `tel`, caminho
794
+ e âncora, e ganha `rel="noopener noreferrer"`. `sanitizarHtml`, `enderecoSeguro`
795
+ e `normalizarEndereco` vivem em `utils/html-seguro`.
796
+ - A barra é `role="toolbar"` (Tab numa parada só, setas, Home e End entre as
797
+ ferramentas). Negrito, itálico, sublinhado, tachado e as listas são botões de
798
+ liga/desliga (`aria-pressed`) que seguem o cursor. A área é `role="textbox"`
799
+ multilinha, com `label` ou `ariaLabel`, `aria-invalid` e `aria-describedby`
800
+ (`errorMessage`, `helperText`). Ctrl+K abre o link.
801
+ - Link sem modal: um campo logo abaixo da barra (endereço, Aplicar, Remover link,
802
+ Cancelar; Esc fecha). Sem texto escolhido, o endereço vira o texto do link.
803
+ Endereço sem esquema ganha `https://`; endereço perigoso mostra o erro e não
804
+ vira link.
805
+ - `footer` (slot): a assinatura do autor, dentro da moldura; `resizable` e
806
+ `minHeight` (px); `readOnly` (sem barra) e `disabled`; `invalid`.
807
+ - Textos por prop: `placeholder`, `toolbarLabel` e `labels` (parcial: `bold`,
808
+ `italic`, `underline`, `strike`, `ul`, `ol`, `link`, `undo`, `redo`, `clear`,
809
+ `linkAddress`, `linkApply`, `linkRemove`, `linkCancel`, `linkInvalid`).
810
+
811
+ Fora deste corte, por tamanho: tabela, imagem, cor, fonte, tamanho e
812
+ alinhamento. Limite técnico: `document.execCommand` é obsoleto no padrão, mas
813
+ todos os navegadores o mantêm; o histórico do desfazer varia um pouco entre eles.
814
+
815
+ ```vue
816
+ <RichTextEditor
817
+ label="Despacho"
818
+ :value="html"
819
+ :onChange="(h) => (html = h)"
820
+ :toolbar="['bold', 'italic', 'underline', '|', 'ul', 'ol', '|', 'link']"
821
+ >
822
+ <template #footer>Ana Paula Souza, SADM</template>
823
+ </RichTextEditor>
824
+ ```
825
+
826
+ - b02f4ff: feat(select): `placement` (a lista abre para cima) e variante `filter` com opção "sem filtro" e rodapé
827
+
828
+ Tudo opt-in; sem as props novas o `Select` é o mesmo.
829
+
830
+ - `placement`: `bottom` (padrão), `top` ou `auto`. O `auto` mede o espaço na hora
831
+ de abrir e abre para cima só se a lista (altura estimada, no máximo os 300px
832
+ do CSS) não cabe embaixo e há mais espaço em cima, como o campo no rodapé de
833
+ um modal numa janela baixa. A lista continua dentro do campo (posição
834
+ absoluta), então um contêiner com `overflow` ainda pode cortá-la, igual
835
+ antes.
836
+ - `variant="filter"`: botão de filtro de barra de ferramentas, contornado em
837
+ azul (`primary-pure` sobre `primary-light`), largura do conteúdo, lista de no
838
+ mínimo 240px, busca focada ao abrir. Combina com `searchable`.
839
+ - `emptyOptionLabel`: opção "sem filtro" no topo da lista (seleção única).
840
+ Aparece marcada enquanto nada está escolhido; escolhê-la chama `onChange("")` e
841
+ o campo volta a mostrar o `placeholder`, que é o nome do filtro.
842
+ - `footer`: rodapé fixo da lista, com ações ("Gerenciar marcadores"). React:
843
+ elemento; Vue: slot `footer`. Clicar nele não fecha a lista.
844
+
845
+ ```vue
846
+ <Select
847
+ variant="filter"
848
+ size="sm"
849
+ placeholder="Marcadores"
850
+ :searchable="true"
851
+ emptyOptionLabel="Todos os marcadores"
852
+ :options="marcadores"
853
+ :value="filtro"
854
+ :onChange="(v) => (filtro = v)"
855
+ placement="auto"
856
+ >
857
+ <template #footer><Button variant="text" size="sm">Gerenciar marcadores</Button></template>
858
+ </Select>
859
+ ```
860
+
861
+ - e45ce94: feat(stack): `gap="none"`, prop `as`, props de item flex e atributos HTML
862
+
863
+ O `Stack` passa a cobrir o que o produto ainda escrevia em CSS próprio. API
864
+ antiga intacta: sem as props novas, o HTML e as classes são os mesmos.
865
+
866
+ - `gap="none"` zera o espaço (antes só havia os degraus da escala).
867
+ - `as`: `div` (padrão), `span`, `ul`, `ol`, `li`, `section`, `nav`, `header`,
868
+ `footer`, `form`. `ul` e `ol` saem sem marcador, margem e recuo, com
869
+ `role="list"` (o Safari tira a semântica de lista de `list-style: none`).
870
+ Com `as="form"`, `onSubmit` recebe o evento.
871
+ - Atributos HTML (`id`, `style`, `title`, `role`, `tabIndex`, `data-*`,
872
+ `aria-*`) vão para o elemento raiz. Sem isso `as="nav"` não tinha como levar
873
+ `aria-label`.
874
+ - Props do próprio Stack como item de outro Stack/flex: `grow`, `shrink`
875
+ (`"0"` | `"1"`), `basis` (`"auto"`, `"0"`, `"25"`, `"33"`, `"50"`, `"66"`,
876
+ `"75"`, `"100"`; os números são %), `minWidth` (`"0"` | `"auto"`; o Stack
877
+ já nasce com `min-width: 0`), `overflow`, `overflowX`, `overflowY`,
878
+ `fullHeight` e `fullWidth`.
879
+
880
+ Decisão: não existe `Stack.Item`. Quem precisa crescer, encolher ou ocupar a
881
+ altura aninha um Stack com as mesmas props. Subcomponente por ponto não
882
+ sobrevive aos dois geradores do Mitosis, e o Stack aninhado já é um item flex.
883
+
884
+ ```tsx
885
+ <Stack as="nav" aria-label="Atalhos" fullHeight>
886
+ <Stack as="ul" gap="none">
887
+ <Stack as="li">...</Stack>
888
+ </Stack>
889
+ <Stack grow overflowY="auto">
890
+ ...
891
+ </Stack>
892
+ <Stack shrink="0">...</Stack>
893
+ </Stack>
894
+ ```
895
+
896
+ - 1d59843: feat(statcard): `labelPosition="top"` e `infoTooltip`
897
+
898
+ Opt-in; sem as props novas o `StatCard` é o mesmo.
899
+
900
+ - `labelPosition="top"`: o rótulo vai para o topo do cartão, acima do ícone e do
901
+ número, e o número passa a 32/800 (o degrau `font-size-lg` do DS), como no
902
+ painel da 1Doc. Só a posição visual muda: no HTML o número continua antes do
903
+ rótulo, então o leitor de tela anuncia na mesma ordem. Por baixo, o corpo vira
904
+ `display: contents` e o cartão uma grade de duas colunas.
905
+ - `infoTooltip`: texto de ajuda; mostra um ⓘ ao lado do rótulo com o `Tooltip`
906
+ `dark`. É um botão focável (`infoLabel` traduz o nome, "Mais informações" por
907
+ padrão) e a ajuda chega ao leitor de tela como descrição do botão. Dentro de
908
+ um cartão com `onClick` seria botão dentro de botão: evite a combinação.
909
+
910
+ ```vue
911
+ <StatCard
912
+ labelPosition="top"
913
+ :value="44"
914
+ label="Não lidos"
915
+ :icon="faEyeSlash"
916
+ variant="primary"
917
+ infoTooltip="Documentos que você ainda não abriu."
918
+ />
919
+ ```
920
+
921
+ - 3d6dd1d: feat(tabs): contador em pílula (`count`) e aba fechável (`closable`) com botão "+" (`onAdd`)
922
+
923
+ Tudo opt-in. Sem as props novas, a aba e a barra se comportam como antes (cada
924
+ `Tab` ganha um `<span role="presentation">` com `display: contents`, que não
925
+ muda o layout, e o `Tabs` ganha uma `div` de barra com o mesmo comportamento).
926
+
927
+ **Tab**
928
+
929
+ - `count` (número ou texto): pílula de 18px ao lado do texto, azul na aba ativa
930
+ (`primary-pure`) e cinza nas outras (`neutral-light-medium`). O `0` aparece. O
931
+ número entra no nome acessível da aba ("Todas 31").
932
+ - `closable`: × num botão próprio, irmão da aba (não dentro dela, para não
933
+ aninhar botão), círculo de 20px. A tecla Delete na aba focada faz o mesmo.
934
+ O × não é uma parada de Tab (a aba já tem o Delete); tem nome "Fechar <aba>".
935
+ - `onClose(index, event)`: quem remove a aba é o app. Clicar no × não troca de aba.
936
+ - `closeLabel`: prefixo do nome acessível do ×, para traduzir ("Close Doc 1").
937
+
938
+ **Tabs**
939
+
940
+ - `onAdd(event)`: mostra o "+" logo depois da última aba, **fora** do
941
+ `role="tablist"` (o tablist só pode ter abas). `addLabel` traduz o nome
942
+ ("Adicionar aba" por padrão).
943
+
944
+ ```vue
945
+ <Tabs
946
+ :value="atual"
947
+ :onChange="mudar"
948
+ :onAdd="adicionar"
949
+ addLabel="Adicionar aba"
950
+ >
951
+ <Tab label="Todas" index="0" :count="31" />
952
+ <Tab v-for="a in abas" :key="a.id" :label="a.nome" :index="a.id"
953
+ :closable="true" closeLabel="Fechar" :onClose="fechar" />
954
+ </Tabs>
955
+ ```
956
+
957
+ Ficou de fora desta rodada: o ponto
958
+ de estado da aba (a bolinha ao lado do nome); a rolagem horizontal das abas já existia.
959
+
960
+ - 96e752b: feat(tooltip): `variant="dark"` compacto e `maxWidth`
961
+
962
+ Opt-in; sem as props novas o `Tooltip` é o mesmo.
963
+
964
+ - `variant="dark"`: balão escuro e compacto (padding 4/8, raio 4, teto de 220px)
965
+ para ícone, sigla e botão de barra de ferramentas. Fundo `background-dark` e
966
+ texto `neutral-light-pure`: o par invertido do tema, então o contraste vale nos
967
+ temas claros, no escuro e no alto contraste (sem cor fixa). A fonte é a de
968
+ 12px do DS (o CrisDoc usa 11px, que não está na escala). A seta acompanha a cor.
969
+ - `maxWidth`: largura máxima do balão, qualquer valor CSS, vence o teto de cada
970
+ variante (280px no padrão, 220px no dark).
971
+
972
+ ```vue
973
+ <Tooltip variant="dark" content="Atualizar" maxWidth="200px">
974
+ <Button variant="neutral-text" size="xs">Atualizar</Button>
975
+ </Tooltip>
976
+ ```
977
+
978
+ ### Patch Changes
979
+
980
+ - 2259459: fix(ailabel): `defaultOpen` passa a funcionar
981
+
982
+ A prop era declarada e documentada, mas nunca lida. Agora o painel nasce
983
+ aberto com `defaultOpen` (também no HTML do servidor) e o clique continua
984
+ abrindo e fechando. `open` controlado segue vencendo.
985
+
986
+ - e00b163: fix(combobox): placeholder do campo somente leitura passa 4,5:1
987
+
988
+ Sobre o fundo de somente leitura o placeholder dava 4,20:1 no 1doc (e
989
+ 4,21–4,31:1 nos temas claros de cor). Agora usa `neutral-dark-down`: 6,78:1 no
990
+ 1doc, 10,83:1 no 1doc-dark e 16,48:1 no alto contraste.
991
+
992
+ - 19ff160: fix(datepicker): placeholder do campo somente leitura passa 4,5:1
993
+
994
+ Sobre o fundo de somente leitura o placeholder dava 4,2:1 nos temas claros e
995
+ o axe reprovava (`color-contrast`). Agora usa `neutral-dark-down`: 6,78:1 no
996
+ 1doc, 10,83:1 no 1doc-dark e 16,48:1 no alto contraste.
997
+
998
+ - 9315dd7: fix(datepicker): `value` e `defaultValue` chegam ao campo no modo single
999
+
1000
+ No modo single o componente só lia `range`: `value` e `defaultValue` eram
1001
+ ignorados e o campo mostrava o placeholder. Agora `value` controla o campo e
1002
+ `defaultValue` semeia o modo não-controlado. O modo range não muda.
1003
+
1004
+ - 2250bb4: fix(input): placeholder do campo somente leitura passa 4,5:1
1005
+
1006
+ Sobre o fundo de somente leitura o placeholder dava 4,20:1 no 1doc (e
1007
+ 4,21–4,31:1 nos temas claros de cor). Agora usa `neutral-dark-down`: 6,78:1 no
1008
+ 1doc, 10,83:1 no 1doc-dark e 16,48:1 no alto contraste.
1009
+
1010
+ - ef321dc: fix(kanban): quadro não faz a página rolar na horizontal em tela estreita
1011
+
1012
+ O texto só para leitor de tela de cada coluna é `position: absolute` e, sem
1013
+ ancestral posicionado, escapava da rolagem do quadro: a 375px a página ganhava
1014
+ rolagem lateral. `.umds-kanban` passa a ser `position: relative`; o visual não
1015
+ muda.
1016
+
1017
+ - 978ad95: fix(multiselect): placeholder do campo somente leitura passa 4,5:1
1018
+
1019
+ Sobre o fundo de somente leitura o placeholder dava 4,20:1 no 1doc (e
1020
+ 4,21–4,31:1 nos temas claros de cor). Agora usa `neutral-dark-down`: 6,78:1 no
1021
+ 1doc, 10,83:1 no 1doc-dark e 16,48:1 no alto contraste.
1022
+
1023
+ - 31d3005: fix(a11y): Select, MultiSelect e SegmentedControl com nome acessível no HTML do servidor
1024
+
1025
+ O id automático desses componentes só nasce no `onMount`, e o nome acessível
1026
+ vinha de `aria-labelledby` apontando para ele: no HTML do servidor, e até a
1027
+ hidratação, o combobox (e os radios do SegmentedControl) ficavam sem nome
1028
+ (axe `aria-input-field-name`). Enquanto não há id, o nome sai do texto do
1029
+ label via `aria-label`; depois do mount volta ao `aria-labelledby`. Servidor e
1030
+ primeira renderização do cliente continuam idênticos. Sem mudança visual.
1031
+
1032
+ - 7f58f04: fix(phoneinput): placeholder do campo somente leitura passa 4,5:1
1033
+
1034
+ Sobre o fundo de somente leitura o placeholder dava 4,20:1 no 1doc (e
1035
+ 4,21–4,31:1 nos temas claros de cor). Agora usa `neutral-dark-down`: 6,78:1 no
1036
+ 1doc, 10,83:1 no 1doc-dark e 16,48:1 no alto contraste.
1037
+
1038
+ - 98e9bf0: fix(select): placeholder do campo somente leitura passa 4,5:1
1039
+
1040
+ Sobre o fundo de somente leitura o placeholder dava 4,20:1 no 1doc (e
1041
+ 4,21–4,31:1 nos temas claros de cor). Agora usa `neutral-dark-down`: 6,78:1 no
1042
+ 1doc, 10,83:1 no 1doc-dark e 16,48:1 no alto contraste.
1043
+
1044
+ - c33298c: fix(stack,box): raiz única no Vue, repassa ouvintes e atributos
1045
+
1046
+ No Vue, `Stack` e `Box` saíam com raiz em FRAGMENTO: o Mitosis gera um
1047
+ `<template v-if="elementTag === ...">` por tag, e o Vue não repassa atributo nem
1048
+ ouvinte a um componente de raiz múltipla. Só sobrevivia uma lista fixa
1049
+ (`data-*`, `aria-*`, `style`, `class`, `title`, `role`, `tabIndex`). No 2.8.0
1050
+ publicado a raiz era um `<div>` único e o Vue repassava tudo, então foi uma
1051
+ regressão silenciosa das props novas (`as`, `gap="none"`...).
1052
+
1053
+ Descartados em silêncio, antes desta correção:
1054
+
1055
+ - ouvintes: `@click`, `@keydown`, `@dragstart`, `@drop`, `@paste`, `@mousedown`...
1056
+ - atributos fora da lista: `tabindex` (minúsculo), `draggable`...
1057
+ - `v-show` e o `$el` do `ref` do componente (apontavam para o nó de âncora do
1058
+ fragmento, não para o elemento).
1059
+
1060
+ Agora o template gerado é um `<component :is="elementTag">` só (ligado no
1061
+ `postbuild.js`, como o do `DataTable`), e o fallthrough do Vue leva ao elemento
1062
+ tudo o que o consumidor passa. Continuam como estavam: `as` com as 10 tags,
1063
+ `role="list"` em `ul`/`ol` (o `role` do consumidor vence), `onSubmit` do
1064
+ `as="form"`, `id`, `style` e `className`. O React não muda.
1065
+
1066
+ Novo teste do pacote Vue, `stack-box-raiz-unica.test.mjs`, que monta o
1067
+ componente num DOM (jsdom) e dispara os eventos. O helper `dom.mjs` serve para
1068
+ qualquer teste de comportamento no Vue; não adiciona dependência (usa o jsdom do
1069
+ pacote React e o `vue/compiler-sfc`).
1070
+
1071
+ Outros componentes do 1DS com raiz em fragmento têm o mesmo limite (ex.: `List`,
1072
+ quando troca entre vazio e `ul`/`ol`); este changeset trata só `Stack` e `Box`.
1073
+
1074
+ - 81cb08e: fix(textarea): placeholder do campo somente leitura passa 4,5:1
1075
+
1076
+ Sobre o fundo de somente leitura o placeholder dava 4,20:1 no 1doc (e
1077
+ 4,21–4,31:1 nos temas claros de cor). Agora usa `neutral-dark-down`: 6,78:1 no
1078
+ 1doc, 10,83:1 no 1doc-dark e 16,48:1 no alto contraste.
1079
+
1080
+ - f7645bf: fix(timepicker): placeholder do campo somente leitura passa 4,5:1
1081
+
1082
+ Sobre o fundo de somente leitura o placeholder dava 4,20:1 no 1doc (e
1083
+ 4,21–4,31:1 nos temas claros de cor). Agora usa `neutral-dark-down`: 6,78:1 no
1084
+ 1doc, 10,83:1 no 1doc-dark e 16,48:1 no alto contraste.
1085
+
1086
+ - 0fc7a82: fix(vue): `Text`, `Grid` e `Logo` repassam `title`, `style` e `aria-*`; `Button` e `DataTable` param de sujar o DOM
1087
+
1088
+ Quatro defeitos que só existiam no Vue gerado (o React estava certo):
1089
+
1090
+ - `Text`, `Grid` e `Logo` descartavam `title`, `style`, `aria-*` e `data-*`. O
1091
+ laço `for (k in props)` do `htmlAttrs` compilava para `props.props`, que não
1092
+ existe. O passo `postbuild` do core passa a ler `props` e `useAttrs()` (o que
1093
+ não está declarado na interface chega por `attrs`, não por `props`). Nos
1094
+ `.lite.tsx` de `Text` e `Grid` o getter `style` virou `estiloInline`: o Mitosis
1095
+ trocava toda ocorrência da palavra por `style.value` e o estilo do
1096
+ consumidor deixava de passar.
1097
+ - `DataTable` escrevia a classe `umds-datatable__row--selected.value`. O getter
1098
+ `selected` colidia com a palavra dentro da string; virou `selectedIndexes`.
1099
+ - `Button` escrevia `autofocus="false"`. `autoFocus` só vai ao DOM quando
1100
+ verdadeiro.
1101
+ - Tipos do Vue: `setTheme`, `getTheme`, `initTheme`, `getAvailableThemes` e
1102
+ `onThemeChange` estavam tipados com `'light' | 'dark' | 'system'`. Agora
1103
+ `Theme` e `ThemeName` são lidos de `core/src/utils/theme.ts` (`'1doc'`,
1104
+ `'1doc-dark'`, `'1doc-high-contrast'`...), e `registerTheme` foi declarado.
1105
+
1106
+ Testes: `pnpm --filter @1doc/1ds-vue test` (novo, `node:test` com SSR, sem
1107
+ dependência nova) e `AtributosRepassados.test.tsx` no React.
1108
+
1109
+ ## 2.8.0
1110
+
1111
+ ### Minor Changes
1112
+
1113
+ - 450dfb6: feat(core): rótulos traduzíveis em 22 componentes
1114
+
1115
+ Todo texto em português que estava fixo no código — visível ou lido pelo
1116
+ leitor de tela — ganhou prop. Sem a prop, nada muda: o padrão é o português de
1117
+ antes, byte a byte. Com ela, um produto em outro idioma deixa de mostrar ou ler
1118
+ português.
1119
+
1120
+ - `AILabel`: `sourcesLabel`, `notIncludedLabel`.
1121
+ - `AIContent`: `label`, `ariaLabel`, `explanationTitle`, `sourcesLabel`,
1122
+ `notIncludedLabel` (repassados ao selo interno, que antes não recebia nenhum).
1123
+ - `AppSidebar`: `expandLabel`, `collapseLabel`.
1124
+ - `AttachmentCard`: `statusContextLabel`, `requiredLabel`, `copyLabel`,
1125
+ `copiedLabel`, `copyErrorLabel`.
1126
+ - `AvatarGroup`: `overflowAriaLabel`, `overflowTitle`.
1127
+ - `BottomSheet`: `grabberLabel`.
1128
+ - `BarChart` e `LineChart`: `categoryLabel`, `valuesListLabel`, `typeLabel`.
1129
+ - `Chips`: `removeAriaLabel`.
1130
+ - `ConfirmDialog`: `loadingLabel`.
1131
+ - `ConfirmAIAction`: `irreversibleLabel`, `typePhraseLabel`, `phraseMatchedLabel`,
1132
+ `phrasePendingLabel`, `loadingLabel`. O `impactLabel` agora também troca o
1133
+ título visível do bloco (antes só o nome acessível da lista).
1134
+ - `DataTable`: `selectAllLabel`, `selectRowLabel`.
1135
+ - `DatePicker`: `dialogLabel`, `dayLabel`.
1136
+ - `FileInput`: `selectFileLabel`, `triggerLabel`, `triggerHint`, `maxSizeLabel`,
1137
+ `dropLabel`, `orLabel`, `browseLabel`, `removeAriaLabel`, `uploadingAriaLabel`.
1138
+ - `Input`: `showPasswordLabel`, `hidePasswordLabel`.
1139
+ - `Kanban`: `announcements` (objeto com as frases do `aria-live`),
1140
+ `assigneeLabel`, `tagsLabel`, `cardRoleDescription`, `columnCountLabel`.
1141
+ - `KanbanCard`: `assigneeLabel`. `KanbanColumn`: `countLabel`.
1142
+ - `Pagination`: `ofLabel`, `itemRangeLabel`, `pageLabel`.
1143
+ - `PhoneInput`: `countryNames`, `copyLabel`, `copyTitle`, `copiedLabel`.
1144
+ - `Stepper`: `completedLabel`, `activeLabel`, `errorLabel`, `pendingLabel`.
1145
+ - `TimePicker`: `hourUnitLabel`, `minuteUnitLabel`, `secondUnitLabel`.
1146
+
1147
+ Texto com variável segue o que o DS já fazia: prefixo em string quando o texto
1148
+ é "verbo + nome" (como o `removeAriaLabel` do `MultiSelect`), função quando há
1149
+ número ou a ordem das palavras muda de idioma para idioma (como o
1150
+ `positionLabel` do `Podium`).
1151
+
1152
+ ### Patch Changes
1153
+
1154
+ - 5f84c72: fix(alert): só `negative` interrompe o leitor de tela
1155
+
1156
+ O Alert usava `role="alert"` (assertivo) em toda variante, e um aviso
1157
+ informativo ou de sucesso cortava o que o leitor de tela estava lendo. Agora
1158
+ `negative` segue com `role="alert"` + `aria-live="assertive"`, e `positive`,
1159
+ `info` e `neutral` passam a `role="status"` + `aria-live="polite"` — a mesma
1160
+ regra do Toast. Sem mudança visual e sem mudança de API.
1161
+
1162
+ - 60a225c: fix(app-header): itens de navegação que não cabem vão para o menu "Mais" em vez de serem recortados. O último item cortado ficava com ~13px de alvo clicável (WCAG 2.5.8). O botão usa o `Dropdown` do DS (`aria-haspopup`, `aria-expanded`, setas, Esc devolve o foco), o item ativo continua na barra sempre que couber, e o rótulo é configurável por `moreLabel` (padrão "Mais"). A medição roda só no navegador, depois de montar (ResizeObserver + MutationObserver).
1163
+ - 1dd44c4: fix(app-nav-item): o item de navegação do cabeçalho ganha área clicável mínima de 24×24px (WCAG 2.5.8) sem padding nem fundo — só a caixa do botão cresce, centralizada.
1164
+ - ffd6692: fix(app-shell): a região de conteúdo (`<main>`) passa a receber foco por teclado (`tabindex="0"`) para rolar pelas setas, com nome acessível configurável na prop nova `contentLabel` (padrão "Conteúdo principal") e foco visível canônico. Resolve o `scrollable-region-focusable` do axe (WCAG 2.1.1).
1165
+ - 35e9f76: fix(attachment-card): no Vue, abrir o painel de conferência por clique ou teclado agora leva o foco para dentro dele, como no React. O foco esperava um `onUpdate` do cartão que o Vue não dispara (quem re-renderiza é o Portal), e passou a ser feito também um quadro depois do painel se posicionar.
1166
+ - 2e610fa: fix(badge): o ícone do Badge não depende mais da ordem de carga do CSS — a regra do SVG ganhou especificidade (`.umds-badge .umds-badge__icon svg`) e deixa de perder para `.umds-icon svg` quando o CSS do Icon chega depois (voltava a 12px, deslocado).
1167
+ - b17859f: fix(bottomsheet): painel nunca sai sem nome acessível
1168
+
1169
+ BottomSheet sem `title`, `ariaLabel` e `ariaLabelledby` saía com
1170
+ `role="dialog"` anônimo. Agora cai no genérico "Painel", como o Drawer, e as
1171
+ props `ariaLabel`/`ariaLabelledby` ganham JSDoc. Sem mudança visual nem de API.
1172
+
1173
+ - 75dde22: fix(confirm-dialog): prop `confirmDisabled`; ConfirmAIAction usa em risco alto
1174
+
1175
+ `ConfirmDialog` ganha `confirmDisabled?: boolean`, que desabilita o botão de
1176
+ confirmar sem o estado de carregamento do `confirmLoading`. O
1177
+ `ConfirmAIAction` passa a usá-la: em risco alto o botão fica desabilitado até
1178
+ a frase digitada conferir (antes continuava clicável e só o handler
1179
+ bloqueava). A mensagem `aria-live` passa a dizer que o botão foi liberado.
1180
+
1181
+ - 3a124aa: fix(core): o CSS do próprio core passa no `@1doc/1ds-lint`
1182
+
1183
+ Raio e espaço fora da escala viraram token: raio 6px/5px/4px → 8px canônico
1184
+ (AppHeader, SidePanel, SidePanelItem, SidePanelSearch, SidePanelSection), 100px
1185
+ e 12px de contador → pill, 2px → `border-radius-xxs`/`spacing-micro`; espaços
1186
+ 20/18/14/10/9/6/3px → degrau mais próximo da escala (AppHeader, AppNavItem,
1187
+ Modal base, SidePanel e filhos). Há mudança de poucos pixels nesses componentes.
1188
+ Onde não existe token equivalente (overlays `rgba`, escurecimento com `black`,
1189
+ raio 3px da caixa do Checkbox, compensações de -5px/-3px/1.5px), o literal
1190
+ continua com `stylelint-disable-next-line` justificado.
1191
+
1192
+ - 4d50df8: fix(dropdown): teclado do menu igual no React e no Vue
1193
+
1194
+ No React, as setas levavam o foco para o item que estava ativo antes da tecla,
1195
+ e o End marcava o penúltimo item. A navegação lia o índice ativo logo depois de
1196
+ escrevê-lo: no Vue o valor muda na hora, no React gerado a leitura vinha do
1197
+ render anterior. Agora o próximo índice é calculado por uma função pura e o foco
1198
+ vai para o índice calculado, lido do item focado no DOM. Nos dois frameworks:
1199
+ ArrowDown/ArrowUp movem (com volta nas pontas e pulando item desabilitado),
1200
+ Home/End vão ao primeiro/último, Enter/Espaço ativam, Esc fecha e devolve o foco
1201
+ ao gatilho. Sem mudança visual e sem mudança de API.
1202
+
1203
+ - 11935a0: fix(field): borda do campo em repouso passa o WCAG 1.4.11
1204
+
1205
+ `--umds-semantic-field-border-default` deixa `neutral-light-down` (#D5D5D5,
1206
+ 1,47:1 sobre branco) e passa a `neutral-dark-medium` (#7D7D7D no tema claro,
1207
+ 4,12:1). Passa 3:1 nos 13 temas, sobre `background-white` e `background-light`.
1208
+ Input, Select, MultiSelect, Textarea, Combobox, FileInput e o somente-leitura
1209
+ de PhoneInput passam a ler o token (antes escreviam o primitivo semântico
1210
+ direto); DatePicker, TimePicker e PhoneInput já liam. Desabilitado continua em
1211
+ `neutral-light-down`. Mudança visual: a borda de todo campo fica mais escura.
1212
+
1213
+ - fc3a622: fix(file-input): o texto de ajuda (`helperText`) e o subtítulo do card do `FileInput` passam de `neutral-dark-medium` (#7D7D7D, 4,11:1) para `neutral-dark-down` (#565656, 7,34:1) — a mesma cor do texto de ajuda do `Input` — e atingem o contraste mínimo do WCAG 1.4.3.
1214
+ - 6754524: fix(modal): prop `ariaLabel` para modal sem título
1215
+
1216
+ Modal sem `title` saía com `role="dialog"` anônimo. Nova prop `ariaLabel`
1217
+ nomeia o diálogo quando não há título (`aria-label`); com título, segue o
1218
+ `aria-labelledby` apontando para ele e `ariaLabel` é ignorado. Sem nenhum dos
1219
+ dois, o diálogo cai no genérico "Diálogo" em vez de sair sem nome (axe
1220
+ aria-dialog-name), como o Drawer já faz com "Painel". Sem mudança visual.
1221
+
1222
+ - 0d31b59: fix(modal): a descrição do Modal base passa de `neutral-dark-medium` (#7D7D7D, 4,11:1) para `neutral-dark-down` (#565656, 7,34:1) e atinge o contraste mínimo do WCAG 1.4.3 em todos os temas.
1223
+ - e80374d: fix(multiselect): mensagem de erro e texto de apoio ligados ao campo
1224
+
1225
+ O foco do MultiSelect cai no trigger `role="combobox"`, e nada ligava a ele a
1226
+ mensagem de erro nem o `helperText`/`description`: o leitor de tela anunciava
1227
+ o campo e nunca o motivo do erro. Agora o combobox recebe `aria-describedby`
1228
+ (erro primeiro, apoio depois, como no Input) e `aria-invalid` quando há
1229
+ `invalid` ou `errorMessage`.
1230
+
1231
+ Os ids automáticos deixam de ser sorteados na inicialização do componente,
1232
+ o que fazia servidor e cliente gerarem ids diferentes e quebrava a hidratação
1233
+ SSR. O id automático nasce no `onMount`; quem precisa dos ids já no HTML do
1234
+ servidor passa a prop `id`, da qual todos derivam.
1235
+
1236
+ - c8d9356: fix(segmented-control): id estável entre servidor e cliente
1237
+
1238
+ O id automático era sorteado na inicialização do componente, então servidor
1239
+ e cliente geravam ids diferentes: a hidratação SSR divergia e o `for` dos
1240
+ rótulos, o `name` dos radios e o `aria-labelledby` do grupo saíam trocados.
1241
+ Nova prop `id`, da qual todos os ids internos derivam (e o `name`, quando não
1242
+ informado). Sem ela, o id automático nasce no `onMount`, só no navegador.
1243
+
1244
+ - b2da66f: fix(select): o gatilho do `Select` desabilitado passa a expor `aria-disabled="true"` — leitor de tela anuncia o estado, como já acontecia no `MultiSelect`.
1245
+ - 13c288c: fix(select): mensagem de erro e texto de apoio ligados ao campo
1246
+
1247
+ O foco do Select cai no trigger `role="combobox"`, e nada ligava a ele a
1248
+ mensagem de erro nem o `helperText`/`description`: o leitor de tela anunciava
1249
+ o campo e nunca o motivo do erro. Agora o combobox recebe `aria-describedby`
1250
+ (erro primeiro, apoio depois, como no Input) e `aria-invalid` também quando há
1251
+ `errorMessage`, não só com `invalid`.
1252
+
1253
+ Os ids automáticos deixam de ser sorteados na inicialização do componente,
1254
+ o que fazia servidor e cliente gerarem ids diferentes e quebrava a hidratação
1255
+ SSR. O id automático nasce no `onMount`; quem precisa dos ids já no HTML do
1256
+ servidor passa a prop `id`, da qual todos derivam.
1257
+
1258
+ - 954b332: fix(side-panel): o contador do `SidePanelItem` e o rótulo do `SidePanelSection` passam de `neutral-dark-medium` (#7D7D7D, 4,11:1) para `neutral-dark-down` (#565656, 7,34:1) e atingem o contraste mínimo do WCAG 1.4.3 em todos os temas.
1259
+ - e8cd29b: fix(stepper): o número da etapa pendente passa da cor de desabilitado (`neutral-dark-up`, #A3A3A3, 2,5:1) para `neutral-dark-down` (#565656, 7,34:1), a mesma do título pendente, e atinge o contraste mínimo do WCAG 1.4.3.
1260
+ - b622c03: docs(text): o JSDoc da prop `color` do `Text` passa a dizer que `color="disabled"` (#A3A3A3, 2,5:1) é só para texto de controle desabilitado — em qualquer outro texto reprova o WCAG 1.4.3; o indicado é `secondary`.
1261
+ - f04dc5a: fix(tooltip): texto anunciado pelo leitor de tela no elemento focável
1262
+
1263
+ O `aria-describedby` ficava no `<span>` que embrulha o gatilho, que nunca
1264
+ recebe foco: o texto do tooltip não era lido. Agora o Tooltip escreve o
1265
+ `aria-describedby` no filho focável (o botão, o link, o campo), somando ao
1266
+ que ele já tinha, e aponta para uma cópia do texto que fica sempre no DOM,
1267
+ visualmente escondida — a bolha só monta depois do foco, tarde demais para o
1268
+ leitor de tela.
1269
+
1270
+ O foco passa a ser escutado com `focusin`/`focusout` nativos: no Vue, o
1271
+ `@focus` no span não disparava quando o foco caía no filho, e o tooltip não
1272
+ abria pelo teclado. Esc continua fechando. Os ids automáticos nascem no
1273
+ `onMount`, sem divergência de hidratação SSR.
1274
+
1275
+ - 2b881aa: fix(tooltip): Esc com o tooltip aberto não fecha o Modal em volta
1276
+
1277
+ Um tooltip aberto dentro de Modal, Drawer ou BottomSheet fechava a dica e o
1278
+ overlay no mesmo Esc. Agora o Esc que fecha o tooltip é consumido
1279
+ (`stopPropagation`, escutando no `window` em captura, antes do `document` onde
1280
+ os overlays escutam). Com o tooltip fechado, o Esc segue normal para o overlay.
1281
+ Sem mudança visual e sem mudança de API.
1282
+
3
1283
  ## 2.7.2
4
1284
 
5
1285
  ### Patch Changes