@veracity/vui 2.18.3 → 2.20.0-beta.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 (263) hide show
  1. package/dist/cjs/button/button.d.ts.map +1 -1
  2. package/dist/cjs/button/button.js +3 -2
  3. package/dist/cjs/button/button.js.map +1 -1
  4. package/dist/cjs/checkbox/checkbox.d.ts.map +1 -1
  5. package/dist/cjs/checkbox/checkbox.js +7 -4
  6. package/dist/cjs/checkbox/checkbox.js.map +1 -1
  7. package/dist/cjs/checkbox/consts.d.ts +5 -3
  8. package/dist/cjs/checkbox/consts.d.ts.map +1 -1
  9. package/dist/cjs/checkbox/consts.js +5 -3
  10. package/dist/cjs/checkbox/consts.js.map +1 -1
  11. package/dist/cjs/checkbox/theme.d.ts +2 -2
  12. package/dist/cjs/checkbox/theme.js +1 -1
  13. package/dist/cjs/checkbox/theme.js.map +1 -1
  14. package/dist/cjs/index.d.ts +1 -0
  15. package/dist/cjs/index.d.ts.map +1 -1
  16. package/dist/cjs/index.js +1 -0
  17. package/dist/cjs/index.js.map +1 -1
  18. package/dist/cjs/input/consts.d.ts +27 -21
  19. package/dist/cjs/input/consts.d.ts.map +1 -1
  20. package/dist/cjs/input/consts.js +8 -2
  21. package/dist/cjs/input/consts.js.map +1 -1
  22. package/dist/cjs/input/helpText.d.ts +1 -1
  23. package/dist/cjs/input/helpText.d.ts.map +1 -1
  24. package/dist/cjs/input/helpText.js +2 -2
  25. package/dist/cjs/input/helpText.js.map +1 -1
  26. package/dist/cjs/input/input.d.ts.map +1 -1
  27. package/dist/cjs/input/input.js +22 -18
  28. package/dist/cjs/input/input.js.map +1 -1
  29. package/dist/cjs/input/input.types.d.ts +7 -3
  30. package/dist/cjs/input/input.types.d.ts.map +1 -1
  31. package/dist/cjs/input/inputInput.js +3 -2
  32. package/dist/cjs/input/inputInput.js.map +1 -1
  33. package/dist/cjs/input/theme.d.ts +20 -8
  34. package/dist/cjs/input/theme.d.ts.map +1 -1
  35. package/dist/cjs/input/theme.js +14 -2
  36. package/dist/cjs/input/theme.js.map +1 -1
  37. package/dist/cjs/label/index.d.ts +4 -0
  38. package/dist/cjs/label/index.d.ts.map +1 -0
  39. package/dist/cjs/label/index.js +25 -0
  40. package/dist/cjs/label/index.js.map +1 -0
  41. package/dist/cjs/label/label.d.ts +6 -0
  42. package/dist/cjs/label/label.d.ts.map +1 -0
  43. package/dist/cjs/label/label.js +41 -0
  44. package/dist/cjs/label/label.js.map +1 -0
  45. package/dist/cjs/label/label.types.d.ts +7 -0
  46. package/dist/cjs/label/label.types.d.ts.map +1 -0
  47. package/dist/cjs/label/label.types.js +3 -0
  48. package/dist/cjs/label/label.types.js.map +1 -0
  49. package/dist/cjs/label/theme.d.ts +23 -0
  50. package/dist/cjs/label/theme.d.ts.map +1 -0
  51. package/dist/cjs/label/theme.js +28 -0
  52. package/dist/cjs/label/theme.js.map +1 -0
  53. package/dist/cjs/list/list.d.ts.map +1 -1
  54. package/dist/cjs/list/list.js +64 -2
  55. package/dist/cjs/list/list.js.map +1 -1
  56. package/dist/cjs/menu/menuItem.d.ts.map +1 -1
  57. package/dist/cjs/menu/menuItem.js +1 -1
  58. package/dist/cjs/menu/menuItem.js.map +1 -1
  59. package/dist/cjs/menu/menuList.d.ts.map +1 -1
  60. package/dist/cjs/menu/menuList.js +1 -1
  61. package/dist/cjs/menu/menuList.js.map +1 -1
  62. package/dist/cjs/radio/consts.d.ts +5 -3
  63. package/dist/cjs/radio/consts.d.ts.map +1 -1
  64. package/dist/cjs/radio/consts.js +5 -3
  65. package/dist/cjs/radio/consts.js.map +1 -1
  66. package/dist/cjs/radio/radio.d.ts.map +1 -1
  67. package/dist/cjs/radio/radio.js +6 -2
  68. package/dist/cjs/radio/radio.js.map +1 -1
  69. package/dist/cjs/radio/theme.d.ts +2 -2
  70. package/dist/cjs/radio/theme.js +1 -1
  71. package/dist/cjs/radio/theme.js.map +1 -1
  72. package/dist/cjs/select/select.d.ts +11 -6
  73. package/dist/cjs/select/select.d.ts.map +1 -1
  74. package/dist/cjs/select/select.js +9 -2
  75. package/dist/cjs/select/select.js.map +1 -1
  76. package/dist/cjs/select/select.types.d.ts +8 -0
  77. package/dist/cjs/select/select.types.d.ts.map +1 -1
  78. package/dist/cjs/select/selectButton.d.ts.map +1 -1
  79. package/dist/cjs/select/selectButton.js +16 -5
  80. package/dist/cjs/select/selectButton.js.map +1 -1
  81. package/dist/cjs/select/selectGroup.js +1 -1
  82. package/dist/cjs/select/selectGroup.js.map +1 -1
  83. package/dist/cjs/select/selectOption.js +1 -1
  84. package/dist/cjs/select/selectOption.js.map +1 -1
  85. package/dist/cjs/select/theme.d.ts +32 -0
  86. package/dist/cjs/select/theme.d.ts.map +1 -1
  87. package/dist/cjs/select/theme.js +33 -1
  88. package/dist/cjs/select/theme.js.map +1 -1
  89. package/dist/cjs/switch/switchLabel.d.ts.map +1 -1
  90. package/dist/cjs/switch/switchLabel.js +4 -0
  91. package/dist/cjs/switch/switchLabel.js.map +1 -1
  92. package/dist/cjs/switch/theme.d.ts +17 -0
  93. package/dist/cjs/switch/theme.d.ts.map +1 -1
  94. package/dist/cjs/switch/theme.js +18 -0
  95. package/dist/cjs/switch/theme.js.map +1 -1
  96. package/dist/cjs/tabs/tabsNavBar.d.ts.map +1 -1
  97. package/dist/cjs/tabs/tabsNavBar.js +5 -1
  98. package/dist/cjs/tabs/tabsNavBar.js.map +1 -1
  99. package/dist/cjs/textarea/textarea.d.ts +1 -1
  100. package/dist/cjs/textarea/textarea.d.ts.map +1 -1
  101. package/dist/cjs/textarea/textarea.js +23 -17
  102. package/dist/cjs/textarea/textarea.js.map +1 -1
  103. package/dist/cjs/textarea/textarea.types.d.ts +8 -0
  104. package/dist/cjs/textarea/textarea.types.d.ts.map +1 -1
  105. package/dist/cjs/textarea/theme.d.ts +8 -8
  106. package/dist/cjs/textarea/theme.js +2 -2
  107. package/dist/cjs/textarea/theme.js.map +1 -1
  108. package/dist/cjs/theme/components.d.ts +101 -20
  109. package/dist/cjs/theme/components.d.ts.map +1 -1
  110. package/dist/cjs/theme/components.js +56 -54
  111. package/dist/cjs/theme/components.js.map +1 -1
  112. package/dist/cjs/theme/defaultTheme.d.ts +101 -20
  113. package/dist/cjs/theme/defaultTheme.d.ts.map +1 -1
  114. package/dist/esm/button/button.d.ts.map +1 -1
  115. package/dist/esm/button/button.js +3 -2
  116. package/dist/esm/button/button.js.map +1 -1
  117. package/dist/esm/checkbox/checkbox.d.ts.map +1 -1
  118. package/dist/esm/checkbox/checkbox.js +7 -4
  119. package/dist/esm/checkbox/checkbox.js.map +1 -1
  120. package/dist/esm/checkbox/consts.d.ts +5 -3
  121. package/dist/esm/checkbox/consts.d.ts.map +1 -1
  122. package/dist/esm/checkbox/consts.js +5 -3
  123. package/dist/esm/checkbox/consts.js.map +1 -1
  124. package/dist/esm/checkbox/theme.d.ts +2 -2
  125. package/dist/esm/checkbox/theme.js +1 -1
  126. package/dist/esm/checkbox/theme.js.map +1 -1
  127. package/dist/esm/index.d.ts +1 -0
  128. package/dist/esm/index.d.ts.map +1 -1
  129. package/dist/esm/index.js +1 -0
  130. package/dist/esm/index.js.map +1 -1
  131. package/dist/esm/input/consts.d.ts +27 -21
  132. package/dist/esm/input/consts.d.ts.map +1 -1
  133. package/dist/esm/input/consts.js +7 -1
  134. package/dist/esm/input/consts.js.map +1 -1
  135. package/dist/esm/input/helpText.d.ts +1 -1
  136. package/dist/esm/input/helpText.d.ts.map +1 -1
  137. package/dist/esm/input/helpText.js +2 -2
  138. package/dist/esm/input/helpText.js.map +1 -1
  139. package/dist/esm/input/input.d.ts.map +1 -1
  140. package/dist/esm/input/input.js +25 -21
  141. package/dist/esm/input/input.js.map +1 -1
  142. package/dist/esm/input/input.types.d.ts +7 -3
  143. package/dist/esm/input/input.types.d.ts.map +1 -1
  144. package/dist/esm/input/inputInput.js +3 -2
  145. package/dist/esm/input/inputInput.js.map +1 -1
  146. package/dist/esm/input/theme.d.ts +20 -8
  147. package/dist/esm/input/theme.d.ts.map +1 -1
  148. package/dist/esm/input/theme.js +14 -2
  149. package/dist/esm/input/theme.js.map +1 -1
  150. package/dist/esm/label/index.d.ts +4 -0
  151. package/dist/esm/label/index.d.ts.map +1 -0
  152. package/dist/esm/label/index.js +4 -0
  153. package/dist/esm/label/index.js.map +1 -0
  154. package/dist/esm/label/label.d.ts +6 -0
  155. package/dist/esm/label/label.d.ts.map +1 -0
  156. package/dist/esm/label/label.js +24 -0
  157. package/dist/esm/label/label.js.map +1 -0
  158. package/dist/esm/label/label.types.d.ts +7 -0
  159. package/dist/esm/label/label.types.d.ts.map +1 -0
  160. package/dist/esm/label/label.types.js +2 -0
  161. package/dist/esm/label/label.types.js.map +1 -0
  162. package/dist/esm/label/theme.d.ts +23 -0
  163. package/dist/esm/label/theme.d.ts.map +1 -0
  164. package/dist/esm/label/theme.js +26 -0
  165. package/dist/esm/label/theme.js.map +1 -0
  166. package/dist/esm/list/list.d.ts.map +1 -1
  167. package/dist/esm/list/list.js +40 -2
  168. package/dist/esm/list/list.js.map +1 -1
  169. package/dist/esm/menu/menuItem.d.ts.map +1 -1
  170. package/dist/esm/menu/menuItem.js +1 -1
  171. package/dist/esm/menu/menuItem.js.map +1 -1
  172. package/dist/esm/menu/menuList.d.ts.map +1 -1
  173. package/dist/esm/menu/menuList.js +1 -1
  174. package/dist/esm/menu/menuList.js.map +1 -1
  175. package/dist/esm/radio/consts.d.ts +5 -3
  176. package/dist/esm/radio/consts.d.ts.map +1 -1
  177. package/dist/esm/radio/consts.js +5 -3
  178. package/dist/esm/radio/consts.js.map +1 -1
  179. package/dist/esm/radio/radio.d.ts.map +1 -1
  180. package/dist/esm/radio/radio.js +6 -2
  181. package/dist/esm/radio/radio.js.map +1 -1
  182. package/dist/esm/radio/theme.d.ts +2 -2
  183. package/dist/esm/radio/theme.js +1 -1
  184. package/dist/esm/radio/theme.js.map +1 -1
  185. package/dist/esm/select/select.d.ts +11 -6
  186. package/dist/esm/select/select.d.ts.map +1 -1
  187. package/dist/esm/select/select.js +13 -6
  188. package/dist/esm/select/select.js.map +1 -1
  189. package/dist/esm/select/select.types.d.ts +8 -0
  190. package/dist/esm/select/select.types.d.ts.map +1 -1
  191. package/dist/esm/select/selectButton.d.ts.map +1 -1
  192. package/dist/esm/select/selectButton.js +16 -5
  193. package/dist/esm/select/selectButton.js.map +1 -1
  194. package/dist/esm/select/selectGroup.js +1 -1
  195. package/dist/esm/select/selectGroup.js.map +1 -1
  196. package/dist/esm/select/selectOption.js +2 -2
  197. package/dist/esm/select/selectOption.js.map +1 -1
  198. package/dist/esm/select/theme.d.ts +32 -0
  199. package/dist/esm/select/theme.d.ts.map +1 -1
  200. package/dist/esm/select/theme.js +33 -1
  201. package/dist/esm/select/theme.js.map +1 -1
  202. package/dist/esm/switch/switchLabel.d.ts.map +1 -1
  203. package/dist/esm/switch/switchLabel.js +4 -0
  204. package/dist/esm/switch/switchLabel.js.map +1 -1
  205. package/dist/esm/switch/theme.d.ts +17 -0
  206. package/dist/esm/switch/theme.d.ts.map +1 -1
  207. package/dist/esm/switch/theme.js +18 -0
  208. package/dist/esm/switch/theme.js.map +1 -1
  209. package/dist/esm/tabs/tabsNavBar.d.ts.map +1 -1
  210. package/dist/esm/tabs/tabsNavBar.js +4 -1
  211. package/dist/esm/tabs/tabsNavBar.js.map +1 -1
  212. package/dist/esm/textarea/textarea.d.ts +1 -1
  213. package/dist/esm/textarea/textarea.d.ts.map +1 -1
  214. package/dist/esm/textarea/textarea.js +27 -21
  215. package/dist/esm/textarea/textarea.js.map +1 -1
  216. package/dist/esm/textarea/textarea.types.d.ts +8 -0
  217. package/dist/esm/textarea/textarea.types.d.ts.map +1 -1
  218. package/dist/esm/textarea/theme.d.ts +8 -8
  219. package/dist/esm/textarea/theme.js +2 -2
  220. package/dist/esm/textarea/theme.js.map +1 -1
  221. package/dist/esm/theme/components.d.ts +101 -20
  222. package/dist/esm/theme/components.d.ts.map +1 -1
  223. package/dist/esm/theme/components.js +2 -0
  224. package/dist/esm/theme/components.js.map +1 -1
  225. package/dist/esm/theme/defaultTheme.d.ts +101 -20
  226. package/dist/esm/theme/defaultTheme.d.ts.map +1 -1
  227. package/dist/tsconfig.legacy.tsbuildinfo +1 -1
  228. package/dist/tsconfig.tsbuildinfo +1 -1
  229. package/package.json +1 -1
  230. package/src/button/button.tsx +11 -6
  231. package/src/checkbox/checkbox.tsx +7 -5
  232. package/src/checkbox/consts.ts +6 -4
  233. package/src/checkbox/theme.ts +1 -1
  234. package/src/index.ts +1 -0
  235. package/src/input/consts.ts +12 -5
  236. package/src/input/helpText.tsx +2 -2
  237. package/src/input/input.tsx +90 -67
  238. package/src/input/input.types.ts +7 -4
  239. package/src/input/inputInput.tsx +2 -2
  240. package/src/input/theme.ts +14 -2
  241. package/src/label/index.ts +3 -0
  242. package/src/label/label.tsx +31 -0
  243. package/src/label/label.types.ts +8 -0
  244. package/src/label/theme.ts +29 -0
  245. package/src/list/list.tsx +44 -3
  246. package/src/menu/menuItem.tsx +1 -10
  247. package/src/menu/menuList.tsx +1 -0
  248. package/src/radio/consts.ts +6 -4
  249. package/src/radio/radio.tsx +5 -3
  250. package/src/radio/theme.ts +1 -1
  251. package/src/select/select.tsx +30 -5
  252. package/src/select/select.types.ts +8 -0
  253. package/src/select/selectButton.tsx +18 -5
  254. package/src/select/selectGroup.tsx +1 -1
  255. package/src/select/selectOption.tsx +2 -2
  256. package/src/select/theme.ts +33 -1
  257. package/src/switch/switchLabel.tsx +5 -0
  258. package/src/switch/theme.ts +21 -0
  259. package/src/tabs/tabsNavBar.tsx +4 -1
  260. package/src/textarea/textarea.tsx +78 -45
  261. package/src/textarea/textarea.types.ts +8 -0
  262. package/src/textarea/theme.ts +2 -2
  263. package/src/theme/components.ts +2 -0
