@opencode-ai/ui 0.0.0-dev-202609070401 → 0.0.0-dev-19227

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 (299) hide show
  1. package/dist/actions/button/button.d.ts +10 -0
  2. package/dist/actions/icon-button/icon-button.d.ts +11 -0
  3. package/dist/actions/split-button/split-button.d.ts +5 -0
  4. package/dist/components/card.d.ts +1 -1
  5. package/dist/components/list.d.ts +1 -1
  6. package/dist/components/scroll-view.d.ts +14 -4
  7. package/dist/context/i18n.d.ts +10 -7
  8. package/dist/context/marked-base.d.ts +3 -0
  9. package/dist/context/marked-parser.d.ts +1 -2
  10. package/dist/{components → data-display/accordion}/accordion.d.ts +6 -6
  11. package/dist/{v2/components/avatar-v2.d.ts → data-display/avatar/avatar.d.ts} +1 -1
  12. package/dist/data-display/badge/badge.d.ts +7 -0
  13. package/dist/{components → data-display/diff-changes}/diff-changes.d.ts +2 -1
  14. package/dist/data-display/keybind/keybind.d.ts +7 -0
  15. package/dist/{v2/components/line-comment-v2.d.ts → data-display/line-comment/line-comment.d.ts} +9 -9
  16. package/dist/{v2/components/project-avatar-v2.d.ts → data-display/project-avatar/project-avatar.d.ts} +1 -1
  17. package/dist/feedback/loader/loader.d.ts +3 -0
  18. package/dist/{components → feedback/progress-circle}/progress-circle.d.ts +2 -0
  19. package/dist/feedback/toast/toast.d.ts +57 -0
  20. package/dist/{components → forms/checkbox}/checkbox.d.ts +2 -2
  21. package/dist/{v2/components/field-v2.d.ts → forms/field/field.d.ts} +4 -10
  22. package/dist/forms/radio/radio.d.ts +16 -0
  23. package/dist/{v2/components/select-v2.d.ts → forms/select/select.d.ts} +5 -6
  24. package/dist/{components → forms/switch}/switch.d.ts +4 -2
  25. package/dist/{v2/components/text-input-v2.d.ts → forms/text-input/text-input.d.ts} +3 -3
  26. package/dist/forms/textarea/textarea.d.ts +7 -0
  27. package/dist/hooks/use-filtered-list.d.ts +9 -0
  28. package/dist/i18n/ar.d.ts +0 -2
  29. package/dist/i18n/bg.d.ts +0 -2
  30. package/dist/i18n/br.d.ts +0 -2
  31. package/dist/i18n/bs.d.ts +0 -2
  32. package/dist/i18n/da.d.ts +0 -2
  33. package/dist/i18n/de.d.ts +0 -2
  34. package/dist/i18n/en.d.ts +242 -1
  35. package/dist/i18n/es.d.ts +0 -2
  36. package/dist/i18n/fr.d.ts +0 -2
  37. package/dist/i18n/he.d.ts +197 -0
  38. package/dist/i18n/ja.d.ts +0 -2
  39. package/dist/i18n/km.d.ts +0 -2
  40. package/dist/i18n/ko.d.ts +0 -2
  41. package/dist/i18n/lo.d.ts +0 -2
  42. package/dist/i18n/mk.d.ts +0 -2
  43. package/dist/i18n/mn.d.ts +0 -2
  44. package/dist/i18n/my.d.ts +0 -2
  45. package/dist/i18n/pl.d.ts +0 -2
  46. package/dist/i18n/ru.d.ts +0 -2
  47. package/dist/i18n/sr.d.ts +0 -2
  48. package/dist/i18n/tg.d.ts +0 -2
  49. package/dist/i18n/th.d.ts +0 -2
  50. package/dist/i18n/tr.d.ts +0 -2
  51. package/dist/i18n/zh.d.ts +0 -2
  52. package/dist/i18n/zht.d.ts +0 -2
  53. package/dist/{components/icon.d.ts → icons/icon/additional-icons.d.ts} +8 -8
  54. package/dist/{v2/components → icons/icon}/icon.d.ts +52 -1
  55. package/dist/layout/divider/divider.d.ts +5 -0
  56. package/dist/navigation/menu/menu.d.ts +59 -0
  57. package/dist/{v2/components/segmented-control-v2.d.ts → navigation/segmented-control/segmented-control.d.ts} +5 -5
  58. package/dist/{components → navigation/tabs}/tabs.d.ts +15 -8
  59. package/dist/{v2/components/dialog-v2.d.ts → overlays/dialog/dialog.d.ts} +1 -2
  60. package/dist/overlays/tooltip/tooltip.d.ts +15 -0
  61. package/dist/{components → typography/text-shimmer}/text-shimmer.d.ts +1 -0
  62. package/dist/typography/wordmark/wordmark.d.ts +5 -0
  63. package/package.json +141 -35
  64. package/src/{v2/components/button-v2.css → actions/button/button.css} +30 -0
  65. package/src/{components → actions/button}/button.tsx +19 -11
  66. package/src/{v2/components/icon-button-v2.css → actions/icon-button/icon-button.css} +27 -9
  67. package/src/actions/icon-button/icon-button.tsx +32 -0
  68. package/src/{v2/components/split-button-v2.css → actions/split-button/split-button.css} +2 -6
  69. package/src/{v2/components/split-button-v2.tsx → actions/split-button/split-button.tsx} +4 -4
  70. package/src/components/animated-number.css +29 -11
  71. package/src/components/animated-number.tsx +2 -2
  72. package/src/components/card.css +2 -23
  73. package/src/components/card.tsx +4 -4
  74. package/src/components/collapsible.tsx +2 -2
  75. package/src/components/dock-surface.css +2 -9
  76. package/src/components/image-preview.tsx +3 -2
  77. package/src/components/list.css +5 -5
  78. package/src/components/list.tsx +7 -5
  79. package/src/components/popover.tsx +3 -2
  80. package/src/components/scroll-view.css +36 -4
  81. package/src/components/scroll-view.tsx +153 -88
  82. package/src/components/sticky-accordion-header.tsx +1 -1
  83. package/src/components/text-field.tsx +12 -4
  84. package/src/context/dialog.tsx +1 -0
  85. package/src/context/i18n.tsx +17 -14
  86. package/src/context/marked-base.tsx +27 -0
  87. package/src/context/marked-parser.tsx +3 -13
  88. package/src/{components → data-display/accordion}/accordion.css +7 -33
  89. package/src/{components → data-display/accordion}/accordion.tsx +14 -14
  90. package/src/{v2/components/avatar-v2.tsx → data-display/avatar/avatar.tsx} +1 -1
  91. package/src/{v2/components/badge-v2.css → data-display/badge/badge.css} +19 -0
  92. package/src/{v2/components/badge-v2.tsx → data-display/badge/badge.tsx} +6 -4
  93. package/src/{components → data-display/diff-changes}/diff-changes.css +22 -19
  94. package/src/{v2/components/diff-changes-v2.tsx → data-display/diff-changes/diff-changes.tsx} +7 -2
  95. package/src/{v2/components/keybind-v2.css → data-display/keybind/keybind.css} +1 -1
  96. package/src/{v2/components/keybind-v2.tsx → data-display/keybind/keybind.tsx} +3 -3
  97. package/src/{v2/components/line-comment-v2.css → data-display/line-comment/line-comment.css} +4 -4
  98. package/src/{v2/components/line-comment-v2.tsx → data-display/line-comment/line-comment.tsx} +17 -15
  99. package/src/{v2/components/project-avatar-v2.css → data-display/project-avatar/project-avatar.css} +4 -4
  100. package/src/{v2/components/project-avatar-v2.tsx → data-display/project-avatar/project-avatar.tsx} +1 -1
  101. package/src/{v2/components/loader-v2.tsx → feedback/loader/loader.tsx} +2 -2
  102. package/src/feedback/progress-circle/progress-circle.css +28 -0
  103. package/src/feedback/progress-circle/progress-circle.tsx +64 -0
  104. package/src/{v2/components/toast-v2.tsx → feedback/toast/toast.tsx} +60 -58
  105. package/src/{components → forms/checkbox}/checkbox.css +1 -7
  106. package/src/{components → forms/checkbox}/checkbox.tsx +13 -13
  107. package/src/{v2/components/field-v2.css → forms/field/field.css} +1 -1
  108. package/src/{v2/components/field-v2.tsx → forms/field/field.tsx} +9 -11
  109. package/src/{v2/components/radio-v2.tsx → forms/radio/radio.tsx} +30 -20
  110. package/src/{v2/components/select-v2.css → forms/select/select.css} +2 -8
  111. package/src/{v2/components/select-v2.tsx → forms/select/select.tsx} +42 -32
  112. package/src/{v2/components/switch-v2.css → forms/switch/switch.css} +110 -0
  113. package/src/forms/switch/switch.tsx +34 -0
  114. package/src/{v2/components/text-input-v2.css → forms/text-input/text-input.css} +3 -3
  115. package/src/{v2/components/text-input-v2.tsx → forms/text-input/text-input.tsx} +4 -4
  116. package/src/{v2/components/textarea-v2.tsx → forms/textarea/textarea.tsx} +3 -3
  117. package/src/hooks/create-auto-scroll.tsx +20 -0
  118. package/src/i18n/am.ts +7 -9
  119. package/src/i18n/ar.ts +7 -9
  120. package/src/i18n/az.ts +7 -9
  121. package/src/i18n/bg.ts +7 -9
  122. package/src/i18n/bn.ts +7 -9
  123. package/src/i18n/br.ts +7 -9
  124. package/src/i18n/bs.ts +7 -9
  125. package/src/i18n/ca.ts +7 -9
  126. package/src/i18n/cs.ts +7 -9
  127. package/src/i18n/da.ts +7 -9
  128. package/src/i18n/de.ts +1 -3
  129. package/src/i18n/dv.ts +7 -9
  130. package/src/i18n/dz.ts +5 -7
  131. package/src/i18n/el.ts +7 -9
  132. package/src/i18n/en.ts +59 -12
  133. package/src/i18n/es.ts +6 -8
  134. package/src/i18n/et.ts +7 -9
  135. package/src/i18n/fa.ts +7 -9
  136. package/src/i18n/fi.ts +7 -9
  137. package/src/i18n/fo.ts +7 -9
  138. package/src/i18n/fr.ts +6 -8
  139. package/src/i18n/he.ts +199 -0
  140. package/src/i18n/hi.ts +7 -9
  141. package/src/i18n/hr.ts +7 -9
  142. package/src/i18n/hu.ts +7 -9
  143. package/src/i18n/hy.ts +7 -9
  144. package/src/i18n/id.ts +7 -9
  145. package/src/i18n/is.ts +7 -9
  146. package/src/i18n/it.ts +7 -9
  147. package/src/i18n/ja.ts +7 -9
  148. package/src/i18n/ka.ts +7 -9
  149. package/src/i18n/km.ts +7 -9
  150. package/src/i18n/ko.ts +7 -9
  151. package/src/i18n/lo.ts +7 -9
  152. package/src/i18n/lt.ts +7 -9
  153. package/src/i18n/lv.ts +7 -9
  154. package/src/i18n/mk.ts +7 -9
  155. package/src/i18n/mn.ts +7 -9
  156. package/src/i18n/ms.ts +7 -9
  157. package/src/i18n/my.ts +7 -9
  158. package/src/i18n/ne.ts +7 -9
  159. package/src/i18n/nl.ts +7 -9
  160. package/src/i18n/no.ts +7 -9
  161. package/src/i18n/pa.ts +7 -9
  162. package/src/i18n/pl.ts +7 -9
  163. package/src/i18n/ro.ts +7 -9
  164. package/src/i18n/ru.ts +7 -9
  165. package/src/i18n/si.ts +7 -9
  166. package/src/i18n/sk.ts +7 -9
  167. package/src/i18n/sl.ts +7 -9
  168. package/src/i18n/sq.ts +7 -9
  169. package/src/i18n/sr.ts +7 -9
  170. package/src/i18n/sv.ts +7 -9
  171. package/src/i18n/tg.ts +7 -9
  172. package/src/i18n/th.ts +7 -9
  173. package/src/i18n/tk.ts +7 -9
  174. package/src/i18n/tr.ts +7 -9
  175. package/src/i18n/uk.ts +7 -9
  176. package/src/i18n/ur.ts +7 -9
  177. package/src/i18n/uz.ts +7 -9
  178. package/src/i18n/vi.ts +7 -9
  179. package/src/i18n/zh.ts +7 -9
  180. package/src/i18n/zht.ts +7 -9
  181. package/src/{components/icon.tsx → icons/icon/additional-icons.ts} +8 -74
  182. package/src/icons/icon/icon.css +3 -0
  183. package/src/{v2/components → icons/icon}/icon.tsx +88 -12
  184. package/src/{v2/components/divider-v2.tsx → layout/divider/divider.tsx} +3 -3
  185. package/src/{v2/components/menu-v2.css → navigation/menu/menu.css} +124 -2
  186. package/src/{v2/components/menu-v2.tsx → navigation/menu/menu.tsx} +96 -32
  187. package/src/{v2/components/segmented-control-v2.css → navigation/segmented-control/segmented-control.css} +1 -1
  188. package/src/{v2/components/segmented-control-v2.tsx → navigation/segmented-control/segmented-control.tsx} +9 -8
  189. package/src/{v2/components/tabs-v2.css → navigation/tabs/tabs-current.css} +25 -10
  190. package/src/{components → navigation/tabs}/tabs.css +53 -232
  191. package/src/navigation/tabs/tabs.tsx +194 -0
  192. package/src/{v2/components/dialog-v2.css → overlays/dialog/dialog.css} +3 -0
  193. package/src/{v2/components/dialog-v2.tsx → overlays/dialog/dialog.tsx} +11 -13
  194. package/src/{v2/components/tooltip-v2.css → overlays/tooltip/tooltip.css} +33 -0
  195. package/src/{v2/components/tooltip-v2.tsx → overlays/tooltip/tooltip.tsx} +24 -17
  196. package/src/styles/base.css +5 -0
  197. package/src/{v2/components/file-tree-v2.css → styles/file-tree.css} +64 -3
  198. package/src/styles/index.css +4 -20
  199. package/src/styles/tailwind/colors.css +2 -0
  200. package/src/styles/tailwind/index.css +18 -1
  201. package/src/styles/theme.css +2 -2
  202. package/src/{v2/styles → styles/tokens}/colors.css +8 -8
  203. package/src/{v2/styles → styles/tokens}/theme.css +23 -16
  204. package/src/theme/context.tsx +19 -11
  205. package/src/theme/themes/oc-2.json +50 -19
  206. package/src/theme/v2/default-primitives.ts +8 -8
  207. package/src/theme/v2/foreground.ts +1 -0
  208. package/src/theme/v2/mapping.ts +7 -1
  209. package/src/{components → typography/text-shimmer}/text-shimmer.css +2 -1
  210. package/src/{components → typography/text-shimmer}/text-shimmer.tsx +1 -0
  211. package/src/typography/wordmark/wordmark.tsx +39 -0
  212. package/dist/components/avatar.d.ts +0 -9
  213. package/dist/components/button.d.ts +0 -9
  214. package/dist/components/dialog.d.ts +0 -12
  215. package/dist/components/dropdown-menu.d.ts +0 -80
  216. package/dist/components/icon-button.d.ts +0 -10
  217. package/dist/components/keybind.d.ts +0 -6
  218. package/dist/components/radio-group.d.ts +0 -16
  219. package/dist/components/select.d.ts +0 -21
  220. package/dist/components/tag.d.ts +0 -5
  221. package/dist/components/toast.d.ts +0 -56
  222. package/dist/components/tooltip.d.ts +0 -17
  223. package/dist/v2/components/accordion-v2.d.ts +0 -26
  224. package/dist/v2/components/badge-v2.d.ts +0 -6
  225. package/dist/v2/components/button-v2.d.ts +0 -10
  226. package/dist/v2/components/checkbox-v2.d.ts +0 -10
  227. package/dist/v2/components/diff-changes-v2.d.ts +0 -11
  228. package/dist/v2/components/divider-v2.d.ts +0 -5
  229. package/dist/v2/components/icon-button-v2.d.ts +0 -11
  230. package/dist/v2/components/inline-input-v2.d.ts +0 -21
  231. package/dist/v2/components/keybind-v2.d.ts +0 -7
  232. package/dist/v2/components/loader-v2.d.ts +0 -3
  233. package/dist/v2/components/menu-v2.d.ts +0 -52
  234. package/dist/v2/components/progress-circle-v2.d.ts +0 -8
  235. package/dist/v2/components/radio-v2.d.ts +0 -16
  236. package/dist/v2/components/split-button-v2.d.ts +0 -5
  237. package/dist/v2/components/switch-v2.d.ts +0 -7
  238. package/dist/v2/components/tabs-v2.d.ts +0 -34
  239. package/dist/v2/components/text-shimmer-v2.d.ts +0 -9
  240. package/dist/v2/components/textarea-v2.d.ts +0 -7
  241. package/dist/v2/components/toast-v2.d.ts +0 -57
  242. package/dist/v2/components/tooltip-v2.d.ts +0 -13
  243. package/dist/v2/components/wordmark-v2.d.ts +0 -2
  244. package/src/components/avatar.css +0 -49
  245. package/src/components/avatar.tsx +0 -55
  246. package/src/components/button.css +0 -194
  247. package/src/components/dialog.css +0 -181
  248. package/src/components/dialog.tsx +0 -72
  249. package/src/components/diff-changes.tsx +0 -115
  250. package/src/components/dropdown-menu.css +0 -135
  251. package/src/components/dropdown-menu.tsx +0 -308
  252. package/src/components/icon-button.css +0 -181
  253. package/src/components/icon-button.tsx +0 -29
  254. package/src/components/icon.css +0 -39
  255. package/src/components/keybind.css +0 -18
  256. package/src/components/keybind.tsx +0 -20
  257. package/src/components/progress-circle.css +0 -16
  258. package/src/components/progress-circle.tsx +0 -64
  259. package/src/components/radio-group.css +0 -187
  260. package/src/components/radio-group.tsx +0 -83
  261. package/src/components/select.css +0 -201
  262. package/src/components/select.tsx +0 -174
  263. package/src/components/switch.css +0 -136
  264. package/src/components/switch.tsx +0 -29
  265. package/src/components/tabs.tsx +0 -126
  266. package/src/components/tag.css +0 -37
  267. package/src/components/tag.tsx +0 -22
  268. package/src/components/toast.css +0 -236
  269. package/src/components/toast.tsx +0 -185
  270. package/src/components/tooltip.css +0 -74
  271. package/src/components/tooltip.tsx +0 -163
  272. package/src/v2/components/accordion-v2.css +0 -139
  273. package/src/v2/components/accordion-v2.tsx +0 -86
  274. package/src/v2/components/button-v2.tsx +0 -35
  275. package/src/v2/components/checkbox-v2.css +0 -184
  276. package/src/v2/components/checkbox-v2.tsx +0 -65
  277. package/src/v2/components/diff-changes-v2.css +0 -26
  278. package/src/v2/components/icon-button-v2.tsx +0 -37
  279. package/src/v2/components/inline-input-v2.css +0 -225
  280. package/src/v2/components/inline-input-v2.tsx +0 -107
  281. package/src/v2/components/progress-circle-v2.css +0 -13
  282. package/src/v2/components/progress-circle-v2.tsx +0 -52
  283. package/src/v2/components/switch-v2.tsx +0 -28
  284. package/src/v2/components/tabs-v2.tsx +0 -149
  285. package/src/v2/components/text-shimmer-v2.css +0 -125
  286. package/src/v2/components/text-shimmer-v2.tsx +0 -63
  287. package/src/v2/components/wordmark-v2.tsx +0 -71
  288. /package/dist/{components → forms/inline-input}/inline-input.d.ts +0 -0
  289. /package/dist/{v2/components → navigation}/tab-state-indicator.d.ts +0 -0
  290. /package/src/{v2/components/avatar-v2.css → data-display/avatar/avatar.css} +0 -0
  291. /package/src/{v2/components/loader-v2.css → feedback/loader/loader.css} +0 -0
  292. /package/src/{v2/components/toast-v2.css → feedback/toast/toast.css} +0 -0
  293. /package/src/{components → forms/inline-input}/inline-input.css +0 -0
  294. /package/src/{components → forms/inline-input}/inline-input.tsx +0 -0
  295. /package/src/{v2/components/radio-v2.css → forms/radio/radio.css} +0 -0
  296. /package/src/{v2/components/textarea-v2.css → forms/textarea/textarea.css} +0 -0
  297. /package/src/{v2/components/divider-v2.css → layout/divider/divider.css} +0 -0
  298. /package/src/{v2/components → navigation}/tab-state-indicator.tsx +0 -0
  299. /package/src/{v2/styles/tailwind.css → styles/tokens/index.css} +0 -0
