@westpac/ui 0.50.3 → 0.53.1

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 (141) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/dist/component-type.json +1 -1
  3. package/dist/components/accordion/components/accordion-item/accordion-item.component.js +15 -4
  4. package/dist/components/accordion/components/accordion-item/accordion-item.styles.d.ts +27 -0
  5. package/dist/components/accordion/components/accordion-item/accordion-item.styles.js +10 -1
  6. package/dist/components/alert/alert.styles.js +1 -1
  7. package/dist/components/autocomplete/autocomplete.styles.js +1 -1
  8. package/dist/components/badge/badge.styles.d.ts +2 -2
  9. package/dist/components/badge/badge.styles.js +2 -2
  10. package/dist/components/bottom-sheet/components/bottom-sheet-dialog/bottom-sheet-dialog.styles.js +2 -2
  11. package/dist/components/breadcrumb/components/breadcrumb-item/breadcrumb-item.component.js +1 -1
  12. package/dist/components/button/button.styles.js +1 -1
  13. package/dist/components/button-dropdown/button-dropdown.component.d.ts +1 -1
  14. package/dist/components/button-dropdown/button-dropdown.component.js +5 -3
  15. package/dist/components/button-dropdown/button-dropdown.types.d.ts +7 -2
  16. package/dist/components/button-dropdown/components/button-dropdown-panel/button-dropdown-panel.styles.js +1 -1
  17. package/dist/components/collapsible/collapsible.styles.js +1 -1
  18. package/dist/components/compacta/compacta.styles.js +1 -1
  19. package/dist/components/date-picker-beta/components/date-field/components/date-segment/date-segment.styles.d.ts +2 -2
  20. package/dist/components/date-picker-beta/components/date-field/components/date-segment/date-segment.styles.js +1 -1
  21. package/dist/components/filter/components/filter-buttons/filter-buttons.component.js +2 -3
  22. package/dist/components/filter/components/filter-buttons/filter-buttons.styles.js +5 -5
  23. package/dist/components/filter/filter.component.js +1 -1
  24. package/dist/components/flexi-cell/components/flexi-cell-body/flexi-cell-body.styles.d.ts +2 -2
  25. package/dist/components/flexi-cell/components/flexi-cell-body/flexi-cell-body.styles.js +1 -1
  26. package/dist/components/flexi-cell/flexi-cell.styles.js +1 -1
  27. package/dist/components/footer/footer.styles.js +1 -1
  28. package/dist/components/header/header.component.d.ts +1 -1
  29. package/dist/components/header/header.component.js +13 -10
  30. package/dist/components/header/header.styles.js +1 -1
  31. package/dist/components/header/header.types.d.ts +7 -1
  32. package/dist/components/input-group/components/input-group-add-ons/input-group-add-ons.styles.d.ts +2 -2
  33. package/dist/components/input-group/components/input-group-add-ons/input-group-add-ons.styles.js +3 -3
  34. package/dist/components/input-group/input-group.component.js +2 -1
  35. package/dist/components/modal/components/modal-dialog/index.d.ts +1 -0
  36. package/dist/components/modal/components/modal-dialog/modal-dialog.styles.js +1 -1
  37. package/dist/components/modal/index.d.ts +1 -0
  38. package/dist/components/pagination/components/pagination-item/pagination-item.component.js +8 -2
  39. package/dist/components/pagination/components/pagination-item/pagination-item.styles.d.ts +12 -0
  40. package/dist/components/pagination/components/pagination-item/pagination-item.styles.js +5 -1
  41. package/dist/components/pagination/components/pagination-presentational/pagination-presentational.styles.js +1 -1
  42. package/dist/components/panel/components/panel-footer/panel-footer.styles.js +1 -1
  43. package/dist/components/panel/panel.styles.js +1 -1
  44. package/dist/components/popover/components/panel/panel.component.js +5 -4
  45. package/dist/components/popover/components/panel/panel.styles.js +2 -2
  46. package/dist/components/progress-rope/components/progress-rope-group-step/progress-rope-group-step.component.js +37 -19
  47. package/dist/components/repeater/repeater.styles.js +1 -1
  48. package/dist/components/select/components/index.d.ts +2 -0
  49. package/dist/components/select/components/index.js +2 -0
  50. package/dist/components/select/components/select-with-tooltip/select-with-tooltip.component.d.ts +13 -0
  51. package/dist/components/select/components/select-with-tooltip/select-with-tooltip.component.js +22 -0
  52. package/dist/components/select/components/select-with-tooltip/select-with-tooltip.styles.d.ts +56 -0
  53. package/dist/components/select/components/select-with-tooltip/select-with-tooltip.styles.js +30 -0
  54. package/dist/components/select/components/styled-select/styled-select.component.d.ts +13 -0
  55. package/dist/components/select/components/styled-select/styled-select.component.js +19 -0
  56. package/dist/components/select/components/styled-select/styled-select.styles.d.ts +104 -0
  57. package/dist/components/select/components/styled-select/styled-select.styles.js +46 -0
  58. package/dist/components/select/select.component.d.ts +1 -0
  59. package/dist/components/select/select.component.js +7 -14
  60. package/dist/components/select/select.styles.d.ts +180 -45
  61. package/dist/components/select/select.styles.js +60 -15
  62. package/dist/components/select/select.types.d.ts +6 -0
  63. package/dist/components/table/table.styles.js +1 -1
  64. package/dist/components/tabs/components/tabs-tab/tabs-tab.styles.js +1 -1
  65. package/dist/components/tabs/components/tabs-tab-panel/tabs-tab-panel.styles.d.ts +2 -2
  66. package/dist/components/tabs/components/tabs-tab-panel/tabs-tab-panel.styles.js +1 -1
  67. package/dist/components/tooltip/components/tooltip-content/tooltip-content.component.d.ts +2 -0
  68. package/dist/components/tooltip/components/tooltip-content/tooltip-content.component.js +9 -0
  69. package/dist/components/tooltip/components/tooltip-content/tooltip-content.styles.d.ts +1 -0
  70. package/dist/components/tooltip/components/tooltip-content/tooltip-content.styles.js +4 -0
  71. package/dist/components/tooltip/components/tooltip-content/tooltip-content.types.d.ts +5 -0
  72. package/dist/components/tooltip/components/tooltip-content/tooltip-content.types.js +1 -0
  73. package/dist/components/tooltip/index.d.ts +1 -0
  74. package/dist/components/tooltip/index.js +1 -0
  75. package/dist/components/tooltip/tooltip.component.d.ts +2 -0
  76. package/dist/components/tooltip/tooltip.component.js +55 -0
  77. package/dist/components/tooltip/tooltip.styles.d.ts +1 -0
  78. package/dist/components/tooltip/tooltip.styles.js +4 -0
  79. package/dist/components/tooltip/tooltip.types.d.ts +7 -0
  80. package/dist/components/tooltip/tooltip.types.js +1 -0
  81. package/dist/components/well/well.styles.d.ts +2 -2
  82. package/dist/components/well/well.styles.js +1 -1
  83. package/dist/css/westpac-ui.css +113 -9
  84. package/dist/css/westpac-ui.min.css +113 -9
  85. package/package.json +3 -3
  86. package/src/components/accordion/components/accordion-item/accordion-item.component.tsx +22 -4
  87. package/src/components/accordion/components/accordion-item/accordion-item.styles.ts +10 -1
  88. package/src/components/alert/alert.styles.ts +1 -1
  89. package/src/components/autocomplete/autocomplete.styles.ts +1 -1
  90. package/src/components/badge/badge.styles.ts +2 -2
  91. package/src/components/bottom-sheet/components/bottom-sheet-dialog/bottom-sheet-dialog.styles.ts +2 -2
  92. package/src/components/breadcrumb/components/breadcrumb-item/breadcrumb-item.component.tsx +1 -1
  93. package/src/components/button/button.styles.ts +1 -1
  94. package/src/components/button-dropdown/button-dropdown.component.tsx +8 -1
  95. package/src/components/button-dropdown/button-dropdown.types.ts +7 -2
  96. package/src/components/button-dropdown/components/button-dropdown-panel/button-dropdown-panel.styles.ts +1 -1
  97. package/src/components/collapsible/collapsible.styles.ts +1 -1
  98. package/src/components/compacta/compacta.styles.ts +1 -1
  99. package/src/components/date-picker-beta/components/date-field/components/date-segment/date-segment.styles.ts +1 -1
  100. package/src/components/filter/components/filter-buttons/filter-buttons.component.tsx +1 -2
  101. package/src/components/filter/components/filter-buttons/filter-buttons.styles.ts +5 -5
  102. package/src/components/filter/filter.component.tsx +1 -1
  103. package/src/components/flexi-cell/components/flexi-cell-body/flexi-cell-body.styles.ts +1 -1
  104. package/src/components/flexi-cell/flexi-cell.styles.ts +1 -1
  105. package/src/components/footer/footer.styles.ts +1 -1
  106. package/src/components/header/header.component.tsx +17 -4
  107. package/src/components/header/header.styles.ts +1 -1
  108. package/src/components/header/header.types.ts +7 -1
  109. package/src/components/input-group/components/input-group-add-ons/input-group-add-ons.styles.ts +3 -3
  110. package/src/components/input-group/input-group.component.tsx +1 -0
  111. package/src/components/modal/components/modal-dialog/index.ts +1 -0
  112. package/src/components/modal/components/modal-dialog/modal-dialog.styles.ts +1 -1
  113. package/src/components/modal/index.ts +1 -0
  114. package/src/components/pagination/components/pagination-item/pagination-item.component.tsx +9 -2
  115. package/src/components/pagination/components/pagination-item/pagination-item.styles.ts +5 -1
  116. package/src/components/pagination/components/pagination-presentational/pagination-presentational.styles.ts +1 -1
  117. package/src/components/panel/components/panel-footer/panel-footer.styles.ts +1 -1
  118. package/src/components/panel/panel.styles.ts +1 -1
  119. package/src/components/popover/components/panel/panel.component.tsx +8 -5
  120. package/src/components/popover/components/panel/panel.styles.ts +2 -2
  121. package/src/components/progress-rope/components/progress-rope-group-step/progress-rope-group-step.component.tsx +62 -38
  122. package/src/components/repeater/repeater.styles.ts +1 -1
  123. package/src/components/select/components/index.ts +2 -0
  124. package/src/components/select/components/select-with-tooltip/select-with-tooltip.component.tsx +31 -0
  125. package/src/components/select/components/select-with-tooltip/select-with-tooltip.styles.ts +26 -0
  126. package/src/components/select/components/styled-select/styled-select.component.tsx +25 -0
  127. package/src/components/select/components/styled-select/styled-select.styles.ts +42 -0
  128. package/src/components/select/select.component.tsx +9 -14
  129. package/src/components/select/select.styles.ts +18 -15
  130. package/src/components/select/select.types.ts +6 -0
  131. package/src/components/table/table.styles.ts +1 -1
  132. package/src/components/tabs/components/tabs-tab/tabs-tab.styles.ts +1 -1
  133. package/src/components/tabs/components/tabs-tab-panel/tabs-tab-panel.styles.ts +1 -1
  134. package/src/components/tooltip/components/tooltip-content/tooltip-content.component.tsx +12 -0
  135. package/src/components/tooltip/components/tooltip-content/tooltip-content.styles.ts +5 -0
  136. package/src/components/tooltip/components/tooltip-content/tooltip-content.types.ts +6 -0
  137. package/src/components/tooltip/index.ts +1 -0
  138. package/src/components/tooltip/tooltip.component.tsx +61 -0
  139. package/src/components/tooltip/tooltip.styles.ts +3 -0
  140. package/src/components/tooltip/tooltip.types.ts +8 -0
  141. package/src/components/well/well.styles.ts +1 -1
