@itwin/itwinui-react 3.9.0 → 3.9.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.9.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#2005](https://github.com/iTwin/iTwinUI/pull/2005): Improved `IconButton` so that its tooltip is removed from the DOM when not visible.
8
+ - [#2004](https://github.com/iTwin/iTwinUI/pull/2004): Fixed a performance issue in `Tooltip` where expensive calculations were being run even when the tooltip was not visible.
9
+
3
10
  ## 3.9.0
4
11
 
5
12
  ### Minor Changes
@@ -43,16 +43,20 @@ const useTooltip = (options = {}) => {
43
43
  placement,
44
44
  open,
45
45
  onOpenChange,
46
- whileElementsMounted: (...args) => (0, react_1.autoUpdate)(...args, autoUpdateOptions),
47
- middleware: [
48
- middleware.offset !== undefined ? (0, react_1.offset)(middleware.offset) : (0, react_1.offset)(4),
46
+ whileElementsMounted: React.useMemo(() =>
47
+ // autoUpdate is expensive and should only be called when tooltip is open
48
+ open ? (...args) => (0, react_1.autoUpdate)(...args, autoUpdateOptions) : undefined, [autoUpdateOptions, open]),
49
+ middleware: React.useMemo(() => [
50
+ middleware.offset !== undefined
51
+ ? (0, react_1.offset)(middleware.offset)
52
+ : (0, react_1.offset)(4),
49
53
  middleware.flip && (0, react_1.flip)(),
50
54
  middleware.shift && (0, react_1.shift)(),
51
55
  middleware.size && (0, react_1.size)(),
52
56
  middleware.autoPlacement && (0, react_1.autoPlacement)(),
53
57
  middleware.inline && (0, react_1.inline)(),
54
58
  middleware.hide && (0, react_1.hide)(),
55
- ].filter(Boolean),
59
+ ].filter(Boolean), [middleware]),
56
60
  ...(reference && { elements: { reference } }),
57
61
  });
58
62
  const ariaProps = React.useMemo(() => ariaStrategy === 'description'
@@ -123,7 +127,13 @@ const useTooltip = (options = {}) => {
123
127
  ...props,
124
128
  id,
125
129
  }), [interactions, props, id, open]);
126
- return React.useMemo(() => ({ getReferenceProps, floatingProps, ...floating }), [getReferenceProps, floatingProps, floating]);
130
+ return React.useMemo(() => ({
131
+ getReferenceProps,
132
+ floatingProps,
133
+ ...floating,
134
+ // styles are not relevant when tooltip is not open
135
+ floatingStyles: floating.context.open ? floating.floatingStyles : {},
136
+ }), [getReferenceProps, floatingProps, floating]);
127
137
  };