@@ -1,9 +1,16 @@
1
1
  import { onMount, type ComponentProps, splitProps } from "solid-js"
2
+ import { additionalIcons, additionalIconViewBox } from "./additional-icons"
3
+ import "./icon.css"
2
4
 
5
+ // Consumers center the SVG viewport, so each icon must center its artwork within its viewBox.
3
6
  const icons = {
7
+ flask: {
8
+ viewBox: "0 0 16 16",
9
+ body: `<path d="M5.5 2H10.5M6 2V6L2.5 12C2 13 2.5 14 3.5 14H12.5C13.5 14 14 13 13.5 12L10 6V2M4.25 9H11.75" stroke="currentColor" stroke-linecap="square" stroke-linejoin="round"/>`,
10
+ },
4
11
  edit: {
5
12
  viewBox: "0 0 16 16",
6
- body: `<path d="M13.5555 8.21534V13.5556H2.44434L2.44434 2.4445H7.78462M6.88878 9.11119C6.88878 9.11119 8.96327 9.0367 9.69678 8.3032L14.0301 3.96986C14.5824 3.4176 14.5824 2.52213 14.0301 1.96986C13.4778 1.4176 12.5824 1.4176 12.0301 1.96986L7.69678 6.3032C7.00513 6.99484 6.88878 9.11119 6.88878 9.11119Z" stroke="currentColor"/>`,
13
+ body: `<path d="M13.5556 8.21529V13.5556H2.44446L2.44446 2.44445H7.78474M6.00002 8.16216V10H7.83786L14 3.83784L12.1622 2L6.00002 8.16216Z" stroke="currentColor"/>`,
7
14
  },
8
15
  "folder-add-left": {
9
16
  viewBox: "0 0 16 16",
@@ -17,6 +24,10 @@ const icons = {
17
24
  viewBox: "0 0 16 16",
18
25
  body: `<path d="M5.118 5.686V10.314M5.118 5.686C5.97 5.686 6.661 4.995 6.661 4.143C6.661 3.291 5.97 2.6 5.118 2.6C4.266 2.6 3.575 3.291 3.575 4.143C3.575 4.995 4.266 5.686 5.118 5.686ZM5.118 10.314C4.266 10.314 3.575 11.005 3.575 11.857C3.575 12.709 4.266 13.4 5.118 13.4C5.97 13.4 6.661 12.709 6.661 11.857M5.118 10.314C5.97 10.314 6.661 11.005 6.661 11.857M10.882 5.686C11.734 5.686 12.425 4.995 12.425 4.143C12.425 3.291 11.734 2.6 10.882 2.6C10.03 2.6 9.339 3.291 9.339 4.143C9.339 4.995 10.03 5.686 10.882 5.686ZM10.882 5.686V9.457C10.882 10.783 9.807 11.857 8.482 11.857H6.661" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>`,
19
26
  },
27
+ "branch-out": {
28
+ viewBox: "0 0 16 16",
29
+ body: `<path d="M10.4225 3.35355L12.9024 5.83344L10.4225 8.31333" stroke="currentColor"/><path d="M1 12.2852H4.23042C4.89912 12.2852 5.52359 11.951 5.89452 11.3946L9.00783 6.72462C8.37877 6.16823 10.0032 5.83402 10.6719 5.83402H12.9024" stroke="currentColor"/><path d="M8.5 12.2852H14" stroke="currentColor" stroke-linejoin="round"/>`,
30
+ },
20
31
  "grid-plus": {
21
32
  viewBox: "0 0 16 16",
22
33
  body: `<path d="M13.9948 11.668H9.32812M11.6641 9.33203V13.9987M6.66667 9.33203V13.9987H2V9.33203H6.66667ZM6.66667 2V6.66667H2V2H6.66667ZM13.9948 2V6.66667H9.32812V2H13.9948Z" stroke="currentColor" stroke-miterlimit="10" stroke-linecap="square"/>`,
@@ -25,6 +36,14 @@ const icons = {
25
36
  viewBox: "0 0 16 16",
26
37
  body: `<path d="M6.33345 6.33349V5.00015H9.66679V7.00015L8.00015 8.00015V9.66679M8.27485 11.6819H7.71897M14.4446 8.00011C14.4446 11.5593 11.5593 14.4446 8.00011 14.4446C4.44094 14.4446 1.55566 11.5593 1.55566 8.00011C1.55566 4.44094 4.44094 1.55566 8.00011 1.55566C11.5593 1.55566 14.4446 4.44094 14.4446 8.00011Z" stroke="currentColor" stroke-linecap="square"/>`,
27
38
  },
39
+ info: {
40
+ viewBox: "0 0 16 16",
41
+ body: `<g transform="translate(2 2)"><path d="M12 12H0V0H12V12ZM1 1V11H11V1H1ZM6.5791 4.81641V9.37207H5.5791V5.81641H4.46777V4.81641H6.5791ZM6.85645 2.62891V3.62891H5.30078V2.62891H6.85645Z" fill="currentColor"/></g>`,
42
+ },
43
+ "circle-exclamation": {
44
+ viewBox: "0 0 16 16",
45
+ body: `<path d="M8.75 11.75H7.25V10.25H8.75V11.75Z" fill="currentColor"/><path d="M8.75 9.25H7.25V4.25H8.75V9.25Z" fill="currentColor"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8 1C9.93286 1 11.684 1.7836 12.9502 3.0498C14.2164 4.31601 15 6.06714 15 8C15 11.866 11.866 15 8 15C6.06714 15 4.31601 14.2164 3.0498 12.9502C1.7836 11.684 1 9.93286 1 8C1 4.13401 4.13401 1 8 1ZM8 2C4.68629 2 2 4.68629 2 8C2 9.65699 2.67148 11.1559 3.75781 12.2422C4.84415 13.3285 6.34301 14 8 14C11.3137 14 14 11.3137 14 8C14 6.34301 13.3285 4.84415 12.2422 3.75781C11.1559 2.67148 9.65699 2 8 2Z" fill="currentColor"/>`,
46
+ },
28
47
  "sidebar-right": {
29
48
  viewBox: "0 0 20 20",
30
49
  body: `<path d="M2.91536 2.91406H2.36536V2.36406H2.91536V2.91406ZM2.91536 17.0807V17.6307H2.36536V17.0807H2.91536ZM17.082 17.0807H17.632V17.6307H17.082V17.0807ZM17.082 2.91406V2.36406H17.632V2.91406H17.082ZM6.9987 2.91406H6.4487V2.36406H6.9987V2.91406ZM6.9987 17.0807V17.6307H6.4487V17.0807H6.9987ZM2.91536 2.91406H3.46536V17.0807H2.91536H2.36536V2.91406H2.91536ZM2.91536 17.0807V16.5307H17.082V17.0807V17.6307H2.91536V17.0807ZM17.082 17.0807H16.532V2.91406H17.082H17.632V17.0807H17.082ZM17.082 2.91406V3.46406H2.91536V2.91406V2.36406H17.082V2.91406ZM6.9987 2.91406H7.5487V17.0807H6.9987H6.4487V2.91406H6.9987ZM17.082 17.0807L17.082 17.6307L6.9987 17.6307V17.0807V16.5307L17.082 16.5307L17.082 17.0807ZM6.9987 2.91406V2.36406H17.082V2.91406V3.46406H6.9987V2.91406Z" fill="currentColor"/>`,
@@ -81,6 +100,14 @@ const icons = {
81
100
  viewBox: "0 0 16 16",
82
101
  body: `<path d="M2 10.668V14.0013H10.6667M13.9974 10.6667V2H2.66406M13.9974 10.668V14.0013H10.6641M2 10V2H5.33333" stroke="currentColor" stroke-miterlimit="10" stroke-linecap="square"/><path d="M10.6693 10.6654V5.33203H5.33594V10.6654H10.6693Z" fill="currentColor"/>`,
83
102
  },
103
+ "outline-worktree": {
104
+ viewBox: "0 0 16 16",
105
+ body: `<path d="M12 3.11133L14.3885 5.49977L12 7.88822M14.5 5.49972H10.058L5.13456 11.8139M14.5 11.6606L8.5 11.6606M5.50012 11.6597H1.5" stroke="currentColor"/>`,
106
+ },
107
+ "outline-trash": {
108
+ viewBox: "0 0 16 16",
109
+ body: `<path d="M2.44434 4.22224H13.5554M5.99994 4.22224V2.44446C5.99994 1.95557 5.99992 1.55557 5.99992 1.55557H9.99989C9.99989 1.55557 9.99994 1.95557 9.99994 2.44446V4.22224M6.55545 7.77779L6.7485 11.7778M9.44437 7.77779L9.2513 11.7778M12.1756 6.88891L11.8666 12.7556C11.8168 13.7068 11.7748 14.4445 11.7748 14.4445H4.22511C4.22511 14.4445 4.18392 13.7067 4.13414 12.7556L3.82509 6.88891" stroke="currentColor"/>`,
110
+ },
84
111
  close: {
85
112
  viewBox: "0 0 20 20",
86
113
  body: `<path d="M14.4446 5.55566L5.55566 14.4446M5.55566 5.55566L14.4446 14.4446" stroke="currentColor" stroke-linejoin="round"/>`,
@@ -121,6 +148,14 @@ const icons = {
121
148
  viewBox: "0 0 20 20",
122
149
  body: `<path d="M7 14.5H13M7 7.99512H10.0049M10.0049 7.99512H13M10.0049 7.99512V5M10.0049 7.99512V11M18 18V2L2 2L2 18H18Z" stroke="currentColor"/>`,
123
150
  },
151
+ "window-analytics": {
152
+ viewBox: "0 0 16 16",
153
+ body: `<path d="M14.5 9.8333V13.5H1.5V2.5H7.1667M9.5 2.5V7.5H14.5V2.5H9.5Z" stroke="currentColor" stroke-miterlimit="10" stroke-linecap="square"/>`,
154
+ },
155
+ trash: {
156
+ viewBox: "0 0 20 20",
157
+ body: `<path d="M4.58342 17.9134L4.58369 17.4134L4.22787 17.5384L4.22766 18.0384H4.58342V17.9134ZM15.4167 17.9134V18.0384H15.7725L15.7723 17.5384L15.4167 17.9134ZM2.08342 3.95508V3.45508H1.58342V3.95508H2.08342V4.45508V3.95508ZM17.9167 4.45508V4.95508H18.4167V4.45508H17.9167V3.95508V4.45508ZM4.16677 4.58008L3.66701 4.5996L4.22816 17.5379L4.72792 17.4934L5.22767 17.4489L4.66652 4.54055L4.16677 4.58008ZM4.58342 18.0384V17.9134H15.4167V18.0384V18.5384H4.58342V18.0384ZM15.4167 17.9134L15.8332 17.5379L16.2498 4.5996L15.7501 4.58008L15.2503 4.56055L14.8337 17.4989L15.4167 17.9134ZM15.8334 4.58008V4.08008H4.16677V4.58008V5.08008H15.8334V4.58008ZM2.08342 4.45508V4.95508H4.16677V4.58008V4.08008H2.08342V4.45508ZM15.8334 4.58008V5.08008H17.9167V4.45508V3.95508H15.8334V4.58008ZM6.83951 4.35149L7.432 4.55047C7.79251 3.47701 8.80699 2.70508 10.0001 2.70508V2.20508V1.70508C8.25392 1.70508 6.77335 2.83539 6.24702 4.15251L6.83951 4.35149ZM10.0001 2.20508V2.70508C11.1932 2.70508 12.2077 3.47701 12.5682 4.55047L13.1607 4.35149L13.7532 4.15251C13.2269 2.83539 11.7463 1.70508 10.0001 1.70508V2.20508Z" fill="currentColor"/>`,
158
+ },
124
159
  "outline-sliders": {
125
160
  viewBox: "0 0 16 16",
126
161
  body: `<path d="M11.7779 4.66675H14.4446M11.7779 4.66675C11.7779 5.77132 10.8825 6.66675 9.77789 6.66675C8.67332 6.66675 7.77789 5.77132 7.77789 4.66675M11.7779 4.66675C11.7779 3.56218 10.8825 2.66675 9.77789 2.66675C8.67332 2.66675 7.77789 3.56218 7.77789 4.66675M1.55566 4.66675H7.77789M4.22233 11.3334H1.55566M4.22233 11.3334C4.22233 12.438 5.11776 13.3334 6.22233 13.3334C7.3269 13.3334 8.22233 12.438 8.22233 11.3334M4.22233 11.3334C4.22233 10.2288 5.11776 9.33341 6.22233 9.33341C7.3269 9.33341 8.22233 10.2288 8.22233 11.3334M14.4446 11.3334H8.22233" stroke="currentColor"/>`,
@@ -129,10 +164,22 @@ const icons = {
129
164
  viewBox: "0 0 16 16",
130
165
  body: `<path d="M4.14908 11.0081H1.76282V1.51758H9.1038V2.55588M14.2225 4.99681H6.75397V14.4873H14.2225V4.99681Z" stroke="currentColor"/>`,
131
166
  },
167
+ "arrow-up-right": {
168
+ viewBox: "0 0 16 16",
169
+ body: `<path d="M11 9.56V5H6.44M11 5L5 11" stroke="currentColor"/>`,
170
+ },
132
171
  "outline-square-arrow": {
133
172
  viewBox: "0 0 16 16",
134
173
  body: `<path d="M13.5555 6.66656V2.44434H9.33326M13.5555 2.44434L7.99993 7.99989M13.5555 9.33324V13.5555C13.5555 13.5555 12.7599 13.5555 11.7777 13.5555H2.44438C2.44438 13.5555 2.44438 12.7599 2.44438 11.7777V4.22213C2.44438 3.2399 2.44434 2.44435 2.44434 2.44435H6.66661" stroke="currentColor"/>`,
135
174
  },
175
+ "outline-arrow-to-corner-top-right": {
176
+ viewBox: "0 0 16 16",
177
+ body: `<path d="M2 8.5V2H14V14H8M5 5.66667H10.3333V11M3.66797 12.333L9.94292 6.05806" stroke="currentColor" stroke-linecap="square"/>`,
178
+ },
179
+ "outline-hexagonal-warning": {
180
+ viewBox: "0 0 16 16",
181
+ body: `<path d="M10.6667 1.33325H5.33272L1.33334 5.33325L1.33342 10.6917L5.3327 14.691L10.6667 14.6909L14.6911 10.6917V5.33255L10.6667 1.33325Z" stroke="currentColor"/><path d="M8 10.6667H8.00667" stroke="currentColor" stroke-linecap="square"/><path d="M8 7.99992V5.33325" stroke="currentColor" stroke-linecap="square"/>`,
182
+ },
136
183
  "outline-share": {
137
184
  viewBox: "0 0 16 16",
138
185
  body: `<path d="M13.5554 10.4445V13.5556C13.5554 13.5556 12.7599 13.5556 11.7777 13.5556H4.22211C3.23989 13.5556 2.44434 13.5556 2.44434 13.5556V10.4445M4.88878 5.55557L7.99989 2.44446L11.111 5.55557M7.99989 2.44446L7.99989 9.11112" stroke="currentColor"/>`,
@@ -145,20 +192,42 @@ const icons = {
145
192
  viewBox: "0 0 20 20",
146
193
  body: `<path d="M5.83333 4.16406L2.5 7.4974L5.83333 10.8307M3.33333 7.4974H17.9167V15.4141H10" stroke="currentColor" stroke-linecap="square"/>`,
147
194
  },
195
+ "fill-triangle-down": {
196
+ viewBox: "0 0 16 16",
197
+ body: `<path d="M5.37624 6.75194C5.1818 6.41861 5.42223 6 5.80813 6H10.1921C10.578 6 10.8184 6.41861 10.624 6.75194L8.43199 10.5096C8.23905 10.8404 7.76115 10.8404 7.56821 10.5096L5.37624 6.75194Z" fill="currentColor"/>`,
198
+ },
148
199
  archive: {
149
200
  viewBox: "0 0 16 16",
150
201
  body: `<path d="M13.1112 13.5555V14.0555H13.6112V13.5555H13.1112ZM2.889 13.5555H2.389L2.389 14.0555H2.889V13.5555ZM3.38901 5.55546L3.38901 5.05546L2.38901 5.05546L2.38901 5.55546L2.88901 5.55546L3.38901 5.55546ZM14.4446 2.44434H14.9446V1.94434L14.4446 1.94434L14.4446 2.44434ZM14.4446 5.55545L14.4446 6.05545L14.9446 6.05545V5.55545H14.4446ZM1.55566 5.55546L1.05566 5.55545L1.05566 6.05546L1.55566 6.05546L1.55566 5.55546ZM1.5557 2.44436L1.5557 1.94436L1.05571 1.94436L1.0557 2.44435L1.5557 2.44436ZM13.1112 5.55546H12.6112V13.5555H13.1112H13.6112V5.55546H13.1112ZM2.889 13.5555H3.389L3.38901 5.55546L2.88901 5.55546L2.38901 5.55546L2.389 13.5555H2.889ZM14.4446 2.44434H13.9446V5.55545H14.4446H14.9446V2.44434H14.4446ZM1.55566 5.55546L2.05566 5.55547L2.0557 2.44436L1.5557 2.44436L1.0557 2.44435L1.05566 5.55545L1.55566 5.55546ZM6.22234 8.22213V8.72213H9.7779V8.22213V7.72213H6.22234V8.22213ZM13.1112 13.5555V13.0555H2.889V13.5555V14.0555H13.1112V13.5555ZM1.5557 2.44436L1.5557 2.94436L14.4446 2.94434L14.4446 2.44434L14.4446 1.94434L1.5557 1.94436L1.5557 2.44436ZM14.4446 5.55545L14.4446 5.05545L1.55566 5.05546L1.55566 5.55546L1.55566 6.05546L14.4446 6.05545L14.4446 5.55545Z" fill="currentColor"/>`,
151
202
  },
152
203
  }
153
204
 
205
+ type IconName = keyof typeof icons | keyof typeof additionalIcons
206
+
154
207
  const spriteID = "opencode-v2-icon-sprite"
155
- const symbol = (name: keyof typeof icons) => `opencode-v2-icon-${name}`
208
+ const symbol = (name: IconName) => `opencode-v2-icon-${name}`
156
209
  let spriteInserted = false
157
210
 
211
+ function getIcon(name: IconName) {
212
+ const icon = icons[name as keyof typeof icons]
213
+ if (icon) return icon
214
+ const body = additionalIcons[name as keyof typeof additionalIcons]
215
+ return { body, viewBox: additionalIconViewBox(name as keyof typeof additionalIcons) }
216
+ }
217
+
218
+ function spriteContent() {
219
+ return Array.from(new Set<IconName>([...Object.keys(additionalIcons), ...Object.keys(icons)] as IconName[]))
220
+ .map((name) => `<symbol id="${symbol(name)}" viewBox="${getIcon(name).viewBox}">${getIcon(name).body}</symbol>`)
221
+ .join("")
222
+ }
223
+
158
224
  function ensureSprite() {
159
225
  if (spriteInserted) return
160
226
  if (typeof document === "undefined") return
161
- if (document.getElementById(spriteID)) {
227
+ // Hot reload preserves the DOM sprite, but its symbols may be from an older module.
228
+ const existing = document.getElementById(spriteID)
229
+ if (existing) {
230
+ existing.innerHTML = spriteContent()
162
231
  spriteInserted = true
163
232
  return
164
233
  }
@@ -170,25 +239,24 @@ function ensureSprite() {
170
239
  svg.setAttribute("height", "0")
171
240
  svg.style.position = "absolute"
172
241
  svg.style.overflow = "hidden"
173
- svg.innerHTML = Object.entries(icons)
174
- .map(
175
- ([name, icon]) =>
176
- `<symbol id="${symbol(name as keyof typeof icons)}" viewBox="${icon.viewBox}">${icon.body}</symbol>`,
177
- )
178
- .join("")
242
+ svg.innerHTML = spriteContent()
179
243
  document.body.insertBefore(svg, document.body.firstChild)
180
244
  spriteInserted = true
181
245
  }
182
246
 
183
247
  export interface IconProps extends ComponentProps<"svg"> {
184
- name: keyof typeof icons | (string & {})
248
+ name: IconName | (string & {})
185
249
  size?: "small" | "normal" | "large"
186
250
  }
187
251
 
188
252
  export function Icon(props: IconProps) {
189
253
  const [split, rest] = splitProps(props, ["name", "size"])
190
- const iconName = () => (icons[split.name as keyof typeof icons] ? (split.name as keyof typeof icons) : "plus")
191
- const icon = () => icons[iconName()]
254
+ const iconName = (): IconName => {
255
+ if (icons[split.name as keyof typeof icons]) return split.name as keyof typeof icons
256
+ if (additionalIcons[split.name as keyof typeof additionalIcons]) return split.name as keyof typeof additionalIcons
257
+ return "plus"
258
+ }
259
+ const icon = () => getIcon(iconName())
192
260
  const pixelSize = split.size === "small" ? 14 : split.size === "large" ? 20 : 16
193
261
  onMount(ensureSprite)
194
262
 
@@ -196,6 +264,14 @@ export function Icon(props: IconProps) {
196
264
  <svg
197
265
  {...rest}
198
266
  data-slot="icon-svg"
267
+ data-directional={
268
+ iconName() === "arrow-left" ||
269
+ iconName() === "arrow-right" ||
270
+ iconName() === "chevron-left" ||
271
+ iconName() === "chevron-right"
272
+ ? ""
273
+ : undefined
274
+ }
199
275
  width={pixelSize}
200
276
  height={pixelSize}
201
277
  viewBox={icon().viewBox}
@@ -1,9 +1,9 @@
1
1
  import { type ComponentProps, splitProps } from "solid-js"
2
- import "./divider-v2.css"
2
+ import "./divider.css"
3
3
 
4
- export interface DividerV2Props extends ComponentProps<"div"> {}
4
+ export interface DividerProps extends ComponentProps<"div"> {}
5
5
 
6
- export function DividerV2(props: DividerV2Props) {
6
+ export function Divider(props: DividerProps) {
7
7
  const [local, rest] = splitProps(props, ["class", "classList"])
8
8
  return (
9
9
  <div
@@ -31,6 +31,10 @@
31
31
  }
32
32
  }
33
33
 
34
+ :dir(rtl) [data-slot="menu-v2-item-chevron"] {
35
+ transform: scaleX(-1);
36
+ }
37
+
34
38
  [data-component="menu-v2-item"] {
35
39
  --menu-v2-fg: var(--v2-text-text-base);
36
40
  --menu-v2-fg-muted: var(--v2-text-text-faint);
@@ -47,11 +51,13 @@
47
51
 
48
52
  box-sizing: border-box;
49
53
  display: flex;
54
+ flex-shrink: 0;
50
55
  flex-direction: row;
51
56
  align-items: center;
52
57
  gap: 8px;
53
58
  height: 28px;
54
59
  padding: 0 12px;
60
+ padding-inline-end: 6px;
55
61
  background: transparent;
56
62
  border-radius: 4px;
57
63
  outline: none;
@@ -72,7 +78,7 @@
72
78
 
73
79
  font-size: 13px;
74
80
  font-weight: 440;
75
- line-height: 100%;
81
+ line-height: var(--line-height-compact);
76
82
  letter-spacing: -0.04px;
77
83
  color: var(--menu-v2-fg);
78
84
  }
@@ -171,13 +177,129 @@
171
177
 
172
178
  font-size: 11px;
173
179
  font-weight: 530;
174
- line-height: 100%;
175
180
  letter-spacing: 0.05px;
176
181
  color: var(--v2-text-text-faint);
177
182
  user-select: none;
178
183
  font-variant-numeric: tabular-nums;
179
184
  }
180
185
 
186
+ [data-component="menu-v2-content"][data-appearance="standard"] {
187
+ min-width: 8rem;
188
+ padding: 4px;
189
+ overflow: hidden;
190
+ border: 1px solid color-mix(in oklch, var(--border-base) 50%, transparent);
191
+ border-radius: var(--radius-md);
192
+ background: var(--surface-raised-stronger-non-alpha);
193
+ background-clip: padding-box;
194
+ box-shadow: var(--shadow-md);
195
+ z-index: 60;
196
+ animation: dropdown-menu-open 150ms ease-out;
197
+
198
+ &[data-closed] {
199
+ animation: dropdown-menu-close 150ms ease-out;
200
+ }
201
+
202
+ [data-component="menu-v2-item"] {
203
+ position: relative;
204
+ height: auto;
205
+ min-height: 0;
206
+ padding: 4px 8px;
207
+ border-radius: var(--radius-sm);
208
+ color: var(--text-strong);
209
+ font-family: var(--font-family-sans);
210
+ font-size: var(--font-size-small);
211
+ font-weight: var(--font-weight-medium);
212
+ line-height: var(--line-height-large);
213
+ letter-spacing: var(--letter-spacing-normal);
214
+ font-variant-numeric: normal;
215
+ -webkit-font-smoothing: auto;
216
+ text-rendering: auto;
217
+
218
+ [data-slot="menu-v2-item-content"] {
219
+ font-family: inherit;
220
+ font-size: inherit;
221
+ font-weight: inherit;
222
+ line-height: inherit;
223
+ letter-spacing: inherit;
224
+ color: inherit;
225
+ }
226
+
227
+ &[data-highlighted] {
228
+ background: var(--surface-raised-base-hover);
229
+ }
230
+
231
+ &[data-disabled] {
232
+ color: var(--text-weak);
233
+ opacity: 1;
234
+ }
235
+
236
+ &[data-checked] {
237
+ padding-inline-end: 28px;
238
+ }
239
+
240
+ &[data-checked] [data-slot="menu-v2-item-content"] {
241
+ font-weight: inherit;
242
+ color: inherit;
243
+ }
244
+
245
+ [data-slot="menu-v2-item-indicator"] {
246
+ position: absolute;
247
+ inset-inline-end: 8px;
248
+ top: 50%;
249
+ width: 16px;
250
+ height: 16px;
251
+ transform: translateY(-50%);
252
+ color: var(--icon-base);
253
+ }
254
+
255
+ [data-slot="menu-v2-item-chevron"] {
256
+ margin-inline-start: auto;
257
+ color: var(--icon-base);
258
+ }
259
+ }
260
+
261
+ [data-slot="menu-v2-separator"] {
262
+ width: calc(100% + 8px);
263
+ height: 1px;
264
+ margin: 4px -4px;
265
+ background: var(--border-weak-base);
266
+ }
267
+
268
+ [data-slot="menu-v2-group-label"] {
269
+ height: auto;
270
+ padding: 4px 8px;
271
+ color: var(--text-weak);
272
+ font-family: var(--font-family-sans);
273
+ font-size: var(--font-size-x-small);
274
+ font-weight: var(--font-weight-medium);
275
+ line-height: var(--line-height-large);
276
+ letter-spacing: var(--letter-spacing-normal);
277
+ font-variant-numeric: normal;
278
+ }
279
+ }
280
+
281
+ @keyframes dropdown-menu-open {
282
+ from {
283
+ opacity: 0;
284
+ transform: scale(0.96);
285
+ }
286
+ to {
287
+ opacity: 1;
288
+ transform: scale(1);
289
+ }
290
+ }
291
+
292
+ @keyframes dropdown-menu-close {
293
+ from {
294
+ opacity: 1;
295
+ transform: scale(1);
296
+ }
297
+ to {
298
+ opacity: 0;
299
+ transform: scale(0.96);
300
+ }
301
+ }
302
+
181
303
  @keyframes menu-v2-in {
182
304
  from {
183
305
  opacity: 0;
@@ -1,7 +1,17 @@
1
1
  import { DropdownMenu } from "@kobalte/core/dropdown-menu"
2
2
  import { ContextMenu } from "@kobalte/core/context-menu"
3
- import { Show, splitProps, type Component, type ComponentProps, type JSX, type ParentProps } from "solid-js"
4
- import "./menu-v2.css"
3
+ import {
4
+ createContext,
5
+ Show,
6
+ splitProps,
7
+ useContext,
8
+ type Accessor,
9
+ type Component,
10
+ type ComponentProps,
11
+ type JSX,
12
+ type ParentProps,
13
+ } from "solid-js"
14
+ import "./menu.css"
5
15
 
6
16
  const ChevronRight: Component = () => (
7
17
  <svg
@@ -29,6 +39,18 @@ const CheckMark: Component = () => (
29
39
  </svg>
30
40
  )
31
41
 
42
+ export type MenuAppearance = "standard" | "compact"
43
+
44
+ const MenuAppearanceContext = createContext<{ appearance: Accessor<MenuAppearance> }>({
45
+ appearance: (): MenuAppearance => "compact",
46
+ })
47
+
48
+ function useMenuContext() {
49
+ const ctx = useContext(MenuAppearanceContext)
50
+ if (!ctx) throw new Error("Menu components must be used inside Menu or Menu.Context")
51
+ return ctx
52
+ }
53
+
32
54
  function ItemBody(
33
55
  props: ParentProps<{
34
56
  shortcut?: JSX.Element | string
@@ -46,15 +68,21 @@ function ItemBody(
46
68
  )
47
69
  }
48
70
 
49
- export interface MenuV2ItemProps extends ComponentProps<typeof DropdownMenu.Item> {
71
+ export interface MenuItemProps extends ComponentProps<typeof DropdownMenu.Item> {
50
72
  shortcut?: JSX.Element | string
51
73
  badge?: JSX.Element | string
52
74
  }
53
75
 
54
- function MenuV2Item(props: ParentProps<MenuV2ItemProps>) {
76
+ function MenuItem(props: ParentProps<MenuItemProps>) {
77
+ const ctx = useMenuContext()
55
78
  const [s, r] = splitProps(props, ["class", "classList", "children", "shortcut", "badge"])
56
79
  return (
57
- <DropdownMenu.Item {...r} data-component="menu-v2-item" classList={{ ...s.classList, [s.class ?? ""]: !!s.class }}>
80
+ <DropdownMenu.Item
81
+ {...r}
82
+ data-component="menu-v2-item"
83
+ data-appearance={ctx.appearance()}
84
+ classList={{ ...s.classList, [s.class ?? ""]: !!s.class }}
85
+ >
58
86
  <ItemBody shortcut={s.shortcut} badge={s.badge}>
59
87
  {s.children}
60
88
  </ItemBody>
@@ -62,17 +90,19 @@ function MenuV2Item(props: ParentProps<MenuV2ItemProps>) {
62
90
  )
63
91
  }
64
92
 
65
- export interface MenuV2CheckboxItemProps extends ComponentProps<typeof DropdownMenu.CheckboxItem> {
93
+ export interface MenuCheckboxItemProps extends ComponentProps<typeof DropdownMenu.CheckboxItem> {
66
94
  shortcut?: JSX.Element | string
67
95
  badge?: JSX.Element | string
68
96
  }
69
97
 
70
- function MenuV2CheckboxItem(props: ParentProps<MenuV2CheckboxItemProps>) {
98
+ function MenuCheckboxItem(props: ParentProps<MenuCheckboxItemProps>) {
99
+ const ctx = useMenuContext()
71
100
  const [s, r] = splitProps(props, ["class", "classList", "children", "shortcut", "badge"])
72
101
  return (
73
102
  <DropdownMenu.CheckboxItem
74
103
  {...r}
75
104
  data-component="menu-v2-item"
105
+ data-appearance={ctx.appearance()}
76
106
  classList={{ ...s.classList, [s.class ?? ""]: !!s.class }}
77
107
  >
78
108
  <ItemBody
@@ -90,17 +120,19 @@ function MenuV2CheckboxItem(props: ParentProps<MenuV2CheckboxItemProps>) {
90
120
  )
91
121
  }
92
122
 
93
- export interface MenuV2RadioItemProps extends ComponentProps<typeof DropdownMenu.RadioItem> {
123
+ export interface MenuRadioItemProps extends ComponentProps<typeof DropdownMenu.RadioItem> {
94
124
  shortcut?: JSX.Element | string
95
125
  badge?: JSX.Element | string
96
126
  }
97
127
 
98
- function MenuV2RadioItem(props: ParentProps<MenuV2RadioItemProps>) {
128
+ function MenuRadioItem(props: ParentProps<MenuRadioItemProps>) {
129
+ const ctx = useMenuContext()
99
130
  const [s, r] = splitProps(props, ["class", "classList", "children", "shortcut", "badge"])
100
131
  return (
101
132
  <DropdownMenu.RadioItem
102
133
  {...r}
103
134
  data-component="menu-v2-item"
135
+ data-appearance={ctx.appearance()}
104
136
  classList={{ ...s.classList, [s.class ?? ""]: !!s.class }}
105
137
  >
106
138
  <ItemBody
@@ -118,17 +150,19 @@ function MenuV2RadioItem(props: ParentProps<MenuV2RadioItemProps>) {
118
150
  )
119
151
  }
120
152
 
121
- export interface MenuV2SubTriggerProps extends ComponentProps<typeof DropdownMenu.SubTrigger> {
153
+ export interface MenuSubTriggerProps extends ComponentProps<typeof DropdownMenu.SubTrigger> {
122
154
  shortcut?: JSX.Element | string
123
155
  badge?: JSX.Element | string
124
156
  }
125
157
 
126
- function MenuV2SubTrigger(props: ParentProps<MenuV2SubTriggerProps>) {
158
+ function MenuSubTrigger(props: ParentProps<MenuSubTriggerProps>) {
159
+ const ctx = useMenuContext()
127
160
  const [s, r] = splitProps(props, ["class", "classList", "children", "shortcut", "badge"])
128
161
  return (
129
162
  <DropdownMenu.SubTrigger
130
163
  {...r}
131
164
  data-component="menu-v2-item"
165
+ data-appearance={ctx.appearance()}
132
166
  classList={{ ...s.classList, [s.class ?? ""]: !!s.class }}
133
167
  >
134
168
  <ItemBody shortcut={s.shortcut} badge={s.badge} trailing={<ChevronRight />}>
@@ -138,88 +172,118 @@ function MenuV2SubTrigger(props: ParentProps<MenuV2SubTriggerProps>) {
138
172
  )
139
173
  }
140
174
 
141
- function MenuV2SubContent(props: ComponentProps<typeof DropdownMenu.SubContent>) {
175
+ function MenuSubContent(props: ComponentProps<typeof DropdownMenu.SubContent>) {
176
+ const ctx = useMenuContext()
142
177
  const [s, r] = splitProps(props, ["class", "classList"])
143
178
  return (
144
179
  <DropdownMenu.SubContent
145
180
  {...r}
146
181
  data-component="menu-v2-content"
182
+ data-appearance={ctx.appearance()}
147
183
  classList={{ ...s.classList, [s.class ?? ""]: !!s.class }}
148
184
  />
149
185
  )
150
186
  }
151
187
 
152
- function MenuV2GroupLabel(props: ComponentProps<typeof DropdownMenu.GroupLabel>) {
188
+ function MenuGroupLabel(props: ComponentProps<typeof DropdownMenu.GroupLabel>) {
189
+ const ctx = useMenuContext()
153
190
  const [s, r] = splitProps(props, ["class", "classList"])
154
191
  return (
155
192
  <DropdownMenu.GroupLabel
156
193
  {...r}
157
194
  data-slot="menu-v2-group-label"
195
+ data-appearance={ctx.appearance()}
158
196
  classList={{ ...s.classList, [s.class ?? ""]: !!s.class }}
159
197
  />
160
198
  )
161
199
  }
162
200
 
163
- function MenuV2Separator(props: ComponentProps<typeof DropdownMenu.Separator>) {
201
+ function MenuSeparator(props: ComponentProps<typeof DropdownMenu.Separator>) {
202
+ const ctx = useMenuContext()
164
203
  const [s, r] = splitProps(props, ["class", "classList"])
165
204
  return (
166
205
  <DropdownMenu.Separator
167
206
  {...r}
168
207
  data-slot="menu-v2-separator"
208
+ data-appearance={ctx.appearance()}
169
209
  classList={{ ...s.classList, [s.class ?? ""]: !!s.class }}
170
210
  />
171
211
  )
172
212
  }
173
213
 
174
- function MenuV2Content(props: ComponentProps<typeof DropdownMenu.Content>) {
214
+ function MenuContent(props: ComponentProps<typeof DropdownMenu.Content>) {
215
+ const ctx = useMenuContext()
175
216
  const [s, r] = splitProps(props, ["class", "classList"])
176
217
  return (
177
218
  <DropdownMenu.Content
178
219
  {...r}
179
220
  data-component="menu-v2-content"
221
+ data-appearance={ctx.appearance()}
180
222
  classList={{ ...s.classList, [s.class ?? ""]: !!s.class }}
181
223
  />
182
224
  )
183
225
  }
184
226
 
185
- function MenuV2Root(props: ComponentProps<typeof DropdownMenu>) {
186
- return <DropdownMenu {...props} />
227
+ export interface MenuProps extends ComponentProps<typeof DropdownMenu> {
228
+ appearance?: MenuAppearance
187
229
  }
188
230
 
189
- function MenuV2ContextRoot(props: ComponentProps<typeof ContextMenu>) {
190
- return <ContextMenu {...props} />
231
+ function MenuRoot(props: MenuProps) {
232
+ const [local, rest] = splitProps(props, ["appearance", "children"])
233
+ const appearance = () => local.appearance ?? "compact"
234
+ return (
235
+ <MenuAppearanceContext.Provider value={{ appearance }}>
236
+ <DropdownMenu {...rest}>{local.children}</DropdownMenu>
237
+ </MenuAppearanceContext.Provider>
238
+ )
239
+ }
240
+
241
+ export interface MenuContextProps extends ComponentProps<typeof ContextMenu> {
242
+ appearance?: MenuAppearance
243
+ }
244
+
245
+ function MenuContextRoot(props: MenuContextProps) {
246
+ const [local, rest] = splitProps(props, ["appearance", "children"])
247
+ const appearance = () => local.appearance ?? "compact"
248
+ return (
249
+ <MenuAppearanceContext.Provider value={{ appearance }}>
250
+ <ContextMenu {...rest}>{local.children}</ContextMenu>
251
+ </MenuAppearanceContext.Provider>
252
+ )
191
253
  }
192
254
 
193
- function MenuV2ContextContent(props: ComponentProps<typeof ContextMenu.Content>) {
255
+ function MenuContextContent(props: ComponentProps<typeof ContextMenu.Content>) {
256
+ const ctx = useMenuContext()
194
257
  const [s, r] = splitProps(props, ["class", "classList"])
195
258
  return (
196
259
  <ContextMenu.Content
197
260
  {...r}
198
261
  data-component="menu-v2-content"
262
+ data-appearance={ctx.appearance()}
199
263
  classList={{ ...s.classList, [s.class ?? ""]: !!s.class }}
200
264
  />
201
265
  )
202
266
  }
203
267
 
204
- const MenuV2Context = Object.assign(MenuV2ContextRoot, {
268
+ const MenuContext = Object.assign(MenuContextRoot, {
205
269
  Trigger: ContextMenu.Trigger,
206
270
  Portal: ContextMenu.Portal,
207
- Content: MenuV2ContextContent,
271
+ Content: MenuContextContent,
208
272
  })
209
273
 
210
- export const MenuV2 = Object.assign(MenuV2Root, {
274
+ export const Menu = Object.assign(MenuRoot, {
211
275
  Trigger: DropdownMenu.Trigger,
212
276
  Portal: DropdownMenu.Portal,
213
- Content: MenuV2Content,
214
- Item: MenuV2Item,
215
- CheckboxItem: MenuV2CheckboxItem,
277
+ Content: MenuContent,
278
+ Item: MenuItem,
279
+ CheckboxItem: MenuCheckboxItem,
216
280
  RadioGroup: DropdownMenu.RadioGroup,
217
- RadioItem: MenuV2RadioItem,
281
+ RadioItem: MenuRadioItem,
218
282
  Group: DropdownMenu.Group,
219
- GroupLabel: MenuV2GroupLabel,
220
- Separator: MenuV2Separator,
283
+ GroupLabel: MenuGroupLabel,
284
+ Separator: MenuSeparator,
221
285
  Sub: DropdownMenu.Sub,
222
- SubTrigger: MenuV2SubTrigger,
223
- SubContent: MenuV2SubContent,
224
- Context: MenuV2Context,
286
+ SubTrigger: MenuSubTrigger,
287
+ SubContent: MenuSubContent,
288
+ Context: MenuContext,
225
289
  })
@@ -37,7 +37,7 @@
37
37
  font-style: normal;
38
38
  font-weight: 440;
39
39
  font-size: 13px;
40
- line-height: 100%;
40
+ line-height: var(--line-height-compact);
41
41
  letter-spacing: -0.04px;
42
42
  font-variant-numeric: tabular-nums;
43
43
  font-variation-settings: "slnt" 0;