@workday/canvas-kit-react 9.1.22 → 9.1.24

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.
@@ -1 +1 @@
1
- {"version":3,"file":"useReturnFocus.d.ts","sourceRoot":"","sources":["../../../../../popup/lib/hooks/useReturnFocus.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAiC1B;;;;;;GAMG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;MA6GzB,CAAC"}
1
+ {"version":3,"file":"useReturnFocus.d.ts","sourceRoot":"","sources":["../../../../../popup/lib/hooks/useReturnFocus.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAkD1B;;;;;;GAMG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;MA2GzB,CAAC"}
@@ -30,6 +30,17 @@ function getFocusableElement(element) {
30
30
  }
31
31
  return getFocusableElement(element.parentElement);
32
32
  }
33
+ /**
34
+ * Is the element outside of bounds. An element is outside of bounds if it is less than half visible.
35
+ */
36
+ function isElementOutOfBounds(element, boundingRect) {
37
+ const elementRect = element.getBoundingClientRect();
38
+ return (elementRect.top + elementRect.height / 2 < boundingRect.top || // is the top half of the target element visible?
39
+ elementRect.bottom - elementRect.height / 2 > boundingRect.bottom || // is the bottom half of the target element visible?
40
+ elementRect.left + elementRect.width / 2 < boundingRect.left || // is the left half of the target element visible?
41
+ elementRect.right - elementRect.width / 2 > boundingRect.right // is the right half of the target element visible?
42
+ );
43
+ }
33
44
  /**
34
45
  * Returns focus to the target element when the popup is hidden. This works well with
35
46
  * {@link useInitialFocus}. This should be used with {@link useFocusRedirect} or
@@ -91,14 +102,12 @@ exports.useReturnFocus = common_1.createElemPropsHook(usePopupModel_1.usePopupMo
91
102
  }
92
103
  const scrollParent = getScrollParent(element);
93
104
  const scrollParentRect = scrollParent.getBoundingClientRect();
94
- const elementRect = element.getBoundingClientRect();
105
+ const viewportRect = { left: 0, top: 0, right: window.innerWidth, bottom: window.innerHeight };
95
106
  // Don't change focus if user focused on a different element like a `input` or the target
96
107
  // element isn't on at least halfway rendered on the screen.
97
108
  if ((elementRef.current && getFocusableElement(elementRef.current)) || // did the user click on a focusable element?
98
- elementRect.top + elementRect.height / 2 < scrollParentRect.top || // is the top half of the target element visible?
99
- elementRect.bottom - elementRect.height / 2 > scrollParentRect.bottom || // is the bottom half of the target element visible?
100
- elementRect.left + elementRect.width / 2 < scrollParentRect.left || // is the left half of the target element visible?
101
- elementRect.right - elementRect.width / 2 > scrollParentRect.right // is the right half of the target element visible?
109
+ isElementOutOfBounds(element, scrollParentRect) || // Is the element not visible in its scroll parent?
110
+ isElementOutOfBounds(element, viewportRect) // Is the element not visible in the viewport?
102
111
  ) {
103
112
  // reset the focus element and bail early
104
113
  elementRef.current = null;
@@ -150,12 +150,7 @@ export declare const useTabsItem: import("@workday/canvas-kit-react/common").Beh
150
150
  menu: {
151
151
  state: {
152
152
  stackRef: React.RefObject<HTMLDivElement>;
153
- targetRef: React.RefObject<HTMLButtonElement>; /**
154
- * The identifier of the tab. This identifier will be used in change events and for `initialTab`.
155
- * Must match the `data-id` of the associated tab panel. If this property is not provided, it will
156
- * default to a string representation of the the zero-based index of the Tab when it was
157
- * initialized.
158
- */
153
+ targetRef: React.RefObject<HTMLButtonElement>;
159
154
  initialFocusRef: React.RefObject<any> | undefined;
160
155
  returnFocusRef: React.RefObject<any> | undefined;
161
156
  placement: import("@popperjs/core").Placement;
@@ -346,12 +341,7 @@ export declare const TabsItem: import("@workday/canvas-kit-react/common").Elemen
346
341
  menu: {
347
342
  state: {
348
343
  stackRef: React.RefObject<HTMLDivElement>;
349
- targetRef: React.RefObject<HTMLButtonElement>; /**
350
- * The identifier of the tab. This identifier will be used in change events and for `initialTab`.
351
- * Must match the `data-id` of the associated tab panel. If this property is not provided, it will
352
- * default to a string representation of the the zero-based index of the Tab when it was
353
- * initialized.
354
- */
344
+ targetRef: React.RefObject<HTMLButtonElement>;
355
345
  initialFocusRef: React.RefObject<any> | undefined;
356
346
  returnFocusRef: React.RefObject<any> | undefined;
357
347
  placement: import("@popperjs/core").Placement;
@@ -1 +1 @@
1
- {"version":3,"file":"TabsItem.d.ts","sourceRoot":"","sources":["../../../../tabs/lib/TabsItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAIL,UAAU,EAGV,YAAY,EAKb,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAC,GAAG,EAAE,SAAS,EAAC,MAAM,kCAAkC,CAAC;AAYhE,MAAM,WAAW,aACf,SAAQ,YAAY,CAAC,OAAO,GAAG,EAAE,KAAK,CAAC,EACrC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACjC;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;OAaG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,aAAa;;;;oDA+EzB,CAAC;AAEF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2DAhHtB;;;;;eAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4HJ,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2DAnInB;;;;;eAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+IH,CAAC"}
1
+ {"version":3,"file":"TabsItem.d.ts","sourceRoot":"","sources":["../../../../tabs/lib/TabsItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAIL,UAAU,EAIV,YAAY,EAKb,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAC,GAAG,EAAE,SAAS,EAAC,MAAM,kCAAkC,CAAC;AAYhE,MAAM,WAAW,aACf,SAAQ,YAAY,CAAC,OAAO,GAAG,EAAE,KAAK,CAAC,EACrC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACjC;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;OAaG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,aAAa;;;;oDA+EzB,CAAC;AAEF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiBvB,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiBnB,CAAC"}
@@ -108,7 +108,7 @@ exports.useTabsItem = common_1.composeHooks(common_1.createElemPropsHook(useTabs
108
108
  type: 'button',
109
109
  role: 'tab',
110
110
  'aria-selected': selected,
111
- 'aria-controls': `tabpanel-${state.id}-${name}`,
111
+ 'aria-controls': common_1.slugify(`tabpanel-${state.id}-${name}`),
112
112
  };
113
113
  }), collection_1.useListItemSelect, collection_1.useOverflowListItemMeasure, collection_1.useListItemRovingFocus, collection_1.useListItemRegister);
114
114
  exports.TabsItem = common_1.createSubcomponent('button')({
@@ -1 +1 @@
1
- {"version":3,"file":"useReturnFocus.d.ts","sourceRoot":"","sources":["../../../../../popup/lib/hooks/useReturnFocus.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAiC1B;;;;;;GAMG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;MA6GzB,CAAC"}
1
+ {"version":3,"file":"useReturnFocus.d.ts","sourceRoot":"","sources":["../../../../../popup/lib/hooks/useReturnFocus.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAkD1B;;;;;;GAMG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;MA2GzB,CAAC"}
@@ -24,6 +24,17 @@ function getFocusableElement(element) {
24
24
  }
25
25
  return getFocusableElement(element.parentElement);
26
26
  }
27
+ /**
28
+ * Is the element outside of bounds. An element is outside of bounds if it is less than half visible.
29
+ */
30
+ function isElementOutOfBounds(element, boundingRect) {
31
+ const elementRect = element.getBoundingClientRect();
32
+ return (elementRect.top + elementRect.height / 2 < boundingRect.top || // is the top half of the target element visible?
33
+ elementRect.bottom - elementRect.height / 2 > boundingRect.bottom || // is the bottom half of the target element visible?
34
+ elementRect.left + elementRect.width / 2 < boundingRect.left || // is the left half of the target element visible?
35
+ elementRect.right - elementRect.width / 2 > boundingRect.right // is the right half of the target element visible?
36
+ );
37
+ }
27
38
  /**
28
39
  * Returns focus to the target element when the popup is hidden. This works well with
29
40
  * {@link useInitialFocus}. This should be used with {@link useFocusRedirect} or
@@ -85,14 +96,12 @@ export const useReturnFocus = createElemPropsHook(usePopupModel)(model => {
85
96
  }
86
97
  const scrollParent = getScrollParent(element);
87
98
  const scrollParentRect = scrollParent.getBoundingClientRect();
88
- const elementRect = element.getBoundingClientRect();
99
+ const viewportRect = { left: 0, top: 0, right: window.innerWidth, bottom: window.innerHeight };
89
100
  // Don't change focus if user focused on a different element like a `input` or the target
90
101
  // element isn't on at least halfway rendered on the screen.
91
102
  if ((elementRef.current && getFocusableElement(elementRef.current)) || // did the user click on a focusable element?
92
- elementRect.top + elementRect.height / 2 < scrollParentRect.top || // is the top half of the target element visible?
93
- elementRect.bottom - elementRect.height / 2 > scrollParentRect.bottom || // is the bottom half of the target element visible?
94
- elementRect.left + elementRect.width / 2 < scrollParentRect.left || // is the left half of the target element visible?
95
- elementRect.right - elementRect.width / 2 > scrollParentRect.right // is the right half of the target element visible?
103
+ isElementOutOfBounds(element, scrollParentRect) || // Is the element not visible in its scroll parent?
104
+ isElementOutOfBounds(element, viewportRect) // Is the element not visible in the viewport?
96
105
  ) {
97
106
  // reset the focus element and bail early
98
107
  elementRef.current = null;
@@ -150,12 +150,7 @@ export declare const useTabsItem: import("@workday/canvas-kit-react/common").Beh
150
150
  menu: {
151
151
  state: {
152
152
  stackRef: React.RefObject<HTMLDivElement>;
153
- targetRef: React.RefObject<HTMLButtonElement>; /**
154
- * The identifier of the tab. This identifier will be used in change events and for `initialTab`.
155
- * Must match the `data-id` of the associated tab panel. If this property is not provided, it will
156
- * default to a string representation of the the zero-based index of the Tab when it was
157
- * initialized.
158
- */
153
+ targetRef: React.RefObject<HTMLButtonElement>;
159
154
  initialFocusRef: React.RefObject<any> | undefined;
160
155
  returnFocusRef: React.RefObject<any> | undefined;
161
156
  placement: import("@popperjs/core").Placement;
@@ -346,12 +341,7 @@ export declare const TabsItem: import("@workday/canvas-kit-react/common").Elemen
346
341
  menu: {
347
342
  state: {
348
343
  stackRef: React.RefObject<HTMLDivElement>;
349
- targetRef: React.RefObject<HTMLButtonElement>; /**
350
- * The identifier of the tab. This identifier will be used in change events and for `initialTab`.
351
- * Must match the `data-id` of the associated tab panel. If this property is not provided, it will
352
- * default to a string representation of the the zero-based index of the Tab when it was
353
- * initialized.
354
- */
344
+ targetRef: React.RefObject<HTMLButtonElement>;
355
345
  initialFocusRef: React.RefObject<any> | undefined;
356
346
  returnFocusRef: React.RefObject<any> | undefined;
357
347
  placement: import("@popperjs/core").Placement;
@@ -1 +1 @@
1
- {"version":3,"file":"TabsItem.d.ts","sourceRoot":"","sources":["../../../../tabs/lib/TabsItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAIL,UAAU,EAGV,YAAY,EAKb,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAC,GAAG,EAAE,SAAS,EAAC,MAAM,kCAAkC,CAAC;AAYhE,MAAM,WAAW,aACf,SAAQ,YAAY,CAAC,OAAO,GAAG,EAAE,KAAK,CAAC,EACrC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACjC;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;OAaG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,aAAa;;;;oDA+EzB,CAAC;AAEF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2DAhHtB;;;;;eAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4HJ,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2DAnInB;;;;;eAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+IH,CAAC"}
1
+ {"version":3,"file":"TabsItem.d.ts","sourceRoot":"","sources":["../../../../tabs/lib/TabsItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAIL,UAAU,EAIV,YAAY,EAKb,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAC,GAAG,EAAE,SAAS,EAAC,MAAM,kCAAkC,CAAC;AAYhE,MAAM,WAAW,aACf,SAAQ,YAAY,CAAC,OAAO,GAAG,EAAE,KAAK,CAAC,EACrC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACjC;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;OAaG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,aAAa;;;;oDA+EzB,CAAC;AAEF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiBvB,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiBnB,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { colors, space, type, borderRadius, iconColors } from '@workday/canvas-kit-react/tokens';
3
- import { focusRing, hideMouseFocus, styled, createElemPropsHook, composeHooks, ellipsisStyles, EllipsisText, createSubcomponent, useModalityType, } from '@workday/canvas-kit-react/common';
3
+ import { focusRing, hideMouseFocus, styled, slugify, createElemPropsHook, composeHooks, ellipsisStyles, EllipsisText, createSubcomponent, useModalityType, } from '@workday/canvas-kit-react/common';
4
4
  import { Box } from '@workday/canvas-kit-react/layout';
5
5
  import { OverflowTooltip } from '@workday/canvas-kit-react/tooltip';
6
6
  import { SystemIcon } from '@workday/canvas-kit-react/icon';
@@ -86,7 +86,7 @@ export const useTabsItem = composeHooks(createElemPropsHook(useTabsModel)(({ sta
86
86
  type: 'button',
87
87
  role: 'tab',
88
88
  'aria-selected': selected,
89
- 'aria-controls': `tabpanel-${state.id}-${name}`,
89
+ 'aria-controls': slugify(`tabpanel-${state.id}-${name}`),
90
90
  };
91
91
  }), useListItemSelect, useOverflowListItemMeasure, useListItemRovingFocus, useListItemRegister);
92
92
  export const TabsItem = createSubcomponent('button')({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workday/canvas-kit-react",
3
- "version": "9.1.22",
3
+ "version": "9.1.24",
4
4
  "description": "The parent module that contains all Workday Canvas Kit React components",
5
5
  "author": "Workday, Inc. (https://www.workday.com)",
6
6
  "license": "Apache-2.0",
@@ -49,7 +49,7 @@
49
49
  "@emotion/styled": "^11.6.0",
50
50
  "@popperjs/core": "^2.5.4",
51
51
  "@workday/canvas-colors-web": "^2.0.0",
52
- "@workday/canvas-kit-popup-stack": "^9.1.22",
52
+ "@workday/canvas-kit-popup-stack": "^9.1.24",
53
53
  "@workday/canvas-system-icons-web": "^3.0.0",
54
54
  "@workday/design-assets-types": "^0.2.8",
55
55
  "chroma-js": "^2.1.0",
@@ -66,5 +66,5 @@
66
66
  "@workday/canvas-accent-icons-web": "^3.0.0",
67
67
  "@workday/canvas-applet-icons-web": "^2.0.0"
68
68
  },
69
- "gitHead": "b00fd1c6dd6d3c2653d4ec7e518df12427557562"
69
+ "gitHead": "823e15c48ab64f2997706232a523f503d87c80df"
70
70
  }
@@ -31,6 +31,23 @@ function getFocusableElement(element: Element | null): Element | null {
31
31
  return getFocusableElement(element.parentElement);
32
32
  }
33
33
 
34
+ /**
35
+ * Is the element outside of bounds. An element is outside of bounds if it is less than half visible.
36
+ */
37
+ function isElementOutOfBounds(
38
+ element: HTMLElement,
39
+ boundingRect: {top: number; bottom: number; left: number; right: number}
40
+ ) {
41
+ const elementRect = element.getBoundingClientRect();
42
+
43
+ return (
44
+ elementRect.top + elementRect.height / 2 < boundingRect.top || // is the top half of the target element visible?
45
+ elementRect.bottom - elementRect.height / 2 > boundingRect.bottom || // is the bottom half of the target element visible?
46
+ elementRect.left + elementRect.width / 2 < boundingRect.left || // is the left half of the target element visible?
47
+ elementRect.right - elementRect.width / 2 > boundingRect.right // is the right half of the target element visible?
48
+ );
49
+ }
50
+
34
51
  /**
35
52
  * Returns focus to the target element when the popup is hidden. This works well with
36
53
  * {@link useInitialFocus}. This should be used with {@link useFocusRedirect} or
@@ -100,16 +117,14 @@ export const useReturnFocus = createElemPropsHook(usePopupModel)(model => {
100
117
  }
101
118
  const scrollParent = getScrollParent(element);
102
119
  const scrollParentRect = scrollParent.getBoundingClientRect();
103
- const elementRect = element.getBoundingClientRect();
120
+ const viewportRect = {left: 0, top: 0, right: window.innerWidth, bottom: window.innerHeight};
104
121
 
105
122
  // Don't change focus if user focused on a different element like a `input` or the target
106
123
  // element isn't on at least halfway rendered on the screen.
107
124
  if (
108
125
  (elementRef.current && getFocusableElement(elementRef.current)) || // did the user click on a focusable element?
109
- elementRect.top + elementRect.height / 2 < scrollParentRect.top || // is the top half of the target element visible?
110
- elementRect.bottom - elementRect.height / 2 > scrollParentRect.bottom || // is the bottom half of the target element visible?
111
- elementRect.left + elementRect.width / 2 < scrollParentRect.left || // is the left half of the target element visible?
112
- elementRect.right - elementRect.width / 2 > scrollParentRect.right // is the right half of the target element visible?
126
+ isElementOutOfBounds(element, scrollParentRect) || // Is the element not visible in its scroll parent?
127
+ isElementOutOfBounds(element, viewportRect) // Is the element not visible in the viewport?
113
128
  ) {
114
129
  // reset the focus element and bail early
115
130
  elementRef.current = null;
@@ -6,6 +6,7 @@ import {
6
6
  hideMouseFocus,
7
7
  styled,
8
8
  StyledType,
9
+ slugify,
9
10
  createElemPropsHook,
10
11
  composeHooks,
11
12
  ExtractProps,
@@ -172,7 +173,7 @@ export const useTabsItem = composeHooks(
172
173
  type: 'button' as const,
173
174
  role: 'tab' as const,
174
175
  'aria-selected': selected,
175
- 'aria-controls': `tabpanel-${state.id}-${name}`,
176
+ 'aria-controls': slugify(`tabpanel-${state.id}-${name}`),
176
177
  };
177
178
  }),
178
179
  useListItemSelect,