@veracity/vui 2.31.0 → 2.33.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 (219) hide show
  1. package/dist/cjs/button/button.d.ts.map +1 -1
  2. package/dist/cjs/button/button.js +15 -0
  3. package/dist/cjs/button/button.js.map +1 -1
  4. package/dist/cjs/calendar/calendar.styles.js +5 -5
  5. package/dist/cjs/calendar/calendar.styles.js.map +1 -1
  6. package/dist/cjs/calendar/components/calendarHeader.js +1 -1
  7. package/dist/cjs/calendar/components/calendarHeader.js.map +1 -1
  8. package/dist/cjs/calendar/components/dayPicker.d.ts.map +1 -1
  9. package/dist/cjs/calendar/components/dayPicker.js +6 -2
  10. package/dist/cjs/calendar/components/dayPicker.js.map +1 -1
  11. package/dist/cjs/calendar/components/monthPicker.d.ts.map +1 -1
  12. package/dist/cjs/calendar/components/monthPicker.js +1 -1
  13. package/dist/cjs/calendar/components/monthPicker.js.map +1 -1
  14. package/dist/cjs/calendar/components/timeUnitHeader.d.ts.map +1 -1
  15. package/dist/cjs/calendar/components/timeUnitHeader.js +1 -1
  16. package/dist/cjs/calendar/components/timeUnitHeader.js.map +1 -1
  17. package/dist/cjs/calendar/components/yearPicker.d.ts.map +1 -1
  18. package/dist/cjs/calendar/components/yearPicker.js +1 -1
  19. package/dist/cjs/calendar/components/yearPicker.js.map +1 -1
  20. package/dist/cjs/calendar/hooks/useCalendar.d.ts +1 -1
  21. package/dist/cjs/calendar/hooks/useCalendar.d.ts.map +1 -1
  22. package/dist/cjs/calendar/hooks/useCalendar.js +22 -16
  23. package/dist/cjs/calendar/hooks/useCalendar.js.map +1 -1
  24. package/dist/cjs/datePicker/datePicker.js +1 -1
  25. package/dist/cjs/datePicker/datePicker.js.map +1 -1
  26. package/dist/cjs/footer/footer.d.ts.map +1 -1
  27. package/dist/cjs/footer/footer.js +1 -1
  28. package/dist/cjs/footer/footer.js.map +1 -1
  29. package/dist/cjs/header/loggedInHeader.js +1 -1
  30. package/dist/cjs/header/loggedInHeader.js.map +1 -1
  31. package/dist/cjs/header/loggedOutHeader.js +1 -1
  32. package/dist/cjs/header/loggedOutHeader.js.map +1 -1
  33. package/dist/cjs/icons/baseIcons/brand/brandXTwitter.d.ts +4 -0
  34. package/dist/cjs/icons/baseIcons/brand/brandXTwitter.d.ts.map +1 -0
  35. package/dist/cjs/icons/baseIcons/brand/brandXTwitter.js +7 -0
  36. package/dist/cjs/icons/baseIcons/brand/brandXTwitter.js.map +1 -0
  37. package/dist/cjs/icons/baseIcons/brand/brandXTwitterSolid.d.ts +4 -0
  38. package/dist/cjs/icons/baseIcons/brand/brandXTwitterSolid.d.ts.map +1 -0
  39. package/dist/cjs/icons/baseIcons/brand/brandXTwitterSolid.js +7 -0
  40. package/dist/cjs/icons/baseIcons/brand/brandXTwitterSolid.js.map +1 -0
  41. package/dist/cjs/icons/baseIcons/icons.d.ts +3 -2
  42. package/dist/cjs/icons/baseIcons/icons.d.ts.map +1 -1
  43. package/dist/cjs/icons/baseIcons/icons.js +12 -10
  44. package/dist/cjs/icons/baseIcons/icons.js.map +1 -1
  45. package/dist/cjs/icons/baseIcons/types.d.ts +2 -2
  46. package/dist/cjs/icons/baseIcons/types.d.ts.map +1 -1
  47. package/dist/cjs/icons/baseIcons/ui/uiShield.js +1 -1
  48. package/dist/cjs/icons/baseIcons/ui/uiShield.js.map +1 -1
  49. package/dist/cjs/icons/baseIcons/ui/uiShieldSolid.d.ts +4 -0
  50. package/dist/cjs/icons/baseIcons/ui/uiShieldSolid.d.ts.map +1 -0
  51. package/dist/cjs/icons/baseIcons/ui/uiShieldSolid.js +8 -0
  52. package/dist/cjs/icons/baseIcons/ui/uiShieldSolid.js.map +1 -0
  53. package/dist/cjs/input/consts.d.ts +3 -3
  54. package/dist/cjs/input/consts.js +5 -5
  55. package/dist/cjs/input/consts.js.map +1 -1
  56. package/dist/cjs/input/input.d.ts.map +1 -1
  57. package/dist/cjs/input/input.js +6 -0
  58. package/dist/cjs/input/input.js.map +1 -1
  59. package/dist/cjs/input/inputIcon.d.ts.map +1 -1
  60. package/dist/cjs/input/inputIcon.js +1 -3
  61. package/dist/cjs/input/inputIcon.js.map +1 -1
  62. package/dist/cjs/range/range.js +1 -1
  63. package/dist/cjs/range/range.js.map +1 -1
  64. package/dist/cjs/select/useSelect.js +1 -1
  65. package/dist/cjs/select/useSelect.js.map +1 -1
  66. package/dist/cjs/sidemenuV2/SidemenuItemContent.d.ts +14 -0
  67. package/dist/cjs/sidemenuV2/SidemenuItemContent.d.ts.map +1 -0
  68. package/dist/cjs/sidemenuV2/SidemenuItemContent.js +22 -0
  69. package/dist/cjs/sidemenuV2/SidemenuItemContent.js.map +1 -0
  70. package/dist/cjs/sidemenuV2/sidemenuItemV2.d.ts.map +1 -1
  71. package/dist/cjs/sidemenuV2/sidemenuItemV2.js +20 -16
  72. package/dist/cjs/sidemenuV2/sidemenuItemV2.js.map +1 -1
  73. package/dist/cjs/sidemenuV2/sidemenuTopV2.d.ts +8 -0
  74. package/dist/cjs/sidemenuV2/sidemenuTopV2.d.ts.map +1 -0
  75. package/dist/cjs/sidemenuV2/sidemenuTopV2.js +31 -0
  76. package/dist/cjs/sidemenuV2/sidemenuTopV2.js.map +1 -0
  77. package/dist/cjs/sidemenuV2/sidemenuV2.d.ts +2 -0
  78. package/dist/cjs/sidemenuV2/sidemenuV2.d.ts.map +1 -1
  79. package/dist/cjs/sidemenuV2/sidemenuV2.js +9 -3
  80. package/dist/cjs/sidemenuV2/sidemenuV2.js.map +1 -1
  81. package/dist/cjs/sidemenuV2/sidemenuV2.types.d.ts +8 -0
  82. package/dist/cjs/sidemenuV2/sidemenuV2.types.d.ts.map +1 -1
  83. package/dist/cjs/table/tableSortIcon.d.ts.map +1 -1
  84. package/dist/cjs/table/tableSortIcon.js +15 -16
  85. package/dist/cjs/table/tableSortIcon.js.map +1 -1
  86. package/dist/cjs/tooltip/tooltip.d.ts.map +1 -1
  87. package/dist/cjs/tooltip/tooltip.js +2 -2
  88. package/dist/cjs/tooltip/tooltip.js.map +1 -1
  89. package/dist/cjs/tooltip/tooltip.types.d.ts +1 -0
  90. package/dist/cjs/tooltip/tooltip.types.d.ts.map +1 -1
  91. package/dist/cjs/tooltip/tooltipContent.js +1 -1
  92. package/dist/cjs/tooltip/tooltipContent.js.map +1 -1
  93. package/dist/esm/button/button.d.ts.map +1 -1
  94. package/dist/esm/button/button.js +15 -0
  95. package/dist/esm/button/button.js.map +1 -1
  96. package/dist/esm/calendar/calendar.styles.js +5 -5
  97. package/dist/esm/calendar/calendar.styles.js.map +1 -1
  98. package/dist/esm/calendar/components/calendarHeader.js +1 -1
  99. package/dist/esm/calendar/components/calendarHeader.js.map +1 -1
  100. package/dist/esm/calendar/components/dayPicker.d.ts.map +1 -1
  101. package/dist/esm/calendar/components/dayPicker.js +6 -2
  102. package/dist/esm/calendar/components/dayPicker.js.map +1 -1
  103. package/dist/esm/calendar/components/monthPicker.d.ts.map +1 -1
  104. package/dist/esm/calendar/components/monthPicker.js +1 -1
  105. package/dist/esm/calendar/components/monthPicker.js.map +1 -1
  106. package/dist/esm/calendar/components/timeUnitHeader.d.ts.map +1 -1
  107. package/dist/esm/calendar/components/timeUnitHeader.js +1 -1
  108. package/dist/esm/calendar/components/timeUnitHeader.js.map +1 -1
  109. package/dist/esm/calendar/components/yearPicker.d.ts.map +1 -1
  110. package/dist/esm/calendar/components/yearPicker.js +1 -1
  111. package/dist/esm/calendar/components/yearPicker.js.map +1 -1
  112. package/dist/esm/calendar/hooks/useCalendar.d.ts +1 -1
  113. package/dist/esm/calendar/hooks/useCalendar.d.ts.map +1 -1
  114. package/dist/esm/calendar/hooks/useCalendar.js +22 -16
  115. package/dist/esm/calendar/hooks/useCalendar.js.map +1 -1
  116. package/dist/esm/datePicker/datePicker.js +1 -1
  117. package/dist/esm/datePicker/datePicker.js.map +1 -1
  118. package/dist/esm/footer/footer.d.ts.map +1 -1
  119. package/dist/esm/footer/footer.js +1 -1
  120. package/dist/esm/footer/footer.js.map +1 -1
  121. package/dist/esm/header/loggedInHeader.js +1 -1
  122. package/dist/esm/header/loggedInHeader.js.map +1 -1
  123. package/dist/esm/header/loggedOutHeader.js +1 -1
  124. package/dist/esm/header/loggedOutHeader.js.map +1 -1
  125. package/dist/esm/icons/baseIcons/brand/brandXTwitter.d.ts +4 -0
  126. package/dist/esm/icons/baseIcons/brand/brandXTwitter.d.ts.map +1 -0
  127. package/dist/esm/icons/baseIcons/brand/brandXTwitter.js +5 -0
  128. package/dist/esm/icons/baseIcons/brand/brandXTwitter.js.map +1 -0
  129. package/dist/esm/icons/baseIcons/brand/brandXTwitterSolid.d.ts +4 -0
  130. package/dist/esm/icons/baseIcons/brand/brandXTwitterSolid.d.ts.map +1 -0
  131. package/dist/esm/icons/baseIcons/brand/brandXTwitterSolid.js +5 -0
  132. package/dist/esm/icons/baseIcons/brand/brandXTwitterSolid.js.map +1 -0
  133. package/dist/esm/icons/baseIcons/icons.d.ts +3 -2
  134. package/dist/esm/icons/baseIcons/icons.d.ts.map +1 -1
  135. package/dist/esm/icons/baseIcons/icons.js +5 -4
  136. package/dist/esm/icons/baseIcons/icons.js.map +1 -1
  137. package/dist/esm/icons/baseIcons/types.d.ts +2 -2
  138. package/dist/esm/icons/baseIcons/types.d.ts.map +1 -1
  139. package/dist/esm/icons/baseIcons/ui/uiShield.js +1 -1
  140. package/dist/esm/icons/baseIcons/ui/uiShield.js.map +1 -1
  141. package/dist/esm/icons/baseIcons/ui/uiShieldSolid.d.ts +4 -0
  142. package/dist/esm/icons/baseIcons/ui/uiShieldSolid.d.ts.map +1 -0
  143. package/dist/esm/icons/baseIcons/ui/uiShieldSolid.js +6 -0
  144. package/dist/esm/icons/baseIcons/ui/uiShieldSolid.js.map +1 -0
  145. package/dist/esm/input/consts.d.ts +3 -3
  146. package/dist/esm/input/consts.js +5 -5
  147. package/dist/esm/input/consts.js.map +1 -1
  148. package/dist/esm/input/input.d.ts.map +1 -1
  149. package/dist/esm/input/input.js +6 -0
  150. package/dist/esm/input/input.js.map +1 -1
  151. package/dist/esm/input/inputIcon.d.ts.map +1 -1
  152. package/dist/esm/input/inputIcon.js +1 -3
  153. package/dist/esm/input/inputIcon.js.map +1 -1
  154. package/dist/esm/range/range.js +1 -1
  155. package/dist/esm/range/range.js.map +1 -1
  156. package/dist/esm/select/useSelect.js +1 -1
  157. package/dist/esm/select/useSelect.js.map +1 -1
  158. package/dist/esm/sidemenuV2/SidemenuItemContent.d.ts +14 -0
  159. package/dist/esm/sidemenuV2/SidemenuItemContent.d.ts.map +1 -0
  160. package/dist/esm/sidemenuV2/SidemenuItemContent.js +16 -0
  161. package/dist/esm/sidemenuV2/SidemenuItemContent.js.map +1 -0
  162. package/dist/esm/sidemenuV2/sidemenuItemV2.d.ts.map +1 -1
  163. package/dist/esm/sidemenuV2/sidemenuItemV2.js +22 -17
  164. package/dist/esm/sidemenuV2/sidemenuItemV2.js.map +1 -1
  165. package/dist/esm/sidemenuV2/sidemenuTopV2.d.ts +8 -0
  166. package/dist/esm/sidemenuV2/sidemenuTopV2.d.ts.map +1 -0
  167. package/dist/esm/sidemenuV2/sidemenuTopV2.js +16 -0
  168. package/dist/esm/sidemenuV2/sidemenuTopV2.js.map +1 -0
  169. package/dist/esm/sidemenuV2/sidemenuV2.d.ts +2 -0
  170. package/dist/esm/sidemenuV2/sidemenuV2.d.ts.map +1 -1
  171. package/dist/esm/sidemenuV2/sidemenuV2.js +9 -3
  172. package/dist/esm/sidemenuV2/sidemenuV2.js.map +1 -1
  173. package/dist/esm/sidemenuV2/sidemenuV2.types.d.ts +8 -0
  174. package/dist/esm/sidemenuV2/sidemenuV2.types.d.ts.map +1 -1
  175. package/dist/esm/table/tableSortIcon.d.ts.map +1 -1
  176. package/dist/esm/table/tableSortIcon.js +15 -8
  177. package/dist/esm/table/tableSortIcon.js.map +1 -1
  178. package/dist/esm/tooltip/tooltip.d.ts.map +1 -1
  179. package/dist/esm/tooltip/tooltip.js +2 -2
  180. package/dist/esm/tooltip/tooltip.js.map +1 -1
  181. package/dist/esm/tooltip/tooltip.types.d.ts +1 -0
  182. package/dist/esm/tooltip/tooltip.types.d.ts.map +1 -1
  183. package/dist/esm/tooltip/tooltipContent.js +1 -1
  184. package/dist/esm/tooltip/tooltipContent.js.map +1 -1
  185. package/dist/tsconfig.legacy.tsbuildinfo +1 -1
  186. package/dist/tsconfig.tsbuildinfo +1 -1
  187. package/package.json +2 -2
  188. package/src/button/button.tsx +15 -0
  189. package/src/calendar/calendar.styles.ts +5 -5
  190. package/src/calendar/components/calendarHeader.tsx +1 -1
  191. package/src/calendar/components/dayPicker.tsx +6 -2
  192. package/src/calendar/components/monthPicker.tsx +2 -0
  193. package/src/calendar/components/timeUnitHeader.tsx +33 -5
  194. package/src/calendar/components/yearPicker.tsx +2 -0
  195. package/src/calendar/hooks/useCalendar.ts +18 -21
  196. package/src/datePicker/datePicker.tsx +2 -2
  197. package/src/footer/footer.tsx +8 -2
  198. package/src/header/loggedInHeader.tsx +1 -1
  199. package/src/header/loggedOutHeader.tsx +1 -1
  200. package/src/icons/baseIcons/brand/brandXTwitter.ts +6 -0
  201. package/src/icons/baseIcons/brand/brandXTwitterSolid.ts +6 -0
  202. package/src/icons/baseIcons/icons.ts +5 -4
  203. package/src/icons/baseIcons/types.ts +6 -5
  204. package/src/icons/baseIcons/ui/uiShield.ts +1 -1
  205. package/src/icons/baseIcons/ui/uiShieldSolid.ts +7 -0
  206. package/src/input/consts.ts +5 -5
  207. package/src/input/input.tsx +6 -0
  208. package/src/input/inputIcon.tsx +1 -4
  209. package/src/range/range.tsx +1 -1
  210. package/src/select/useSelect.tsx +1 -1
  211. package/src/sidemenuV2/SidemenuItemContent.tsx +75 -0
  212. package/src/sidemenuV2/sidemenuItemV2.tsx +128 -134
  213. package/src/sidemenuV2/sidemenuTopV2.tsx +28 -0
  214. package/src/sidemenuV2/sidemenuV2.tsx +30 -4
  215. package/src/sidemenuV2/sidemenuV2.types.ts +9 -0
  216. package/src/table/tableSortIcon.tsx +30 -16
  217. package/src/tooltip/tooltip.tsx +2 -1
  218. package/src/tooltip/tooltip.types.ts +1 -0
  219. package/src/tooltip/tooltipContent.tsx +2 -2