128
138
  /**
129
139
  * Basic tooltip component to display informative content when an element is hovered or focused.
@@ -139,11 +149,13 @@ const useTooltip = (options = {}) => {
139
149
  exports.Tooltip = React.forwardRef((props, forwardedRef) => {
140
150
  const { content, children, portal = true, className, style, ...rest } = props;
141
151
  const tooltip = useTooltip(rest);
152
+ const refs = (0, index_js_1.useMergedRefs)(tooltip.refs.setFloating, forwardedRef);
142
153
  return (React.createElement(React.Fragment, null,
143
154
  (0, index_js_1.cloneElementWithRef)(children, (children) => ({
144
155
  ...tooltip.getReferenceProps(children.props),
145
156
  ref: tooltip.refs.setReference,
146
157
  })),
147
- React.createElement(index_js_1.Portal, { portal: portal },
148
- React.createElement(index_js_1.Box, { className: (0, classnames_1.default)('iui-tooltip', className), ref: (0, index_js_1.useMergedRefs)(tooltip.refs.setFloating, forwardedRef), style: { ...tooltip.floatingStyles, ...style }, ...tooltip.floatingProps }, content))));
158
+ // Tooltip must always be present in the DOM (even when closed) for ARIA to work
159
+ props.ariaStrategy !== 'none' || tooltip.context.open ? (React.createElement(index_js_1.Portal, { portal: portal },
160
+ React.createElement(index_js_1.Box, { className: (0, classnames_1.default)('iui-tooltip', className), ref: refs, style: { ...tooltip.floatingStyles, ...style }, ...tooltip.floatingProps }, content))) : null));
149
161
  });
@@ -14,16 +14,20 @@ const useTooltip = (options = {}) => {
14
14
  placement,
15
15
  open,
16
16
  onOpenChange,
17
- whileElementsMounted: (...args) => autoUpdate(...args, autoUpdateOptions),
18
- middleware: [
19
- middleware.offset !== undefined ? offset(middleware.offset) : offset(4),
17
+ whileElementsMounted: React.useMemo(() =>
18
+ // autoUpdate is expensive and should only be called when tooltip is open
19
+ open ? (...args) => autoUpdate(...args, autoUpdateOptions) : undefined, [autoUpdateOptions, open]),
20
+ middleware: React.useMemo(() => [
21
+ middleware.offset !== undefined
22
+ ? offset(middleware.offset)
23
+ : offset(4),
20
24
  middleware.flip && flip(),
21
25
  middleware.shift && shift(),
22
26
  middleware.size && size(),
23
27
  middleware.autoPlacement && autoPlacement(),
24
28
  middleware.inline && inline(),
25
29
  middleware.hide && hide(),
26
- ].filter(Boolean),
30
+ ].filter(Boolean), [middleware]),
27
31
  ...(reference && { elements: { reference } }),
28
32
  });
29
33
  const ariaProps = React.useMemo(() => ariaStrategy === 'description'
@@ -94,7 +98,13 @@ const useTooltip = (options = {}) => {
94
98
  ...props,
95
99
  id,
96
100
  }), [interactions, props, id, open]);
97
- return React.useMemo(() => ({ getReferenceProps, floatingProps, ...floating }), [getReferenceProps, floatingProps, floating]);
101
+ return React.useMemo(() => ({
102
+ getReferenceProps,
103
+ floatingProps,
104
+ ...floating,
105
+ // styles are not relevant when tooltip is not open
106
+ floatingStyles: floating.context.open ? floating.floatingStyles : {},
107
+ }), [getReferenceProps, floatingProps, floating]);
98
108
  };
99
109
  /**
100
110
  * Basic tooltip component to display informative content when an element is hovered or focused.
@@ -110,11 +120,13 @@ const useTooltip = (options = {}) => {
110
120
  export const Tooltip = React.forwardRef((props, forwardedRef) => {
111
121
  const { content, children, portal = true, className, style, ...rest } = props;
112
122
  const tooltip = useTooltip(rest);
123
+ const refs = useMergedRefs(tooltip.refs.setFloating, forwardedRef);
113
124
  return (React.createElement(React.Fragment, null,
114
125
  cloneElementWithRef(children, (children) => ({
115
126
  ...tooltip.getReferenceProps(children.props),
116
127
  ref: tooltip.refs.setReference,
117
128
  })),
118
- React.createElement(Portal, { portal: portal },
119
- React.createElement(Box, { className: cx('iui-tooltip', className), ref: useMergedRefs(tooltip.refs.setFloating, forwardedRef), style: { ...tooltip.floatingStyles, ...style }, ...tooltip.floatingProps }, content))));
129
+ // Tooltip must always be present in the DOM (even when closed) for ARIA to work
130
+ props.ariaStrategy !== 'none' || tooltip.context.open ? (React.createElement(Portal, { portal: portal },
131
+ React.createElement(Box, { className: cx('iui-tooltip', className), ref: refs, style: { ...tooltip.floatingStyles, ...style }, ...tooltip.floatingProps }, content))) : null));
120
132
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/itwinui-react",
3
- "version": "3.9.0",
3
+ "version": "3.9.1",
4
4
  "author": "Bentley Systems",
5
5
  "license": "MIT",
6
6
  "type": "module",