@@ -1,5 +1,5 @@
1
- import { AnimatePresence, LazyMotion, m } from 'motion/react';
2
- import React, { useId, useMemo } from 'react';
1
+ import { LazyMotion, m, useAnimate } from 'motion/react';
2
+ import React, { useEffect, useId, useMemo, useState } from 'react';
3
3
  import { useFocusRing } from 'react-aria';
4
4
 
5
5
  import { Circle, VisuallyHidden } from '../../../index.js';
@@ -23,6 +23,8 @@ export function ProgressRopeGroupStep({
23
23
  onToggle,
24
24
  tag: Tag,
25
25
  }: ProgressRopeGroupStepProps) {
26
+ // Handling expanding animation this way for focus ring on steps
27
+ const [scope, animate] = useAnimate();
26
28
  const id = useId();
27
29
  const stepsContainerID = `progress-rope-group-steps-container-${id}`;
28
30
 
@@ -60,6 +62,38 @@ export function ProgressRopeGroupStep({
60
62
  }, [current, visited]);
61
63
 
62
64
  const styles = progressRopeGroupStyles({ firstItem, state, isFocusVisible });
65
+ const [overflowVisible, setOverflowVisible] = useState(false);
66
+
67
+ useEffect(() => {
68
+ // Animates expanding/collapsing steps
69
+ if (opened) {
70
+ animate(
71
+ scope.current,
72
+ { height: 'auto' },
73
+ {
74
+ duration: 0.2,
75
+ ease: 'easeInOut',
76
+ onComplete: () => {
77
+ setOverflowVisible(true);
78
+ },
79
+ },
80
+ );
81
+ } else {
82
+ animate(
83
+ scope.current,
84
+ { height: 0 },
85
+ {
86
+ duration: 0.2,
87
+ ease: 'easeInOut',
88
+ onPlay: () => {
89
+ setOverflowVisible(false);
90
+ },
91
+ },
92
+ );
93
+ }
94
+ // eslint-disable-next-line react-hooks/exhaustive-deps
95
+ }, [opened]);
96
+
63
97
  return (
64
98
  <Tag>
65
99
  <button
@@ -74,42 +108,32 @@ export function ProgressRopeGroupStep({
74
108
  <VisuallyHidden>{visuallyHiddenMessage}</VisuallyHidden>
75
109
  </button>
76
110
  <LazyMotion features={loadAnimations}>
77
- <AnimatePresence initial={false}>
78
- {opened && (
79
- <m.div
80
- initial={{
81
- height: 0,
82
- overflow: 'hidden',
83
- }}
84
- animate={{
85
- height: 'auto',
86
- }}
87
- exit={{
88
- height: 0,
89
- overflow: 'hidden',
90
- }}
91
- transition={{ duration: 0.2, ease: 'easeInOut' }}
92
- >
93
- <ol className={styles.stepsWrapper({})} id={stepsContainerID} aria-hidden={!opened}>
94
- {steps.map((step, index) => (
95
- <li key={step.index}>
96
- <ProgressRopeStep
97
- firstItem={index === 0}
98
- lastItemInGroup={index === steps.length - 1}
99
- size="small"
100
- onClick={(furthestVisitedStep || 0) >= step.index ? step.onClick : undefined}
101
- current={step.index === currentKey}
102
- visited={(furthestVisitedStep || 0) > step.index}
103
- furthest={furthestVisitedStep === step.index}
104
- >
105
- {step.text}
106
- </ProgressRopeStep>
107
- </li>
108
- ))}
109
- </ol>
110
- </m.div>
111
- )}
112
- </AnimatePresence>
111
+ <m.div
112
+ ref={scope}
113
+ initial={{ height: opened ? 'auto' : 0 }}
114
+ style={{
115
+ overflow: overflowVisible ? 'visible' : 'hidden', // to show focus ring correctly when expanded
116
+ }}
117
+ >
118
+ <ol className={styles.stepsWrapper({})} id={stepsContainerID} aria-hidden={!opened}>
119
+ {steps.map((step, index) => (
120
+ <li key={step.index}>
121
+ <ProgressRopeStep
122
+ firstItem={index === 0}
123
+ lastItemInGroup={index === steps.length - 1}
124
+ size="small"
125
+ onClick={(furthestVisitedStep || 0) >= step.index ? step.onClick : undefined}
126
+ current={step.index === currentKey}
127
+ visited={(furthestVisitedStep || 0) > step.index}
128
+ furthest={furthestVisitedStep === step.index}
129
+ tabIndex={opened ? 0 : -1} // Using hidden/visibility breaks styles
130
+ >
131
+ {step.text}
132
+ </ProgressRopeStep>
133
+ </li>
134
+ ))}
135
+ </ol>
136
+ </m.div>
113
137
  </LazyMotion>
114
138
  </Tag>
115
139
  );
@@ -7,7 +7,7 @@ export const styles = tv(
7
7
  list: 'm-0 flex list-none flex-col pl-0',
8
8
  item: 'relative',
9
9
  itemIndex: 'mb-3 font-bold',
10
- content: '',
10
+ content: '[&_:focus-visible]:focus-outline',
11
11
  removeBtn: 'absolute right-0 top-0 h-auto p-0 no-underline hover:underline',
12
12
  footer: 'flex justify-between pt-[0.875rem]',
13
13
  addBtn: 'h-auto p-0 no-underline hover:underline',
@@ -0,0 +1,2 @@
1
+ export { SelectWithTooltip } from './select-with-tooltip/select-with-tooltip.component.js';
2
+ export { StyledSelect } from './styled-select/styled-select.component.js';
@@ -0,0 +1,31 @@
1
+ import React, { ForwardedRef, forwardRef, useState } from 'react';
2
+
3
+ import { Tooltip } from '../../../tooltip/index.js';
4
+ import { SelectProps } from '../../select.types.js';
5
+ import { StyledSelect } from '../styled-select/styled-select.component.js';
6
+
7
+ import { styles } from './select-with-tooltip.styles.js';
8
+
9
+ function BaseSelectWithTooltip(
10
+ { width = 'auto', children, onChange, ...props }: SelectProps,
11
+ ref: ForwardedRef<HTMLSelectElement>,
12
+ ) {
13
+ const [selectedOption, setSelectedOption] = useState('');
14
+ return (
15
+ <Tooltip tooltip={selectedOption} className={styles({ width })}>
16
+ <StyledSelect
17
+ ref={ref}
18
+ onChange={e => {
19
+ setSelectedOption(e.target.options[e.target.selectedIndex].text);
20
+ onChange?.(e);
21
+ }}
22
+ width={width}
23
+ {...props}
24
+ >
25
+ {children}
26
+ </StyledSelect>
27
+ </Tooltip>
28
+ );
29
+ }
30
+
31
+ export const SelectWithTooltip = forwardRef<HTMLSelectElement, SelectProps>(BaseSelectWithTooltip);
@@ -0,0 +1,26 @@
1
+ import { tv } from 'tailwind-variants';
2
+
3
+ export const styles = tv(
4
+ {
5
+ base: '',
6
+ variants: {
7
+ width: {
8
+ auto: 'flex-1',
9
+ full: 'w-full flex-1',
10
+ 1: 'w-[1.81ex]',
11
+ 2: 'w-[3.62ex]',
12
+ 3: 'w-[5.43ex]',
13
+ 4: 'w-[7.24ex]',
14
+ 5: 'w-[9.05ex]',
15
+ 6: 'w-[10.86ex]',
16
+ 7: 'w-[12.67ex]',
17
+ 8: 'w-[14.48ex]',
18
+ 9: 'w-[16.29ex]',
19
+ 10: 'w-[18.1ex]',
20
+ 20: 'w-[36.2ex]',
21
+ 30: 'w-[54.3ex]',
22
+ },
23
+ },
24
+ },
25
+ { responsiveVariants: ['xsl', 'sm', 'md', 'lg', 'xl'] },
26
+ );
@@ -0,0 +1,25 @@
1
+ import React, { ForwardedRef, forwardRef } from 'react';
2
+ import { mergeProps, useFocusRing } from 'react-aria';
3
+
4
+ import { type SelectProps } from '../../select.types.js';
5
+
6
+ import { styles } from './styled-select.styles.js';
7
+
8
+ function BaseSelect(
9
+ { className, size = 'medium', invalid = false, width = 'auto', children, ...props }: SelectProps,
10
+ ref: ForwardedRef<HTMLSelectElement>,
11
+ ) {
12
+ const { isFocused, isFocusVisible, focusProps } = useFocusRing();
13
+
14
+ return (
15
+ <select
16
+ ref={ref}
17
+ className={styles({ className, size, invalid, isFocused, isFocusVisible, width })}
18
+ {...mergeProps(props, focusProps)}
19
+ >
20
+ {children}
21
+ </select>
22
+ );
23
+ }
24
+
25
+ export const StyledSelect = forwardRef<HTMLSelectElement, SelectProps>(BaseSelect);
@@ -0,0 +1,42 @@
1
+ import { tv } from 'tailwind-variants';
2
+
3
+ export const styles = tv(
4
+ {
5
+ base: 'form-control overflow-hidden overflow-ellipsis whitespace-nowrap bg-no-repeat select-caret disabled:form-control-disabled group-first/add-on-before:!rounded-l group-first/add-on-before:rounded-r-none group-first/add-on-before:!border-x group-last/add-on-after:!rounded-r group-last/add-on-after:rounded-l-none group-last/add-on-after:!border-x group-[.input-group-after]:rounded-r-none group-[.input-group-before]:rounded-l-none group-[.input-group-after]:border-r-0 group-[.input-group-before]:border-l-0',
6
+ variants: {
7
+ size: {
8
+ small: 'form-control-small bg-[right_0.5625rem_center] pr-[calc(0.5rem+14px+0.5625rem)]',
9
+ medium: 'form-control-medium bg-[right_0.75rem_center] pr-[calc(0.5rem+14px+0.75rem)]',
10
+ large: 'form-control-large bg-[right_0.9375rem_center] pr-[calc(0.5rem+14px+0.9375rem)]',
11
+ xlarge: 'form-control-xlarge bg-[right_1.125rem_center] pr-[calc(0.5rem+14px+1.125rem)]',
12
+ },
13
+ invalid: {
14
+ true: 'border-danger',
15
+ false: 'border-borderDark',
16
+ },
17
+ isFocusVisible: {
18
+ true: 'focus-outline',
19
+ },
20
+ isFocused: {
21
+ true: 'outline-none',
22
+ },
23
+ width: {
24
+ auto: 'flex-1',
25
+ full: 'w-full flex-1',
26
+ 1: 'box-content w-[1.81ex]',
27
+ 2: 'box-content w-[3.62ex]',
28
+ 3: 'box-content w-[5.43ex]',
29
+ 4: 'box-content w-[7.24ex]',
30
+ 5: 'box-content w-[9.05ex]',
31
+ 6: 'box-content w-[10.86ex]',
32
+ 7: 'box-content w-[12.67ex]',
33
+ 8: 'box-content w-[14.48ex]',
34
+ 9: 'box-content w-[16.29ex]',
35
+ 10: 'box-content w-[18.1ex]',
36
+ 20: 'box-content w-[36.2ex]',
37
+ 30: 'box-content w-[54.3ex]',
38
+ },
39
+ },
40
+ },
41
+ { responsiveVariants: ['xsl', 'sm', 'md', 'lg', 'xl'] },
42
+ );
@@ -1,24 +1,19 @@
1
1
  'use client';
2
2
 
3
3
  import React, { ForwardedRef, forwardRef } from 'react';
4
- import { mergeProps, useFocusRing } from 'react-aria';
5
4
 
6
- import { styles } from './select.styles.js';
5
+ import { SelectWithTooltip, StyledSelect } from './components/index.js';
7
6
  import { type SelectProps } from './select.types.js';
8
7
 
9
- function BaseSelect(
10
- { className, size = 'medium', invalid = false, width = 'auto', children, ...props }: SelectProps,
11
- ref: ForwardedRef<HTMLSelectElement>,
12
- ) {
13
- const { isFocused, isFocusVisible, focusProps } = useFocusRing();
14
- return (
15
- <select
16
- ref={ref}
17
- className={styles({ className, size, invalid, isFocused, isFocusVisible, width })}
18
- {...mergeProps(props, focusProps)}
19
- >
8
+ function BaseSelect({ children, enableTooltip, ...props }: SelectProps, ref: ForwardedRef<HTMLSelectElement>) {
9
+ return enableTooltip ? (
10
+ <SelectWithTooltip ref={ref} {...props}>
20
11
  {children}
21
- </select>
12
+ </SelectWithTooltip>
13
+ ) : (
14
+ <StyledSelect ref={ref} {...props}>
15
+ {children}
16
+ </StyledSelect>
22
17
  );
23
18
  }
24
19
 
@@ -2,7 +2,10 @@ import { tv } from 'tailwind-variants';
2
2
 
3
3
  export const styles = tv(
4
4
  {
5
- base: 'form-control bg-no-repeat select-caret disabled:form-control-disabled group-first/add-on-before:!rounded-l group-first/add-on-before:rounded-r-none group-first/add-on-before:!border-x group-last/add-on-after:!rounded-r group-last/add-on-after:rounded-l-none group-last/add-on-after:!border-x group-[.input-group-after]:rounded-r-none group-[.input-group-before]:rounded-l-none group-[.input-group-after]:border-r-0 group-[.input-group-before]:border-l-0',
5
+ slots: {
6
+ base: 'form-control overflow-hidden overflow-ellipsis whitespace-nowrap bg-no-repeat select-caret disabled:form-control-disabled group-first/add-on-before:!rounded-l group-first/add-on-before:rounded-r-none group-first/add-on-before:!border-x group-last/add-on-after:!rounded-r group-last/add-on-after:rounded-l-none group-last/add-on-after:!border-x group-[.input-group-after]:rounded-r-none group-[.input-group-before]:rounded-l-none group-[.input-group-after]:border-r-0 group-[.input-group-before]:border-l-0',
7
+ tooltip: '',
8
+ },
6
9
  variants: {
7
10
  size: {
8
11
  small: 'form-control-small bg-[right_0.5625rem_center] pr-[calc(0.5rem+14px+0.5625rem)]',
@@ -21,20 +24,20 @@ export const styles = tv(
21
24
  true: 'outline-none',
22
25
  },
23
26
  width: {
24
- auto: 'flex-1',
25
- full: 'w-full flex-1',
26
- 1: 'box-content w-[1.81ex]',
27
- 2: 'box-content w-[3.62ex]',
28
- 3: 'box-content w-[5.43ex]',
29
- 4: 'box-content w-[7.24ex]',
30
- 5: 'box-content w-[9.05ex]',
31
- 6: 'box-content w-[10.86ex]',
32
- 7: 'box-content w-[12.67ex]',
33
- 8: 'box-content w-[14.48ex]',
34
- 9: 'box-content w-[16.29ex]',
35
- 10: 'box-content w-[18.1ex]',
36
- 20: 'box-content w-[36.2ex]',
37
- 30: 'box-content w-[54.3ex]',
27
+ auto: { base: 'flex-1', tooltip: 'flex-1' },
28
+ full: { base: 'w-full flex-1', tooltip: 'w-full flex-1' },
29
+ 1: { base: 'box-content w-[1.81ex]', tooltip: 'w-[1.81ex]' },
30
+ 2: { base: 'box-content w-[3.62ex]', tooltip: 'w-[3.62ex]' },
31
+ 3: { base: 'box-content w-[5.43ex]', tooltip: 'w-[5.43ex]' },
32
+ 4: { base: 'box-content w-[7.24ex]', tooltip: 'w-[7.24ex]' },
33
+ 5: { base: 'box-content w-[9.05ex]', tooltip: 'w-[9.05ex]' },
34
+ 6: { base: 'box-content w-[10.86ex]', tooltip: 'w-[10.86ex]' },
35
+ 7: { base: 'box-content w-[12.67ex]', tooltip: 'w-[12.67ex]' },
36
+ 8: { base: 'box-content w-[14.48ex]', tooltip: 'w-[14.48ex]' },
37
+ 9: { base: 'box-content w-[16.29ex]', tooltip: 'w-[16.29ex]' },
38
+ 10: { base: 'box-content w-[18.1ex]', tooltip: 'w-[18.1ex]' },
39
+ 20: { base: 'box-content w-[36.2ex]', tooltip: 'w-[36.2ex]' },
40
+ 30: { base: 'box-content w-[54.3ex]', tooltip: 'w-[54.3ex]' },
38
41
  },
39
42
  },
40
43
  },
@@ -6,6 +6,12 @@ import { styles } from './select.styles.js';
6
6
  type Variants = VariantProps<typeof styles>;
7
7
 
8
8
  export type SelectProps = {
9
+ /**
10
+ * Whether to set the title for the select to the currently selected option for use with truncation.
11
+ * Optional for accessibility reasons as it should only be enabled when required. Will not be read by screen readers.
12
+ * @default false
13
+ */
14
+ enableTooltip?: boolean;
9
15
  /**
10
16
  * Whether select is invalid
11
17
  * @default false
@@ -3,7 +3,7 @@ import { tv } from 'tailwind-variants';
3
3
  export const styles = tv(
4
4
  {
5
5
  slots: {
6
- base: 'mb-4 w-full',
6
+ base: 'mb-4 w-full [&_:focus-visible]:focus-outline',
7
7
  wrapper: 'max-xsl:mb-3 max-xsl:w-full max-xsl:overflow-x-auto max-xsl:overflow-y-hidden',
8
8
  },
9
9
  variants: {},
@@ -24,7 +24,7 @@ export const styles = tv(
24
24
  hero: '',
25
25
  },
26
26
  isFocusVisible: {
27
- true: 'focus-outline',
27
+ true: 'z-10 focus-outline',
28
28
  false: 'outline-none',
29
29
  },
30
30
  },
@@ -2,7 +2,7 @@ import { tv } from 'tailwind-variants';
2
2
 
3
3
  export const styles = tv(
4
4
  {
5
- base: 'flex-1 bg-white p-4',
5
+ base: 'flex-1 bg-white p-4 [&_:focus-visible]:focus-outline',
6
6
  variants: {
7
7
  look: {
8
8
  default: 'border border-border',
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+
3
+ import { styles } from './tooltip-content.styles.js';
4
+ import { TooltipContentProps } from './tooltip-content.types.js';
5
+
6
+ export function TooltipContent({ children, id }: TooltipContentProps) {
7
+ return children ? (
8
+ <span className={styles()} role="tooltip" id={id}>
9
+ {children}
10
+ </span>
11
+ ) : null;
12
+ }
@@ -0,0 +1,5 @@
1
+ import { tv } from 'tailwind-variants';
2
+
3
+ export const styles = tv({
4
+ base: 'absolute left-1 top-full z-10 mt-2 whitespace-nowrap rounded-sm border border-border bg-background p-0.5 text-text',
5
+ });
@@ -0,0 +1,6 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ export type TooltipContentProps = {
4
+ children?: ReactNode;
5
+ id: string;
6
+ };
@@ -0,0 +1 @@
1
+ export { Tooltip } from './tooltip.component.js';
@@ -0,0 +1,61 @@
1
+ 'use client';
2
+
3
+ import React, { useCallback, useEffect, useId, useRef, useState } from 'react';
4
+ import { mergeProps, useHover, useFocusRing } from 'react-aria';
5
+
6
+ import { TooltipContent } from './components/tooltip-content/tooltip-content.component.js';
7
+ import { styles } from './tooltip.styles.js';
8
+ import { TooltipProps } from './tooltip.types.js';
9
+
10
+ // TODO: Complete component/replace with a library that works (react-tooltip if can find a way to remove aria-described by for select)
11
+ export function Tooltip({ children, tooltip, id, className }: TooltipProps) {
12
+ const localId = useId();
13
+ const [isOpen, setIsOpen] = useState(false);
14
+ const tooltipWaitTime = useRef<NodeJS.Timeout | null>(null);
15
+
16
+ const handleKeyDown = (e: KeyboardEvent) => {
17
+ if (e.key === 'Escape' && isOpen) {
18
+ setIsOpen(false);
19
+ }
20
+ };
21
+ const { hoverProps, isHovered } = useHover({});
22
+ const { isFocusVisible, focusProps } = useFocusRing({ within: true });
23
+
24
+ const startTimer = useCallback(() => {
25
+ tooltipWaitTime.current = setTimeout(() => {
26
+ setIsOpen(true);
27
+ }, 1000);
28
+ }, []);
29
+
30
+ const stopTimer = useCallback(() => {
31
+ if (tooltipWaitTime.current) {
32
+ clearTimeout(tooltipWaitTime.current);
33
+ }
34
+ }, []);
35
+
36
+ useEffect(() => {
37
+ setIsOpen(isFocusVisible);
38
+ }, [isFocusVisible]);
39
+
40
+ useEffect(() => {
41
+ if (isHovered && !isOpen) startTimer();
42
+ if (!isHovered) setIsOpen(false);
43
+
44
+ return () => stopTimer();
45
+
46
+ // eslint-disable-next-line react-hooks/exhaustive-deps
47
+ }, [isHovered]);
48
+
49
+ useEffect(() => {
50
+ window.addEventListener('keydown', handleKeyDown);
51
+ return () => window.removeEventListener('keydown', handleKeyDown);
52
+ // eslint-disable-next-line react-hooks/exhaustive-deps
53
+ }, [isOpen]);
54
+
55
+ return (
56
+ <span {...mergeProps(hoverProps, focusProps)} className={styles({ className })}>
57
+ {children}
58
+ {isOpen && <TooltipContent id={id ?? localId}>{tooltip}</TooltipContent>}
59
+ </span>
60
+ );
61
+ }
@@ -0,0 +1,3 @@
1
+ import { tv } from 'tailwind-variants';
2
+
3
+ export const styles = tv({ base: 'relative' });
@@ -0,0 +1,8 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ export type TooltipProps = {
4
+ children: ReactNode;
5
+ tooltip: string;
6
+ id?: string;
7
+ className?: string;
8
+ };
@@ -2,7 +2,7 @@ import { tv } from 'tailwind-variants';
2
2
 
3
3
  export const styles = tv(
4
4
  {
5
- base: 'rounded border border-border p-2 sm:p-4',
5
+ base: 'rounded border border-border p-2 sm:p-4 [&_:focus-visible]:focus-outline',
6
6
  variants: {
7
7
  color: {
8
8
  light: 'bg-light',