@@ -1,93 +1,19 @@
1
1
  import type { MouseEvent } from 'react'
2
- import { useEffect, useMemo, useCallback, memo } from 'react'
2
+ import { useEffect, useMemo, useCallback } from 'react'
3
3
 
4
- import Badge from '../badge'
5
- import type { BadgeProps } from '../badge/badge.types'
6
4
  import Box from '../box'
7
5
  import Button from '../button'
8
6
  import type { VuiComponent } from '../core'
9
7
  import { omitThemingProps, styled, th, vui } from '../core'
10
- import Icon from '../icon'
11
- import type { IconProp } from '../icon'
12
8
  import Popover from '../popover'
13
- import T from '../t'
9
+ import { colors } from '../theme'
10
+ import Tooltip from '../tooltip'
14
11
  import { cs, generateMenuItemId } from '../utils'
15
12
  import { collapsedWidth, expandedWidth } from './consts'
13
+ import SidemenuItemContent from './SidemenuItemContent'
16
14
  import type { SidemenuItemV2Props } from './sidemenuV2.types'
17
15
  import useSidemenuItem from './useSidemenuItem'
18
16
 
19
- // Internal component for sidemenu item content
20
- interface SidemenuItemContentProps {
21
- icon?: IconProp
22
- iconSize?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
23
- title: string
24
- isMenuExpanded?: boolean
25
- isInPopover?: boolean
26
- badge?: Pick<BadgeProps, 'text' | 'variant'>
27
- badgeLinkUrl?: string
28
- }
29
-
30
- const SidemenuItemContent = memo<SidemenuItemContentProps>(
31
- ({ icon, iconSize = 'sm', title, isMenuExpanded, isInPopover, badge, badgeLinkUrl }) => {
32
- // Calculate dynamic margins based on menu state
33
- const iconBaseMarginLeft = 13 / 8 // 1.625rem (13px)
34
- const iconMarginRight = isMenuExpanded
35
- ? 10 / 8 // 1.25rem (10px) when expanded
36
- : 20 / 8 // 2.5rem (20px) when collapsed
37
-
38
- if (isInPopover)
39
- return (
40
- <>
41
- <T isTruncated size="sm" display="inline-block" fontWeight="500" ml={iconBaseMarginLeft}>
42
- {title}
43
- </T>
44
- {badge && typeof badge === 'object' && typeof badge.text === 'string' && badge.text.trim() !== '' && (
45
- <Badge
46
- {...badge}
47
- data-link={btoa(badgeLinkUrl ?? '#')}
48
- variant={badge.variant ?? 'subtleGreen'}
49
- size="sm"
50
- minW="32px"
51
- fontSize="12px"
52
- lineHeight="16px"
53
- ml="10px"
54
- mr="10px"
55
- />
56
- )}
57
- </>
58
- )
59
-
60
- return (
61
- <>
62
- {/* Icon container with responsive margins */}
63
- <Box ml={iconBaseMarginLeft} mr={iconMarginRight} w="20px" transition="margin 0.2s ease-in-out">
64
- {icon && <Icon name={icon} size={iconSize} />}
65
- </Box>
66
-
67
- {/* Menu item title and badge */}
68
- <T isTruncated size="sm" display="inline-block">
69
- {title}
70
- </T>
71
- {badge && typeof badge === 'object' && typeof badge.text === 'string' && badge.text.trim() !== '' && (
72
- <Badge
73
- {...badge}
74
- data-link={btoa(badgeLinkUrl ?? '#')}
75
- variant={badge.variant ?? 'subtleGreen'}
76
- size="sm"
77
- minW="32px"
78
- fontSize="12px"
79
- lineHeight="16px"
80
- ml="10px"
81
- mr="10px"
82
- />
83
- )}
84
- </>
85
- )
86
- },
87
- )
88
-
89
- SidemenuItemContent.displayName = 'SidemenuItemContent'
90
-
91
17
  export const PopoverHovered = styled.div<{ hoverColor: string }>`
92
18
  &:hover .vui-sidemenu-item-popover .vui-button.vui-button {
93
19
  background: ${p => th.color(p.hoverColor)};
@@ -97,6 +23,63 @@ export const PopoverHovered = styled.div<{ hoverColor: string }>`
97
23
  }