@@ -18,16 +18,7 @@ export const MenuItem = vui<'li', ListItemProps>((props, ref) => {
18
18
  closeOnSelect && instance?.hide()
19
19
  })
20
20
 
21
- return (
22
- <ListItem
23
- className={cs('vui-menuItem', className)}
24
- isInteractive
25
- onClick={onClick}
26
- ref={ref}
27
- {...styles.item}
28
- {...rest}
29
- />
30
- )
21
+ return <ListItem className={cs('vui-menuItem', className)} onClick={onClick} ref={ref} {...styles.item} {...rest} />
31
22
  })
32
23
 
33
24
  MenuItem.displayName = 'MenuItem'
@@ -20,6 +20,7 @@ export const MenuList = vui<'ul', MenuListProps>((props, ref) => {
20
20
  {slotTop}
21
21
  <List
22
22
  className={cs('vui-menuList', className)}
23
+ isInteractive
23
24
  py={1}
24
25
  ref={ref}
25
26
  w="100%"
@@ -1,5 +1,7 @@
1
1
  export const radioColors = {
2
- main: 'seaBlue.main',
3
- hover: 'seaBlue.40',
4
- disabled: 'sandstone.main',
5
- }
2
+ unchecked: 'sandstone.60',
3
+ checked: 'seaBlue.28',
4
+ hover: 'seaBlue.20',
5
+ focus: 'seaBlue.35',
6
+ disabled: 'sandstone.90',
7
+ } as const
@@ -39,6 +39,10 @@ export const RadioBase = styled.labelBox<RadioStyleProps>`
39
39
  color: ${p => th.color(p.controlHoverColor)};
40
40
  }
41
41
 
42
+ .vui-radioControl:focus-within {
43
+ color: ${radioColors.focus};
44
+ }
45
+
42
46
  &[aria-disabled='true'] {
43
47
  color: ${radioColors.disabled};
44
48
  cursor: not-allowed;
@@ -89,7 +93,7 @@ export const Radio = vui<'span', RadioProps>((props, ref) => {
89
93
 
90
94
  const icon = isChecked ? iconChecked : iconProp
91
95
  const controlMr = children || label ? 1 : 0
92
- const color = controlColor ? controlColor : radioColors.main
96
+ const color = isChecked ? radioColors.checked : controlColor
93
97
  const controlHoverColor = hoverColor ? hoverColor : radioColors.hover
94
98
 
95
99
  useEffect(() => {
@@ -128,7 +132,6 @@ export const Radio = vui<'span', RadioProps>((props, ref) => {
128
132
  >
129
133
  {checked !== undefined && (
130
134
  <RadioInput
131
- aria-label="input-radio"
132
135
  className="vui-radioInput"
133
136
  onChange={handleOnChange}
134
137
  ref={inputRef}
@@ -140,7 +143,6 @@ export const Radio = vui<'span', RadioProps>((props, ref) => {
140
143
 
141
144
  {checked === undefined && (
142
145
  <RadioInput
143
- aria-label="input-radio"
144
146
  className="vui-radioInput"
145
147
  onChange={handleOnChange}
146
148
  ref={inputRef}
@@ -2,7 +2,7 @@ import { radioColors } from './consts'
2
2
 
3
3
  const baseStyle = {
4
4
  control: {
5
- color: radioColors.main,
5
+ color: radioColors.unchecked,
6
6
  hoverColor: radioColors.hover,
7
7
  },
8
8
  }
@@ -1,10 +1,14 @@
1
- import React, { useEffect, useState } from 'react'
1
+ import { useEffect, useId, useState } from 'react'
2
2
 
3
3
  import { Box } from '../box'
4
+ import { useStyleConfig } from '../core'
4
5
  import { Input } from '../input'
6
+ import { helpTextSize } from '../input/consts'
7
+ import HelpText from '../input/helpText'
8
+ import Label from '../label'
5
9
  import { Popover } from '../popover'
6
- import { __DEV__ } from '../utils'
7
- import { SelectProvider } from './context'
10
+ import { __DEV__, isString } from '../utils'
11
+ import { SelectProvider, useSelectContext } from './context'
8
12
  import { SelectOptionData, SelectProps } from './select.types'
9
13
  import SelectButton from './selectButton'
10
14
  import SelectContent from './selectContent'
@@ -22,8 +26,12 @@ export function Select(props: SelectProps) {
22
26
  children,
23
27
  defaultValue,
24
28
  disabled,
29
+ errorText,
30
+ helpText,
31
+ id: idProp,
25
32
  isInvalid,
26
33
  isMultiple,
34
+ label,
27
35
  maxHeight,
28
36
  name,
29
37
  onChange,
@@ -33,7 +41,7 @@ export function Select(props: SelectProps) {
33
41
  selectButton,
34
42
  selectButtonProps,
35
43
  showOptionsFilter,
36
- size,
44
+ size = 'lg',
37
45
  value,
38
46
  variant,
39
47
  ...rest
@@ -45,9 +53,13 @@ export function Select(props: SelectProps) {
45
53
  console.error('<Select /> is used with isMultiple but its value is not an array: ', value)
46
54
  }
47
55
 
56
+ const generatedId = useId()
57
+ const styles = useStyleConfig('Select', useSelectContext())
48
58
  const [query, setQuery] = useState<string>('')
49
59
  const [filteredOptions, setFilteredOptions] = useState(options)
50
60
 
61
+ const id = idProp || generatedId
62
+
51
63
  const context = {
52
64
  disabled,
53
65
  isInvalid,
@@ -73,6 +85,13 @@ export function Select(props: SelectProps) {
73
85
 
74
86
  return (
75
87
  <SelectProvider value={context}>
88
+ {isString(label) ? (
89
+ <Label aria-disabled={disabled} className="vui-input-label" htmlFor={id} mb={0.5} {...styles.label}>
90
+ {label}
91
+ </Label>
92
+ ) : (
93
+ label
94
+ )}
76
95
  <Popover matchWidth {...rest}>
77
96
  <>
78
97
  {selectButton ?? <SelectButton {...selectButtonProps} />}
@@ -85,7 +104,7 @@ export function Select(props: SelectProps) {
85
104
  mt={0}
86
105
  onChange={onQueryChange}
87
106
  placeholder="Filter…"
88
- size="sm"
107
+ size={size}
89
108
  value={query}
90
109
  />
91
110
  </Box>
@@ -97,6 +116,12 @@ export function Select(props: SelectProps) {
97
116
  </SelectContent>
98
117
  </>
99
118
  </Popover>
119
+ {!!helpText && <HelpText size={helpTextSize[size]}>{helpText}</HelpText>}
120
+ {!!errorText && (
121
+ <HelpText isError size={helpTextSize[size]}>
122
+ {errorText}
123
+ </HelpText>
124
+ )}
100
125
  </SelectProvider>
101
126
  )
102
127
  }
@@ -24,12 +24,20 @@ export type SelectProps = ThemingProps<'Select'> &
24
24
  UseSelectProps & {
25
25
  /** Select cannot be opened and is styled accordingly. */
26
26
  disabled?: boolean
27
+ /** Socket displaying error text below an input. */
28
+ errorText?: string | React.ReactNode
29
+ /** Socket displaying help text below an input. */
30
+ helpText?: React.ReactNode | string
31
+ /** Unique identifier */
32
+ id?: string
27
33
  /** Represents invalid form input and is styled accordingly. */
28
34
  isInvalid?: boolean
29
35
  /** Maximum container height in px. */
30
36
  maxHeight?: number
31
37
  /** Name of the input. Used in custom change event to support form library integration. */
32
38
  name?: string
39
+ /** The label. */
40
+ label?: string | React.ReactNode
33
41
  /** Data prop to display an array of options in the popover. */
34
42
  options?: SelectOptionData[]
35
43
  /** Displayed inside the trigger when no value is selected. */
@@ -18,8 +18,18 @@ export const SelectButton = vui<'button', SelectButtonProps>((props, ref) => {
18
18
  const styles = useStyleConfig('Select', useSelectContext())
19
19
 
20
20
  const text = valueText || placeholder
21
- const textColor = disabled ? 'sandstone.10' : !valueText ? 'sandstone.10' : undefined
22
- const iconColor = disabled ? 'sandstone.10' : 'seaBlue.main'
21
+
22
+ const disabledProps = disabled
23
+ ? {
24
+ activeBg: 'sandstone.79',
25
+ cursor: 'not-allowed',
26
+ backgroundColor: 'sandstone.79',
27
+ borderColor: 'sandstone.79',
28
+ hoverBg: 'sandstone.79',
29
+ hoverBorderColor: 'sandstone.79',
30
+ activeBorderColor: 'sandstone.79',
31
+ }
32
+ : undefined
23
33
 
24
34
  const readOnlyProps = readOnly
25
35
  ? {
@@ -31,14 +41,17 @@ export const SelectButton = vui<'button', SelectButtonProps>((props, ref) => {
31
41
  hoverBg: 'sandstone.95',
32
42
  opacity: 1,
33
43
  }
34
- : {}
44
+ : undefined
35
45
 
36
46
  const isInvalidProps = isInvalid
37
47
  ? {
38
48
  borderColor: 'energyRed.45',
39
49
  hoverBorderColor: 'energyRed.45',
40
50
  }
41
- : {}
51
+ : undefined
52
+
53
+ const textColor = valueText ? undefined : 'sandstone.10'
54
+ const iconColor = disabled ? 'sandstone.10' : 'seaBlue.main'
42
55
 
43
56
  return (
44
57
  <PopoverTrigger
@@ -59,6 +72,7 @@ export const SelectButton = vui<'button', SelectButtonProps>((props, ref) => {
59
72
  }
60
73
  userSelect="text"
61
74
  {...styles.button}
75
+ {...disabledProps}
62
76
  {...readOnlyProps}
63
77
  {...isInvalidProps}
64
78
  {...rest}
@@ -67,5 +81,4 @@ export const SelectButton = vui<'button', SelectButtonProps>((props, ref) => {
67
81
  })
68
82
 
69
83
  SelectButton.displayName = 'SelectButton'
70
-
71
84
  export default SelectButton
@@ -11,7 +11,7 @@ export const SelectGroup = vui<'ul', SelectGroupProps>((props, ref) => {
11
11
  const { className, ...rest } = props
12
12
  const styles = useStyleConfig('Select', useSelectContext())
13
13
 
14
- return <List className={cs('vui-selectGroup', className)} ref={ref} size="sm" {...styles.group} {...rest} />
14
+ return <List className={cs('vui-selectGroup', className)} ref={ref} {...styles.group} {...rest} />
15
15
  }) as VuiComponent<'ul', SelectGroupProps> & {
16
16
  Divider: typeof ListDivider
17
17
  Heading: typeof ListHeading
@@ -50,14 +50,14 @@ export const SelectOption = vui<'li', SelectOptionProps>((props, ref) => {
50
50
  selectedBg="skyBlue.selected"
51
51
  title={title}
52
52
  value={valueProp}
53
- {...styles.item}
53
+ {...styles.option}
54
54
  {...rest}
55
55
  {...ellipsisOverflow}
56
56
  >
57
57
  {children ??
58
58
  (isMultiple && (
59
59
  <>
60
- <Checkbox checked={isSelected} disabled={disabled} mr={1} />
60
+ <Checkbox checked={isSelected} disabled={disabled} mr={1} {...styles.option} />
61
61
  <List.Text>{props.text}</List.Text>
62
62
  </>
63
63
  ))}
@@ -5,18 +5,50 @@ const defaultProps = {
5
5
  variant: 'outlined',
6
6
  }
7
7
 
8
- const parts = ['container', 'button', 'content', 'group', 'option']
8
+ const parts = ['container', 'button', 'content', 'group', 'option', 'label']
9
9
 
10
10
  const sizes = {
11
11
  sm: {
12
12
  button: {
13
13
  size: 'sm',
14
14
  },
15
+ group: {
16
+ size: 'sm',
17
+ },
18
+ option: {
19
+ size: 'sm',
20
+ },
21
+ label: {
22
+ fontSize: 'sm',
23
+ },
15
24
  },
16
25
  md: {
17
26
  button: {
18
27
  size: 'md',
19
28
  },
29
+ group: {
30
+ size: 'md',
31
+ },
32
+ option: {
33
+ size: 'md',
34
+ },
35
+ label: {
36
+ fontSize: 'md',
37
+ },
38
+ },
39
+ lg: {
40
+ button: {
41
+ size: 'lg',
42
+ },
43
+ group: {
44
+ size: 'lg',
45
+ },
46
+ option: {
47
+ size: 'lg',
48
+ },
49
+ label: {
50
+ fontSize: 'lg',
51
+ },
20
52
  },
21
53
  }
22
54
 
@@ -10,6 +10,11 @@ export const SwitchLabel = vui<'span', TProps>((props, ref) => {
10
10
  const { className, ...rest } = props
11
11
  const styles = useStyleConfig('Switch', useSwitchContext())
12
12
 
13
+ // <T> has xs but not xl
14
+ if (styles.label.size === 'xl') {
15
+ rest.fontSize = 20
16
+ }
17
+
13
18
  return <T className={cs('vui-switchLabel', className)} display="flex" ref={ref} {...styles.label} {...rest} />
14
19
  })
15
20
 
@@ -11,6 +11,26 @@ const baseStyle = {
11
11
  },
12
12
  }
13
13
 
14
+ function sizeXl() {
15
+ const button = {
16
+ fontSize: 'lg',
17
+ minW: 58,
18
+ thumb: {
19
+ h: 28,
20
+ w: 28,
21
+ },
22
+ track: {
23
+ h: 32,
24
+ },
25
+ }
26
+
27
+ const label = {
28
+ size: 'xl',
29
+ }
30
+
31
+ return { button, label }
32
+ }
33
+
14
34
  function sizeLg() {
15
35
  const button = {
16
36
  fontSize: 'md',
@@ -82,6 +102,7 @@ const sizes = {
82
102
  sm: sizeSm,
83
103
  md: sizeMd,
84
104
  lg: sizeLg,
105
+ xl: sizeXl,
85
106
  }
86
107
 
87
108
  const variants = {
@@ -66,7 +66,10 @@ export const TabsNavBar = vui<'div', TabNavBarProps>((props, ref) => {
66
66
  hoverColor="seaBlue.main"
67
67
  isRound={false}
68
68
  ml={1}
69
- onClick={e => tab?.onDelete?.(e)}
69
+ onClick={e => {
70
+ e.stopPropagation()
71
+ tab?.onDelete?.(e)
72
+ }}
70
73
  title="Delete"
71
74
  />
72
75
  )}
@@ -1,9 +1,12 @@
1
- import React, { useEffect, useState } from 'react'
1
+ import { useEffect, useId, useState } from 'react'
2
2
 
3
+ import { Label } from '..'
3
4
  import { omitThemingProps, styled, useStyleConfig, vui } from '../core'
4
- import { inputColors } from '../input/consts'
5
+ import { helpTextSize, inputColors } from '../input/consts'
6
+ import HelpText from '../input/helpText'
7
+ import label from '../label'
5
8
  import T from '../t'
6
- import { ChangeEvent, cs, filterUndefined } from '../utils'
9
+ import { ChangeEvent, cs, filterUndefined, isString } from '../utils'
7
10
  import { getInitialCount } from './helpers'
8
11
  import { TextareaProps } from './textarea.types'
9
12
 
@@ -13,6 +16,7 @@ const TextareaTextarea = styled.textareaBox`
13
16
  outline: none;
14
17
  padding: 1;
15
18
  resize: none;
19
+ min-height: 80px;
16
20
  transition-duration: fast;
17
21
  width: 100%;
18
22
 
@@ -26,7 +30,7 @@ const TextareaTextarea = styled.textareaBox`
26
30
 
27
31
  export const TextareaBase = styled.divBox`
28
32
  display: flex;
29
- min-height: 80px;
33
+ flex-direction: column;
30
34
  position: relative;
31
35
  width: 100%;
32
36
  `
@@ -38,12 +42,16 @@ export const TextareaBase = styled.divBox`
38
42
  export const Textarea = vui<'div', TextareaProps>((props, ref) => {
39
43
  const {
40
44
  autoFocus,
45
+ ariaLabel,
41
46
  className,
42
47
  colorScheme: colorSchemeProp,
43
48
  cols,
44
49
  defaultValue,
45
50
  disabled,
46
- id,
51
+ errorText,
52
+ id: idProp,
53
+ helpText,
54
+ label,
47
55
  maxLength,
48
56
  name,
49
57
  onBlur,
@@ -61,9 +69,12 @@ export const Textarea = vui<'div', TextareaProps>((props, ref) => {
61
69
  ...rest
62
70
  } = omitThemingProps(props)
63
71
 
72
+ const generatedId = useId()
64
73
  const [count, setCount] = useState(getInitialCount(props))
65
74
  const [valueInternal, setValueInternal] = useState(defaultValue)
66
75
 
76
+ const id = idProp || generatedId
77
+
67
78
  const styles = useStyleConfig('Textarea', props)
68
79
 
69
80
  function onChange(e: ChangeEvent<HTMLTextAreaElement>) {
@@ -78,6 +89,7 @@ export const Textarea = vui<'div', TextareaProps>((props, ref) => {
78
89
 
79
90
  const textareaAliasedProps = filterUndefined({
80
91
  'aria-disabled': disabled,
92
+ 'aria-label': ariaLabel,
81
93
  bg: readOnly ? 'sandstone.97' : undefined,
82
94
  borderColor: readOnly ? 'sandstone.55' : undefined,
83
95
  focusWithinBorderColor: !readOnly ? 'transparent' : undefined,
@@ -90,47 +102,68 @@ export const Textarea = vui<'div', TextareaProps>((props, ref) => {
90
102
  }, [value])
91
103
 
92
104
  return (
93
- <TextareaBase className={cs('vui-textarea', className)} ref={ref} {...styles.container} {...aliasedProps} {...rest}>
94
- <TextareaTextarea
95
- aria-label="input-textarea"
96
- className="vui-textareaTextarea"
97
- ref={textareaRef}
98
- {...{
99
- autoFocus,
100
- cols,
101
- defaultValue,
102
- disabled,
103
- id,
104
- maxLength,
105
- name,
106
- onBlur,
107
- onChange,
108
- onFocus,
109
- placeholder,
110
- readOnly,
111
- required,
112
- resize,
113
- rows,
114
- }}
115
- value={valueInternal}
116
- {...styles.textarea}
117
- {...textareaAliasedProps}
118
- {...textareaProps}
119
- />
120
-
121
- {showCount && (
122
- <T
123
- className="vui-textareaCount"
124
- color={maxLength && count > maxLength ? inputColors.error : inputColors.helpText}
125
- position="absolute"
126
- right={0}
127
- size="sm"
128
- top="calc(100% + 1px)"
129
- >
130
- {count} {maxLength ? `/ ${maxLength}` : null}
131
- </T>
105
+ <>
106
+ {isString(label) ? (
107
+ <Label aria-disabled={disabled} className="vui-textareaLabel" htmlFor={id} mb={0.5} {...styles.label}>
108
+ {label}
109
+ </Label>
110
+ ) : (
111
+ label
132
112
  )}
133
- </TextareaBase>
113
+ <TextareaBase
114
+ className={cs('vui-textarea', className)}
115
+ ref={ref}
116
+ {...styles.container}
117
+ {...aliasedProps}
118
+ {...rest}
119
+ >
120
+ <TextareaTextarea
121
+ className="vui-textareaTextarea"
122
+ ref={textareaRef}
123
+ {...{
124
+ autoFocus,
125
+ cols,
126
+ defaultValue,
127
+ disabled,
128
+ id,
129
+ maxLength,
130
+ name,
131
+ onBlur,
132
+ onChange,
133
+ onFocus,
134
+ placeholder,
135
+ readOnly,
136
+ required,
137
+ resize,
138
+ rows,
139
+ }}
140
+ value={valueInternal}
141
+ {...styles.textarea}
142
+ {...textareaAliasedProps}
143
+ {...textareaProps}
144
+ />
145
+
146
+ {showCount && (
147
+ <T
148
+ className="vui-textareaCount"
149
+ color={maxLength && count > maxLength ? inputColors.error : inputColors.helpText}
150
+ position="absolute"
151
+ right={0}
152
+ size="sm"
153
+ top="calc(100% + 1px)"
154
+ >
155
+ {count} {maxLength ? `/ ${maxLength}` : null}
156
+ </T>
157
+ )}
158
+
159
+ {!!helpText && <HelpText size={helpTextSize['lg']}>{helpText}</HelpText>}
160
+ {!!errorText && (
161
+ <HelpText isError size={helpTextSize['lg']}>
162
+ {errorText}
163
+ </HelpText>
164
+ )}
165
+ </TextareaBase>
166
+ </>
134
167
  )
135
168
  })
136
169
 
@@ -6,6 +6,8 @@ export type TextareaProps = SystemProps &
6
6
  ThemingProps<'Textarea'> & {
7
7
  /** Passed to the inner input. */
8
8
  autoFocus?: boolean
9
+ /** ARIA label for the input element. */
10
+ ariaLabel?: string
9
11
  /** Children are disabled for this component. */
10
12
  children?: never
11
13
  /** Deprecated. Please use variant instead. @deprecated */
@@ -16,8 +18,14 @@ export type TextareaProps = SystemProps &
16
18
  defaultValue?: number | string
17
19
  /** Passed to the inner input. */
18
20
  disabled?: boolean
21
+ /** Socket displaying error text below an input. */
22
+ errorText?: string | React.ReactNode
23
+ /** Socket displaying help text below an input. */
24
+ helpText?: React.ReactNode | string
19
25
  /** Deprecated. Please use variant="red" instead. @deprecated*/
20
26
  isInvalid?: boolean
27
+ /** The label. */
28
+ label?: string | React.ReactNode
21
29
  /** Passed to the inner input. */
22
30
  maxLength?: number
23
31
  /** Passed to the inner input. */
@@ -2,7 +2,7 @@ import { inputColors } from '../input/consts'
2
2
 
3
3
  const baseStyle = {
4
4
  textarea: {
5
- focusWithinRing: 2,
5
+ focusWithinRing: 3,
6
6
  color: inputColors.inputText,
7
7
  },
8
8
  input: {
@@ -14,7 +14,7 @@ const defaultProps = {
14
14
  variant: 'grey',
15
15
  }
16
16
 
17
- const parts = ['container', 'textarea']
17
+ const parts = ['container', 'textarea', 'label']
18
18
 
19
19
  const sizes = {}
20
20
 
@@ -20,6 +20,7 @@ import Heading from '../heading/theme'
20
20
  import Icon from '../icon/theme'
21
21
  import Image from '../image/theme'
22
22
  import Input from '../input/theme'
23
+ import Label from '../label/theme'
23
24
  import Link from '../link/theme'
24
25
  import List from '../list/theme'
25
26
  import Menu from '../menu/theme'
@@ -75,6 +76,7 @@ export default {
75
76
  Icon,
76
77
  Image,
77
78
  Input,
79
+ Label,
78
80
  Link,
79
81
  List,
80
82
  Markdown,