From 7e2feaa521a3ed9d1de929bad1816ae8fd1eed15 Mon Sep 17 00:00:00 2001 From: dgreif Date: Wed, 23 Jun 2021 14:15:11 -0700 Subject: [PATCH 1/5] feat(Overlay): slide away from anchor based on position --- docs/content/Overlay.mdx | 6 +-- src/AnchoredOverlay/AnchoredOverlay.tsx | 3 +- src/Overlay.tsx | 57 ++++++++++++++++++++----- src/behaviors/anchoredPosition.ts | 15 +++++-- src/hooks/useAnchoredPosition.ts | 8 ++-- src/hooks/useCombinedRefs.ts | 2 +- 6 files changed, 67 insertions(+), 24 deletions(-) diff --git a/docs/content/Overlay.mdx b/docs/content/Overlay.mdx index 685db5826de..5cc607101ac 100644 --- a/docs/content/Overlay.mdx +++ b/docs/content/Overlay.mdx @@ -73,8 +73,8 @@ render() | initialFocusRef | `React.RefObject` | `undefined` | Optional. Ref for the element to focus when the `Overlay` is opened. If nothing is provided, the first focusable element in the `Overlay` body is focused. | | anchorRef | `React.RefObject` | `undefined` | Required. Element the `Overlay` should be anchored to. | | returnFocusRef | `React.RefObject` | `undefined` | Required. Ref for the element to focus when the `Overlay` is closed. | -| onClickOutside | `function` | `undefined` | Required. Function to call when clicking outside of the `Overlay`. Typically this function sets the `Overlay` visibility state to `false`. | -| onEscape | `function` | `undefined` | Required. Function to call when user presses `Escape`. Typically this function sets the `Overlay` visibility state to `false`. | +| onClickOutside | `function` | `undefined` | Required. Function to call when clicking outside of the `Overlay`. Typically this function removes the Overlay. | +| onEscape | `function` | `undefined` | Required. Function to call when user presses `Escape`. Typically this function removes the Overlay. | | width | `'small' │ 'medium' │ 'large' │ 'xlarge' │ 'xxlarge' │ 'auto'` | `auto` | Sets the width of the `Overlay`, pick from our set list of widths, or pass `auto` to automatically set the width based on the content of the `Overlay`. `small` corresponds to `256px`, `medium` corresponds to `320px`, `large` corresponds to `480px`, `xlarge` corresponds to `640px`, `xxlarge` corresponds to `960px`. | | height | `'xsmall', 'small', 'medium', 'large', 'xlarge', 'auto'` | `auto` | Sets the height of the `Overlay`, pick from our set list of heights, or pass `auto` to automatically set the height based on the content of the `Overlay`. `xsmall` corresponds to `192px`, `small` corresponds to `256px`, `medium` corresponds to `320px`, `large` corresponds to `432px`, `xlarge` corresponds to `600px`. | -| visibility | `'visible', 'hidden'` | `visible` | Sets the visibility of the `Overlay`. | +| anchorSide | `AnchorSide` | undefined | Optional. If provided, the Overlay will slide into position from the side of the anchor with a brief animation | diff --git a/src/AnchoredOverlay/AnchoredOverlay.tsx b/src/AnchoredOverlay/AnchoredOverlay.tsx index 436605f8e6a..848977db137 100644 --- a/src/AnchoredOverlay/AnchoredOverlay.tsx +++ b/src/AnchoredOverlay/AnchoredOverlay.tsx @@ -124,7 +124,7 @@ export const AnchoredOverlay: React.FC = ({ [overlayRef.current] ) const overlayPosition = useMemo(() => { - return position && {top: `${position.top}px`, left: `${position.left}px`} + return position && {top: `${position.top}px`, left: `${position.left}px`, anchorSide: position.anchorSide} }, [position]) useFocusZone({ @@ -154,7 +154,6 @@ export const AnchoredOverlay: React.FC = ({ onEscape={onEscape} ref={updateOverlayRef} role="listbox" - visibility={position ? 'visible' : 'hidden'} height={height} width={width} {...overlayPosition} diff --git a/src/Overlay.tsx b/src/Overlay.tsx index 3696dfbccdc..276013a2427 100644 --- a/src/Overlay.tsx +++ b/src/Overlay.tsx @@ -6,12 +6,13 @@ import {useOverlay, TouchOrMouseEvent} from './hooks' import Portal from './Portal' import sx, {SxProp} from './sx' import {useCombinedRefs} from './hooks/useCombinedRefs' +import {AnchorSide} from './behaviors/anchoredPosition' type StyledOverlayProps = { width?: keyof typeof widthMap height?: keyof typeof heightMap maxHeight?: keyof Omit - visibility?: 'visible' | 'hidden' + anchorSide?: AnchorSide } const heightMap = { @@ -33,6 +34,20 @@ const widthMap = { auto: 'auto' } +function getSlideAnimationFactors(anchorSide?: AnchorSide): {x: number; y: number} { + if (anchorSide?.endsWith('bottom')) { + return {x: 0, y: -1} + } else if (anchorSide?.endsWith('top')) { + return {x: 0, y: 1} + } else if (anchorSide?.endsWith('right')) { + return {x: -1, y: 0} + } else if (anchorSide?.endsWith('left')) { + return {x: 1, y: 0} + } + + return {x: 0, y: 0} +} + const StyledOverlay = styled.div` background-color: ${get('colors.bg.overlay')}; box-shadow: ${get('shadows.overlay.shadow')}; @@ -44,18 +59,30 @@ const StyledOverlay = styled.div widthMap[props.width || 'auto']}; border-radius: 12px; overflow: hidden; - animation: overlay-appear 200ms ${get('animation.easeOutCubic')}; + animation: overlay-appear 200ms ${get('animation.easeOutCubic')}, + overlay-slide var(--slide-animation-timing, 200ms) ${get('animation.easeOutCubic')}; @keyframes overlay-appear { 0% { opacity: 0; - transform: translateY(${get('space.2')}); } 100% { opacity: 1; } } - visibility: ${props => props.visibility || 'visible'}; + + // split from overlay-appear so that the timing can be set to 0 initially or if we don't know which side to slide from + @keyframes overlay-slide { + 0% { + transform: translate( + calc(var(--slide-animation-x-factor) * ${get('space.2')}), + calc(var(--slide-animation-y-factor) * ${get('space.2')}) + ); + } + 100% { + } + } + :focus { outline: none; } @@ -69,9 +96,8 @@ export type OverlayProps = { returnFocusRef: React.RefObject onClickOutside: (e: TouchOrMouseEvent) => void onEscape: (e: KeyboardEvent) => void - visibility?: 'visible' | 'hidden' [additionalKey: string]: unknown -} & Omit, 'visibility' | keyof SystemPositionProps> +} & Omit, keyof SystemPositionProps> /** * An `Overlay` is a flexible floating surface, used to display transient content such as menus, @@ -80,12 +106,12 @@ export type OverlayProps = { * @param ignoreClickRefs Optional. An array of ref objects to ignore clicks on in the `onOutsideClick` behavior. This is often used to ignore clicking on the element that toggles the open/closed state for the `Overlay` to prevent the `Overlay` from being toggled twice. * @param initialFocusRef Optional. Ref for the element to focus when the `Overlay` is opened. If nothing is provided, the first focusable element in the `Overlay` body is focused. * @param returnFocusRef Required. Ref for the element to focus when the `Overlay` is closed. - * @param onClickOutside Required. Function to call when clicking outside of the `Overlay`. Typically this function sets the `Overlay` visibility state to `false`. - * @param onEscape Required. Function to call when user presses `Escape`. Typically this function sets the `Overlay` visibility state to `false`. + * @param onClickOutside Required. Function to call when clicking outside of the `Overlay`. Typically this function removes the Overlay. + * @param onEscape Required. Function to call when user presses `Escape`. Typically this function removes the Overlay. * @param width Sets the width of the `Overlay`, pick from our set list of widths, or pass `auto` to automatically set the width based on the content of the `Overlay`. `small` corresponds to `256px`, `medium` corresponds to `320px`, `large` corresponds to `480px`, `xlarge` corresponds to `640px`, `xxlarge` corresponds to `960px`. * @param height Sets the height of the `Overlay`, pick from our set list of heights, or pass `auto` to automatically set the height based on the content of the `Overlay`, or pass `initial` to set the height based on the initial content of the `Overlay` (i.e. ignoring content changes). `xsmall` corresponds to `192px`, `small` corresponds to `256px`, `medium` corresponds to `320px`, `large` corresponds to `432px`, `xlarge` corresponds to `600px`. * @param maxHeight Sets the maximum height of the `Overlay`, pick from our set list of heights. `xsmall` corresponds to `192px`, `small` corresponds to `256px`, `medium` corresponds to `320px`, `large` corresponds to `432px`, `xlarge` corresponds to `600px`. - * @param visibility Sets the visibility of the `Overlay` + * @param anchorSide If provided, the Overlay will slide into position from the side of the anchor with a brief animation */ const Overlay = React.forwardRef( ( @@ -96,14 +122,15 @@ const Overlay = React.forwardRef( returnFocusRef, ignoreClickRefs, onEscape, - visibility, height, + anchorSide, ...rest }, forwardedRef ): ReactElement => { const overlayRef = useRef(null) const combinedRef = useCombinedRefs(overlayRef, forwardedRef) + const slideAnimationFactors = getSlideAnimationFactors(anchorSide) useOverlay({ overlayRef, @@ -128,7 +155,15 @@ const Overlay = React.forwardRef( height={height} {...rest} ref={combinedRef} - visibility={visibility} + style={ + { + '--slide-animation-x-factor': slideAnimationFactors.x, + '--slide-animation-y-factor': slideAnimationFactors.y, + '--slide-animation-timing': + slideAnimationFactors.x === 0 && slideAnimationFactors.y === 0 ? '0' : undefined // 0 if we don't want to animate, fallback in css if we do + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any + } /> ) diff --git a/src/behaviors/anchoredPosition.ts b/src/behaviors/anchoredPosition.ts index 004c6726d56..e9f2159fd0e 100644 --- a/src/behaviors/anchoredPosition.ts +++ b/src/behaviors/anchoredPosition.ts @@ -109,6 +109,12 @@ interface Position { left: number } +export interface AnchorPosition { + top: number + left: number + anchorSide: AnchorSide +} + interface BoxPosition extends Size, Position {} /** @@ -125,7 +131,7 @@ export function getAnchoredPosition( floatingElement: Element, anchorElement: Element | DOMRect, settings: Partial = {} -): {top: number; left: number} { +): AnchorPosition { const parentElement = getPositionedParent(floatingElement) const clippingRect = getClippingRect(parentElement) @@ -258,7 +264,7 @@ function pureCalculateAnchoredPosition( floatingRect: Size, anchorRect: BoxPosition, {side, align, allowOutOfBounds, anchorOffset, alignmentOffset}: PositionSettings -): {top: number; left: number} { +): AnchorPosition { // Compute the relative viewport rect, to bring it into the same coordinate space as `pos` const relativeViewportRect: BoxPosition = { top: viewportRect.top - relativePosition.top, @@ -268,6 +274,7 @@ function pureCalculateAnchoredPosition( } let pos = calculatePosition(floatingRect, anchorRect, side, align, anchorOffset, alignmentOffset) + let anchorSide = side pos.top -= relativePosition.top pos.left -= relativePosition.left @@ -290,6 +297,7 @@ function pureCalculateAnchoredPosition( pos = calculatePosition(floatingRect, anchorRect, nextSide, align, anchorOffset, alignmentOffset) pos.top -= relativePosition.top pos.left -= relativePosition.left + anchorSide = nextSide } } // At this point we've flipped the position if applicable. Now just nudge until it's on-screen. @@ -311,7 +319,8 @@ function pureCalculateAnchoredPosition( } } } - return pos + + return {...pos, anchorSide} } /** diff --git a/src/hooks/useAnchoredPosition.ts b/src/hooks/useAnchoredPosition.ts index 7ba0a40a4fb..2ae88526a60 100644 --- a/src/hooks/useAnchoredPosition.ts +++ b/src/hooks/useAnchoredPosition.ts @@ -1,5 +1,5 @@ import React from 'react' -import {PositionSettings, getAnchoredPosition} from '../behaviors/anchoredPosition' +import {PositionSettings, getAnchoredPosition, AnchorPosition} from '../behaviors/anchoredPosition' import {useProvidedRefOrCreate} from './useProvidedRefOrCreate' export interface AnchoredPositionHookSettings extends Partial { @@ -22,12 +22,12 @@ export function useAnchoredPosition( ): { floatingElementRef: React.RefObject anchorElementRef: React.RefObject - position: {top: number; left: number} | undefined + position: AnchorPosition | undefined } { const floatingElementRef = useProvidedRefOrCreate(settings?.floatingElementRef) const anchorElementRef = useProvidedRefOrCreate(settings?.anchorElementRef) - const [position, setPosition] = React.useState<{top: number; left: number} | undefined>(undefined) - React.useEffect(() => { + const [position, setPosition] = React.useState(undefined) + React.useLayoutEffect(() => { if (floatingElementRef.current instanceof Element && anchorElementRef.current instanceof Element) { setPosition(getAnchoredPosition(floatingElementRef.current, anchorElementRef.current, settings)) } else { diff --git a/src/hooks/useCombinedRefs.ts b/src/hooks/useCombinedRefs.ts index 0fef707de7d..0eedc6beb5e 100644 --- a/src/hooks/useCombinedRefs.ts +++ b/src/hooks/useCombinedRefs.ts @@ -11,7 +11,7 @@ import React, {ForwardedRef, useRef} from 'react' export function useCombinedRefs(...refs: (ForwardedRef | null | undefined)[]) { const combinedRef = useRef(null) - React.useEffect(() => { + React.useLayoutEffect(() => { function setRefs(current: T | null = null) { for (const ref of refs) { if (!ref) { From 5835f863297a13c45db4a800e6e1b9d5e7fc731a Mon Sep 17 00:00:00 2001 From: dgreif Date: Thu, 24 Jun 2021 15:26:15 -0700 Subject: [PATCH 2/5] fix: handle position changes when re-opening AnchoredOverlay --- src/AnchoredOverlay/AnchoredOverlay.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/AnchoredOverlay/AnchoredOverlay.tsx b/src/AnchoredOverlay/AnchoredOverlay.tsx index 848977db137..9bae7d87ac8 100644 --- a/src/AnchoredOverlay/AnchoredOverlay.tsx +++ b/src/AnchoredOverlay/AnchoredOverlay.tsx @@ -1,4 +1,4 @@ -import React, {useCallback, useMemo} from 'react' +import React, {useCallback, useEffect, useMemo} from 'react' import Overlay, {OverlayProps} from '../Overlay' import {FocusTrapHookSettings, useFocusTrap} from '../hooks/useFocusTrap' import {FocusZoneHookSettings, useFocusZone} from '../hooks/useFocusZone' @@ -127,6 +127,13 @@ export const AnchoredOverlay: React.FC = ({ return position && {top: `${position.top}px`, left: `${position.left}px`, anchorSide: position.anchorSide} }, [position]) + useEffect(() => { + // ensure overlay ref gets cleared when closed, so position can reset between closing/re-opening + if (!open && overlayRef.current) { + updateOverlayRef(null) + } + }, [open, overlayRef, updateOverlayRef]) + useFocusZone({ containerRef: overlayRef, disabled: !open || !position, From db69e072593a12c20aece971e81a98840b0448f3 Mon Sep 17 00:00:00 2001 From: dgreif Date: Fri, 25 Jun 2021 16:18:31 -0700 Subject: [PATCH 3/5] refactor: use js animation for slide to fix safari --- src/Overlay.tsx | 58 +++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/src/Overlay.tsx b/src/Overlay.tsx index 276013a2427..29d75f18e27 100644 --- a/src/Overlay.tsx +++ b/src/Overlay.tsx @@ -1,5 +1,5 @@ import styled from 'styled-components' -import React, {ReactElement, useEffect, useRef} from 'react' +import React, {ReactElement, useEffect, useLayoutEffect, useRef} from 'react' import {get, COMMON, POSITION, SystemPositionProps, SystemCommonProps} from './constants' import {ComponentProps} from './utils/types' import {useOverlay, TouchOrMouseEvent} from './hooks' @@ -7,6 +7,7 @@ import Portal from './Portal' import sx, {SxProp} from './sx' import {useCombinedRefs} from './hooks/useCombinedRefs' import {AnchorSide} from './behaviors/anchoredPosition' +import {useTheme} from './ThemeProvider' type StyledOverlayProps = { width?: keyof typeof widthMap @@ -33,8 +34,9 @@ const widthMap = { xxlarge: '960px', auto: 'auto' } +const animationDuration = 200 -function getSlideAnimationFactors(anchorSide?: AnchorSide): {x: number; y: number} { +function getSlideAnimationStartingVector(anchorSide?: AnchorSide): {x: number; y: number} { if (anchorSide?.endsWith('bottom')) { return {x: 0, y: -1} } else if (anchorSide?.endsWith('top')) { @@ -59,8 +61,7 @@ const StyledOverlay = styled.div widthMap[props.width || 'auto']}; border-radius: 12px; overflow: hidden; - animation: overlay-appear 200ms ${get('animation.easeOutCubic')}, - overlay-slide var(--slide-animation-timing, 200ms) ${get('animation.easeOutCubic')}; + animation: overlay-appear ${animationDuration}ms ${get('animation.easeOutCubic')}; @keyframes overlay-appear { 0% { @@ -71,18 +72,6 @@ const StyledOverlay = styled.div( ): ReactElement => { const overlayRef = useRef(null) const combinedRef = useCombinedRefs(overlayRef, forwardedRef) - const slideAnimationFactors = getSlideAnimationFactors(anchorSide) + const {theme} = useTheme() + const slideAnimationDistance = parseInt(get('space.2')(theme).replace('px', '')) + const slideAnimationEasing = get('animation.easeOutCubic')(theme) useOverlay({ overlayRef, @@ -147,24 +138,25 @@ const Overlay = React.forwardRef( } }, [height, combinedRef]) + useLayoutEffect(() => { + const {x, y} = getSlideAnimationStartingVector(anchorSide) + if ((!x && !y) || !overlayRef.current?.animate) { + return + } + + // JS animation is required because Safari does not allow css animations to start paused and then run + overlayRef.current.animate( + {transform: [`translate(${slideAnimationDistance * x}px, ${slideAnimationDistance * y}px)`, `translate(0, 0)`]}, + { + duration: animationDuration, + easing: slideAnimationEasing + } + ) + }, [anchorSide, slideAnimationDistance, slideAnimationEasing]) + return ( - + ) } From 108ead588257baa8e7de43bfee79e697ce6ab795 Mon Sep 17 00:00:00 2001 From: Clay Miller Date: Tue, 29 Jun 2021 12:22:30 -0400 Subject: [PATCH 4/5] fix: Tests were failing with Axe violations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - https://dequeuniversity.com/rules/axe/4.1/aria-dialog-name - https://dequeuniversity.com/rules/axe/4.2/presentation-role-conflict - https://www.w3.org/TR/wai-aria-practices-1.1/examples/menu-button/menu-button-links.html First, 'Overlay's aren’t 'listbox'es, because (when used in 'DropdownMenu' or 'ActionMenu') they contain 'menuitem's, 'menuitemradio's, or 'menuitemcheckbox'es. Second, 'Overlay's aren’t 'dialog's, because (as demonstrated in the WAI ARIA practices page linked above), 'menu's need not be contained in a 'dialog', and also (as noted in the 'aria-dialog-name' link above), 'dialog's must have an 'aria-label', 'aria-labelledby', or 'title', but neither 'DropdownMenu' nor 'ActionMenu' have any kind of header element that could be used for this. Third, if 'Overlay's are 'none', they can’t be focusable (as noted in the 'presentation-role-conflict' link above), but one of our hooks (maybe 'FocusTrap', maybe 'FocusZone') was setting 'tabIndex' to '0' (in the test component), because it did not contain a focusable child. This PR adds a focusable button child so the 'none' 'Overlay' container won’t receive 'tabIndex' '0'. --- src/AnchoredOverlay/AnchoredOverlay.tsx | 4 +- src/Overlay.tsx | 6 +-- src/__tests__/AnchoredOverlay.tsx | 28 ++++++---- src/__tests__/Overlay.tsx | 54 ++++++++++--------- .../__snapshots__/ActionMenu.tsx.snap | 2 +- .../__snapshots__/AnchoredOverlay.tsx.snap | 47 ++++++++++------ .../__snapshots__/DropdownMenu.tsx.snap | 2 +- .../__snapshots__/SelectPanel.tsx.snap | 2 +- 8 files changed, 85 insertions(+), 60 deletions(-) diff --git a/src/AnchoredOverlay/AnchoredOverlay.tsx b/src/AnchoredOverlay/AnchoredOverlay.tsx index 9bae7d87ac8..baab28528ed 100644 --- a/src/AnchoredOverlay/AnchoredOverlay.tsx +++ b/src/AnchoredOverlay/AnchoredOverlay.tsx @@ -148,7 +148,7 @@ export const AnchoredOverlay: React.FC = ({ ref: anchorRef, id: anchorId, 'aria-labelledby': anchorId, - 'aria-haspopup': 'listbox', + 'aria-haspopup': 'true', tabIndex: 0, onClick: onAnchorClick, onKeyDown: onAnchorKeyDown @@ -160,7 +160,7 @@ export const AnchoredOverlay: React.FC = ({ ignoreClickRefs={[anchorRef]} onEscape={onEscape} ref={updateOverlayRef} - role="listbox" + role="none" height={height} width={width} {...overlayPosition} diff --git a/src/Overlay.tsx b/src/Overlay.tsx index 29d75f18e27..36bedd4a6d9 100644 --- a/src/Overlay.tsx +++ b/src/Overlay.tsx @@ -1,5 +1,5 @@ import styled from 'styled-components' -import React, {ReactElement, useEffect, useLayoutEffect, useRef} from 'react' +import React, {ReactElement, useEffect, useLayoutEffect, useRef, useState} from 'react' import {get, COMMON, POSITION, SystemPositionProps, SystemCommonProps} from './constants' import {ComponentProps} from './utils/types' import {useOverlay, TouchOrMouseEvent} from './hooks' @@ -106,7 +106,7 @@ const Overlay = React.forwardRef( ( { onClickOutside, - role = 'dialog', + role = 'none', initialFocusRef, returnFocusRef, ignoreClickRefs, @@ -156,7 +156,7 @@ const Overlay = React.forwardRef( return ( - + ) } diff --git a/src/__tests__/AnchoredOverlay.tsx b/src/__tests__/AnchoredOverlay.tsx index 90e9aaff497..f06446fc0ef 100644 --- a/src/__tests__/AnchoredOverlay.tsx +++ b/src/__tests__/AnchoredOverlay.tsx @@ -5,6 +5,8 @@ import {render as HTMLRender, cleanup, fireEvent} from '@testing-library/react' import {axe, toHaveNoViolations} from 'jest-axe' import 'babel-polyfill' import {Button} from '../index' +import theme from '../theme' +import {BaseStyles, ThemeProvider} from '..' expect.extend(toHaveNoViolations) type TestComponentSettings = { @@ -34,14 +36,18 @@ const AnchoredOverlayTestComponent = ({ [onCloseCallback] ) return ( - } - > - Contents - + + + } + > + + + + ) } @@ -78,7 +84,7 @@ describe('AnchoredOverlay', () => { const anchoredOverlay = HTMLRender( ) - const anchor = anchoredOverlay.baseElement.querySelector('[aria-haspopup="listbox"]')! + const anchor = anchoredOverlay.baseElement.querySelector('[aria-haspopup="true"]')! fireEvent.click(anchor) expect(mockOpenCallback).toHaveBeenCalledTimes(1) @@ -92,7 +98,7 @@ describe('AnchoredOverlay', () => { const anchoredOverlay = HTMLRender( ) - const anchor = anchoredOverlay.baseElement.querySelector('[aria-haspopup="listbox"]')! + const anchor = anchoredOverlay.baseElement.querySelector('[aria-haspopup="true"]')! fireEvent.keyDown(anchor, {key: ' '}) expect(mockOpenCallback).toHaveBeenCalledTimes(1) @@ -127,7 +133,7 @@ describe('AnchoredOverlay', () => { onCloseCallback={mockCloseCallback} /> ) - const overlay = await anchoredOverlay.findByRole('listbox') + const overlay = await anchoredOverlay.findByRole('none') fireEvent.keyDown(overlay, {key: 'Escape'}) expect(mockOpenCallback).toHaveBeenCalledTimes(0) diff --git a/src/__tests__/Overlay.tsx b/src/__tests__/Overlay.tsx index 21ef6374335..ddc6bf08cf0 100644 --- a/src/__tests__/Overlay.tsx +++ b/src/__tests__/Overlay.tsx @@ -3,6 +3,8 @@ import {Overlay, Position, Flex, Text, ButtonDanger, Button} from '..' import {render, cleanup, waitFor, fireEvent, act} from '@testing-library/react' import userEvent from '@testing-library/user-event' import {axe, toHaveNoViolations} from 'jest-axe' +import theme from '../theme' +import {BaseStyles, ThemeProvider} from '..' expect.extend(toHaveNoViolations) @@ -22,30 +24,34 @@ const TestComponent = ({initialFocus, callback}: TestComponentSettings) => { } } return ( - - - - {isOpen ? ( - - - Are you sure? - Cancel - - - - ) : null} - + + + + + + {isOpen ? ( + + + Are you sure? + Cancel + + + + ) : null} + + + ) } diff --git a/src/__tests__/__snapshots__/ActionMenu.tsx.snap b/src/__tests__/__snapshots__/ActionMenu.tsx.snap index a92e9626f63..43aaddf600d 100644 --- a/src/__tests__/__snapshots__/ActionMenu.tsx.snap +++ b/src/__tests__/__snapshots__/ActionMenu.tsx.snap @@ -68,7 +68,7 @@ exports[`ActionMenu renders consistently 1`] = ` } + + `; diff --git a/src/__tests__/__snapshots__/DropdownMenu.tsx.snap b/src/__tests__/__snapshots__/DropdownMenu.tsx.snap index 0ed5d845df6..0324c63d005 100644 --- a/src/__tests__/__snapshots__/DropdownMenu.tsx.snap +++ b/src/__tests__/__snapshots__/DropdownMenu.tsx.snap @@ -72,7 +72,7 @@ exports[`DropdownMenu renders consistently 1`] = ` }