98
24
  `
99
25
 
26
+ // SidemenuPopover component extracted from inline Popover logic
27
+ const SidemenuPopover = ({
28
+ isDark,
29
+ className,
30
+ buttonStyles,
31
+ isExactlyActive,
32
+ icon,
33
+ title,
34
+ isMenuExpanded,
35
+ children,
36
+ }: {
37
+ isDark: boolean
38
+ className?: string
39
+ buttonStyles: any
40
+ isExactlyActive: boolean
41
+ icon?: any
42
+ title: string
43
+ isMenuExpanded: boolean
44
+ children: React.ReactNode
45
+ }) => (
46
+ <Popover offset={[0, collapsedWidth - expandedWidth - 2]} placement="right-start" trigger="mouseenter">
47
+ {({ isOpen }: { isOpen: boolean }) => (
48
+ <PopoverHovered hoverColor={isDark ? colors.seaBlue.main : colors.skyBlue.selected}>
49
+ <Popover.Trigger as={Box} className={cs('vui-sidemenu-item-popover', className)}>
50
+ <Button
51
+ {...buttonStyles}
52
+ borderLeft={`3px solid ${isDark ? 'digiGreen.main' : 'seaBlue.main'}`}
53
+ isActive={isExactlyActive}
54
+ className={cs('focusAsBorder')}
55
+ >
56
+ <SidemenuItemContent
57
+ icon={icon}
58
+ iconSize={buttonStyles.iconSize}
59
+ title={title}
60
+ isMenuExpanded={isMenuExpanded}
61
+ />
62
+ </Button>
63
+ </Popover.Trigger>
64
+ <Popover.Content elevation="none" className={cs('vui-sidemenu-item-content', className)}>
65
+ <Box flexDirection="column" justifyContent="start" w="100%">
66
+ <Button
67
+ {...buttonStyles}
68
+ borderLeftColor={'transparent!important'}
69
+ minW={'240px'}
70
+ isActive={isOpen && isExactlyActive}
71
+ className={cs('focusAsBorder')}
72
+ >
73
+ <SidemenuItemContent title={title} isInPopover={true} />
74
+ </Button>
75
+ {children}
76
+ </Box>
77
+ </Popover.Content>
78
+ </PopoverHovered>
79
+ )}
80
+ </Popover>
81
+ )
82
+
100
83
  /** A menu item. */
101
84
  export const SidemenuItemV2 = vui<'button', SidemenuItemV2Props>((props, ref) => {
102
85
  const {
@@ -253,64 +236,75 @@ export const SidemenuItemV2 = vui<'button', SidemenuItemV2Props>((props, ref) =>
253
236
  }
254
237
  }, [isSubmenuOpen, themeValues.buttonVariant])
255
238
 
239
+ // Helper: Render collapsed popover
240
+ const renderPopover = () => (
241
+ <SidemenuPopover
242
+ isDark={isDark}
243
+ className={className}
244
+ buttonStyles={buttonStyles}
245
+ isExactlyActive={isExactlyActive}
246
+ icon={icon}
247
+ title={title}
248
+ isMenuExpanded={isMenuExpanded}
249
+ >
250
+ {children ? children : undefined}
251
+ </SidemenuPopover>
252
+ )
253
+
254
+ // Helper: Render expanded button
255
+ const renderButton = () => {
256
+ if (level === 0 && !isMenuExpanded) {
257
+ return (
258
+ <Tooltip text={title} placement="right" offset={[0, -200]}>
259
+ <Button
260
+ className={cs('vui-sidemenu-item focusAsBorder', isExactlyActive && 'vui-sidemenu-item--active', className)}
261
+ {...buttonStyles}
262
+ isActive={isExactlyActive}
263
+ >
264
+ <SidemenuItemContent icon={icon} iconSize={buttonStyles.iconSize} />
265
+ {isMenuExpanded && computedStates.shouldShowExpandButton && <Button {...expandButtonProps} />}{' '}
266
+ </Button>
267
+ </Tooltip>
268
+ )
269
+ }
270
+
271
+ return (
272
+ <Button
273
+ className={cs('vui-sidemenu-item focusAsBorder', isExactlyActive && 'vui-sidemenu-item--active', className)}
274
+ {...buttonStyles}
275
+ isActive={isExactlyActive}
276
+ title={!isMenuExpanded ? title : undefined}
277
+ >
278
+ <SidemenuItemContent
279
+ icon={icon}
280
+ iconSize={buttonStyles.iconSize}
281
+ title={title}
282
+ isMenuExpanded={isMenuExpanded}
283
+ badge={props.badge}
284
+ badgeLinkUrl={props.badgeLinkUrl}
285
+ />
286
+ {isMenuExpanded && computedStates.shouldShowExpandButton && <Button {...expandButtonProps} />}{' '}
287
+ {/* Expand/Collapse button */}
288
+ </Button>
289
+ )
290
+ // No leftover return, handled above
291
+ }
292
+
293
+ // Helper: Render expanded children
294
+ const renderChildren = () => (
295
+ <Box flexDirection="column" justifyContent="start" w="100%">
296
+ {children}
297
+ </Box>
298
+ )
299
+
300
+ const shouldShowPopover = Boolean(!isMenuExpanded && level === 0 && !!children)
301
+ const shouldShowChildren = computedStates.hasChildrenExpanded
302
+
256
303
  return (
257
304
  <Box flexDirection="column" ref={ref} w="100%" mt={onBottom ? 'auto' : 0} id={computedItemId}>
258
- {!isMenuExpanded && children ? (
259
- <Popover offset={[0, collapsedWidth - expandedWidth - 2]} placement="right-start" trigger="mouseenter">
260
- {({ isOpen }) => (
261
- <PopoverHovered hoverColor={isDark ?'#003591' : '#d3eef8'}>
262
- <Popover.Trigger as={Box} className={cs('vui-sidemenu-item-popover', className)}>
263
- <Button
264
- {...buttonStyles}
265
- borderLeft={`3px solid ${isDark ? 'digiGreen.main' : 'seaBlue.main'}`}
266
- isActive={isExactlyActive}
267
- >
268
- <SidemenuItemContent
269
- icon={icon}
270
- iconSize={buttonStyles.iconSize}
271
- title={title}
272
- isMenuExpanded={isMenuExpanded}
273
- />
274
- </Button>
275
- </Popover.Trigger>
276
- <Popover.Content elevation="none" className={cs('vui-sidemenu-item-content', className)}>
277
- <Box flexDirection="column" justifyContent="start" w="100%">
278
- <Button
279
- {...buttonStyles}
280
- borderLeftColor={'transparent!important'}
281
- minW={'240px'}
282
- isActive={isOpen && isExactlyActive}
283
- >
284
- <SidemenuItemContent title={title} isInPopover={true} />
285
- </Button>
286
- {children}
287
- </Box>
288
- </Popover.Content>
289
- </PopoverHovered>
290
- )}
291
- </Popover>
292
- ) : (
293
- <Button
294
- className={cs('vui-sidemenu-item', isExactlyActive && 'vui-sidemenu-item--active', className)}
295
- {...buttonStyles}
296
- isActive={isExactlyActive}
297
- >
298
- <SidemenuItemContent
299
- icon={icon}
300
- iconSize={buttonStyles.iconSize}
301
- title={title}
302
- isMenuExpanded={isMenuExpanded}
303
- badge={props.badge}
304
- badgeLinkUrl={props.badgeLinkUrl}
305
- />
306
- {computedStates.shouldShowExpandButton && <Button {...expandButtonProps} />} {/* Expand/Collapse button */}
307
- </Button>
308
- )}
309
- {computedStates.hasChildrenExpanded && (
310
- <Box flexDirection="column" justifyContent="start" w="100%">
311
- {children}
312
- </Box>
313
- )}
305
+ {shouldShowPopover && renderPopover()}
306
+ {!shouldShowPopover && renderButton()}
307
+ {shouldShowChildren && renderChildren()}
314
308
  </Box>
315
309
  )
316
310
  }) as VuiComponent<'div', SidemenuItemV2Props>
@@ -0,0 +1,28 @@
1
+ import { Box } from '../box'
2
+ import { omitThemingProps, useStyleConfig } from '../core'
3
+ import { cs } from '../utils'
4
+ import { collapsedWidth } from './consts'
5
+ import type { SidemenuTopPropsV2 } from './sidemenuV2.types'
6
+
7
+ /** Top container. */
8
+ export const SidemenuTopV2 = (props: SidemenuTopPropsV2) => {
9
+ const { className, leftSlot, rightSlot, ...rest } = omitThemingProps(props)
10
+ const styles = useStyleConfig('Sidemenu', props)
11
+
12
+ if (!leftSlot && !rightSlot) return null
13
+
14
+ return (
15
+ <Box className={cs('vui-sidemenu-top', className)} mb={1} w="100%" {...styles.sidemenuTop} {...rest}>
16
+ {!!leftSlot && (
17
+ <Box alignItems="center" className="vui-sidemenu-top-left" minW={collapsedWidth}>
18
+ {leftSlot}
19
+ </Box>
20
+ )}
21
+ {!!rightSlot && <Box className="vui-sidemenu-top-left">{rightSlot}</Box>}
22
+ </Box>
23
+ )
24
+ }
25
+
26
+ SidemenuTopV2.displayName = 'SidemenuTopV2'
27
+
28
+ export default SidemenuTopV2
@@ -9,6 +9,7 @@ import { cs, isActivePath, generateMenuItemId } from '../utils'
9
9
  import { collapsedWidth, expandedWidth } from './consts'
10
10
  import { SidemenuStateProvider, useSidemenuContext } from './context'
11
11
  import SidemenuItemV2 from './sidemenuItemV2'
12
+ import SidemenuTopV2 from './sidemenuTopV2'
12
13
  import type { SidemenuItemV2Props, SidemenuV2Props } from './sidemenuV2.types'
13
14
 
14
15
  // Re-export context provider and hook
@@ -18,9 +19,18 @@ export { SidemenuStateProvider, useSidemenuContext }
18
19
  export const SidemenuV2 = vui<'div', SidemenuV2Props>((props, ref) => {
19
20
  const {
20
21
  isExpandedInitial = true, // Uncontrolled: only affects initial state
22
+ onExpandedChange, // Extract this to prevent it from being passed to DOM
21
23
  size,
22
24
  variant = 'light',
23
- onExpandedChange,
25
+ children,
26
+ className,
27
+ items,
28
+ shouldExpand,
29
+ isSticky,
30
+ width,
31
+ top,
32
+ onNavigate,
33
+ ...restProps // Only DOM-safe props remain
24
34
  } = props
25
35
 
26
36
  return (
@@ -31,11 +41,26 @@ export const SidemenuV2 = vui<'div', SidemenuV2Props>((props, ref) => {
31
41
  size={size}
32
42
  isDark={variant === 'dark'}
33
43
  >
34
- <SidemenuInner {...props} ref={ref} />
44
+ <SidemenuInner
45
+ ref={ref}
46
+ // Only pass DOM-safe props, not onExpandedChange
47
+ children={children}
48
+ className={className}
49
+ items={items}
50
+ shouldExpand={shouldExpand}
51
+ isSticky={isSticky}
52
+ size={size}
53
+ variant={variant}
54
+ width={width}
55
+ top={top}
56
+ onNavigate={onNavigate}
57
+ {...restProps} // Remaining DOM-safe props
58
+ />
35
59
  </SidemenuStateProvider>
36
60
  )
37
61
  }) as VuiComponent<'div', SidemenuV2Props> & {
38
62
  Item: typeof SidemenuItemV2
63
+ Top: typeof SidemenuTopV2
39
64
  }
40
65
 
41
66
  // Inner component that uses context
@@ -264,7 +289,7 @@ const SidemenuInner = vui<'div', SidemenuV2Props>((props, ref) => {
264
289
  )
265
290
 
266
291
  return (
267
- <Box elevation="3" {...containerProps}>
292
+ <Box elevation="1" {...containerProps}>
268
293
  <Box
269
294
  className="vui-sidemenu-content"
270
295
  flexDirection="column"
@@ -292,11 +317,12 @@ const SidemenuInner = vui<'div', SidemenuV2Props>((props, ref) => {
292
317
  </Box>
293
318
  )
294
319
  }) as VuiComponent<'div', SidemenuV2Props> & {
295
- // Top: typeof SidemenuTop
320
+ Top: typeof SidemenuTopV2
296
321
  Item: typeof SidemenuItemV2
297
322
  }
298
323
 
299
324
  SidemenuV2.Item = SidemenuItemV2
325
+ SidemenuV2.Top = SidemenuTopV2
300
326
  SidemenuV2.displayName = 'SidemenuV2'
301
327
 
302
328
  export default SidemenuV2
@@ -313,6 +313,15 @@ export type SidemenuExpandEventV2 = {
313
313
  duration: number
314
314
  }
315
315
 
316
+ export type SidemenuTopPropsV2 = BoxProps & {
317
+ /** Custom class name */
318
+ className?: string
319
+ /** Left slot (always visible) */
320
+ leftSlot?: ReactNode
321
+ /** Right slot (hidden if the sidemenu is collapsed) */
322
+ rightSlot?: ReactNode
323
+ }
324
+
316
325
  // Utility types
317
326
  export type SidemenuItemWithChildrenV2 = SidemenuItemV2Props & {
318
327
  children: SidemenuItemV2Props[]
@@ -1,27 +1,41 @@
1
- import { useStyleConfig, vui } from '../core'
1
+ import Box from '../box'
2
+ import { vui } from '../core'
2
3
  import { Icon } from '../icon'
3
4
  import { cs } from '../utils'
4
- import { useTableContext } from './context'
5
5
  import type { TableSortIconProps } from './table.types'
6
6
 
7
7
  /** Displays a sort icon with given direction based on sort order. */
8
8
  export const TableSortIcon = vui<'svg', TableSortIconProps>((props, ref) => {
9
- const { className, order, ...rest } = props
10
- const styles = useStyleConfig('Table', useTableContext())
11
- const rotate = order === 'asc' ? 180 : 0
12
- const pathFill = order ? ['seaBlue.main', 'sandstone.main'] : 'sandstone.main'
9
+ const { className, order } = props
10
+ const activeColor = 'seaBlue.main'
11
+ const inactiveColor = 'sandstone.85'
12
+
13
+ const icons = [
14
+ {
15
+ color: order === 'asc' ? activeColor : inactiveColor,
16
+ },
17
+ {
18
+ color: order === 'desc' ? activeColor : inactiveColor,
19
+ },
20
+ ]
13
21
 
14
22
  return (
15
- <Icon
16
- className={cs('vui-tableSortIcon', className)}
17
- name="uiSort"
18
- pathFill={pathFill}
19
- ref={ref}
20
- rotate={rotate}
21
- size="xs"
22
- {...styles.tableSortIcon}
23
- {...rest}
24
- />
23
+ <Box ref={ref} column alignItems="center" justifyItems="center" ml="8px">
24
+ <Icon
25
+ className={cs('vui-tableSortIcon--top', className)}
26
+ name={'uiCaretUp'}
27
+ color={icons[0].color}
28
+ size="xs"
29
+ mb="-4px"
30
+ />
31
+ <Icon
32
+ className={cs('vui-tableSortIcon--bottom', className)}
33
+ name={'uiCaretDown'}
34
+ color={icons[1].color}
35
+ size="xs"
36
+ mt="-4px"
37
+ />
38
+ </Box>
25
39
  )
26
40
  })
27
41
 
@@ -26,6 +26,7 @@ export const Tooltip = (props: TooltipProps) => {
26
26
  placement = 'top',
27
27
  disabled = false,
28
28
  visible = false,
29
+ offset = [0, 2],
29
30
  } = props
30
31
 
31
32
  const isDesktop = useUp('md')
@@ -63,7 +64,7 @@ export const Tooltip = (props: TooltipProps) => {
63
64
  )
64
65
  }
65
66
  interactive
66
- offset={[0, 2]}
67
+ offset={offset}
67
68
  placement={placement}
68
69
  popperOptions={{
69
70
  modifiers: [
@@ -32,4 +32,5 @@ export interface TooltipProps extends ChildrenProp {
32
32
  linkProps?: LinkProps
33
33
  /** Keeping the tooltip always visible @default false */
34
34
  visible?: boolean
35
+ offset?: [number, number]
35
36
  }
@@ -21,8 +21,8 @@ export const TooltipContent = ({
21
21
  maxW={maxWidth}
22
22
  overflowY="auto"
23
23
  p={1}
24
- pl={2}
25
- pr={2}
24
+ px={2}
25
+ whiteSpace="pre-wrap"
26
26
  >
27
27
  {children}
28
28
  </Box>