From 1460e1d270c68d17972cf0f5abf9bae185f6d3aa Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Wed, 14 Feb 2024 15:56:19 +0100 Subject: [PATCH 01/10] cleanup: outdated comment --- .../src/drafts/SelectPanel2/SelectPanel.examples.stories.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/react/src/drafts/SelectPanel2/SelectPanel.examples.stories.tsx b/packages/react/src/drafts/SelectPanel2/SelectPanel.examples.stories.tsx index a4057183ced..61144ac0d2c 100644 --- a/packages/react/src/drafts/SelectPanel2/SelectPanel.examples.stories.tsx +++ b/packages/react/src/drafts/SelectPanel2/SelectPanel.examples.stories.tsx @@ -599,9 +599,7 @@ export const ShortSelectPanel = () => { return ( <>

Short SelectPanel

-

- Use height=fit-content to match height of contents -

+ Notify me:{' '} From d37dd5468187db280424cadb7ac9c6f76359c861 Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Wed, 14 Feb 2024 15:56:40 +0100 Subject: [PATCH 02/10] full screen based on media query --- .../react/src/drafts/SelectPanel2/SelectPanel.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/react/src/drafts/SelectPanel2/SelectPanel.tsx b/packages/react/src/drafts/SelectPanel2/SelectPanel.tsx index 22db6fa66d3..12915a44e13 100644 --- a/packages/react/src/drafts/SelectPanel2/SelectPanel.tsx +++ b/packages/react/src/drafts/SelectPanel2/SelectPanel.tsx @@ -266,6 +266,19 @@ const Panel: React.FC = ({ '75%': {transform: 'scale(0.95, 1.05)'}, '100%': {transform: 'scale(1, 1)'}, }, + + // always full screen on narrow screen + '@media (max-width: 768px)': { + margin: 0, + top: 0, + left: 0, + width: '100%', + maxWidth: '100vw', + height: '100%', + maxHeight: '100vh', + '--max-height': '100vh', + borderRadius: 'unset', + }, }} {...props} onClick={event => { From cb1af31c5cd4da807dbd275e0a310036cb56b2a4 Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Wed, 14 Feb 2024 15:57:15 +0100 Subject: [PATCH 03/10] automated responsive button size --- .../react/src/drafts/SelectPanel2/SelectPanel.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/react/src/drafts/SelectPanel2/SelectPanel.tsx b/packages/react/src/drafts/SelectPanel2/SelectPanel.tsx index 12915a44e13..01794f1a4b5 100644 --- a/packages/react/src/drafts/SelectPanel2/SelectPanel.tsx +++ b/packages/react/src/drafts/SelectPanel2/SelectPanel.tsx @@ -27,6 +27,7 @@ import {useFocusZone} from '../../hooks/useFocusZone' import {StyledOverlay, OverlayProps, heightMap} from '../../Overlay/Overlay' import InputLabel from '../../internal/components/InputLabel' import {invariant} from '../../utils/invariant' +import {ResponsiveValue, useResponsiveValue} from '../../hooks/useResponsiveValue' const SelectPanelContext = React.createContext<{ title: string @@ -50,6 +51,8 @@ const SelectPanelContext = React.createContext<{ moveFocusToList: () => {}, }) +const responsiveButtonSizes: ResponsiveValue<'small' | 'medium'> = {narrow: 'medium', regular: 'small'} + export type SelectPanelProps = { title: string description?: string @@ -464,6 +467,7 @@ const SelectPanelFooter = ({...props}) => { const {onCancel, selectionVariant} = React.useContext(SelectPanelContext) const hidePrimaryActions = selectionVariant === 'instant' + const buttonSize = useResponsiveValue(responsiveButtonSizes, 'small') if (hidePrimaryActions && !props.children) { // nothing to render @@ -489,10 +493,10 @@ const SelectPanelFooter = ({...props}) => { {hidePrimaryActions ? null : ( - - @@ -503,13 +507,15 @@ const SelectPanelFooter = ({...props}) => { } const SecondaryButton: React.FC = props => { - return ) From 3b55bff8c2622bfb7334bcc71b957e120e7c3094 Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Wed, 14 Feb 2024 16:47:39 +0100 Subject: [PATCH 04/10] use ResponsiveVariants --- .../SelectPanel.playground.stories.tsx | 2 ++ .../src/drafts/SelectPanel2/SelectPanel.tsx | 27 ++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/packages/react/src/drafts/SelectPanel2/SelectPanel.playground.stories.tsx b/packages/react/src/drafts/SelectPanel2/SelectPanel.playground.stories.tsx index 16d3ca80a39..7f740b7928d 100644 --- a/packages/react/src/drafts/SelectPanel2/SelectPanel.playground.stories.tsx +++ b/packages/react/src/drafts/SelectPanel2/SelectPanel.playground.stories.tsx @@ -12,6 +12,7 @@ export default { title: 'Select labels', selectionVariant: 'multiple', secondaryActionVariant: 'button', + variant: {regular: 'anchored', narrow: 'full-screen'}, }, argTypes: { secondaryActionVariant: { @@ -92,6 +93,7 @@ export const Playground: StoryFn = args => { = {narrow: 'medium', regular: 'small'} +type ResponsiveVariant = ResponsiveValue<'anchored' | 'modal', 'full-screen' | 'bottom-sheet'> export type SelectPanelProps = { title: string description?: string - variant?: 'anchored' | 'modal' + variant?: 'anchored' | 'modal' | ResponsiveVariant selectionVariant?: ActionListProps['selectionVariant'] | 'instant' id?: string @@ -79,7 +80,7 @@ export type SelectPanelProps = { const Panel: React.FC = ({ title, description, - variant = 'anchored', + variant: propsVariant, selectionVariant = 'multiple', id, @@ -97,6 +98,12 @@ const Panel: React.FC = ({ }) => { const [internalOpen, setInternalOpen] = React.useState(defaultOpen) + const responsiveVariants = Object.assign( + {regular: 'anchored', narrow: 'full-screen'}, // defaults + typeof propsVariant === 'object' ? propsVariant : {regular: propsVariant}, + ) + const currentVariant = useResponsiveValue(responsiveVariants, 'anchored') + // sync open state with props if (propsOpen !== undefined && internalOpen !== propsOpen) setInternalOpen(propsOpen) @@ -249,6 +256,7 @@ const Panel: React.FC = ({ width={width} height="fit-content" maxHeight={maxHeight} + data-variant={currentVariant} sx={{ '--max-height': heightMap[maxHeight], // reset dialog default styles @@ -256,9 +264,6 @@ const Panel: React.FC = ({ padding: 0, '&[open]': {display: 'flex'}, // to fit children - ...(variant === 'anchored' ? {margin: 0, top: position?.top, left: position?.left} : {}), - '::backdrop': {backgroundColor: variant === 'anchored' ? 'transparent' : 'primer.canvas.backdrop'}, - '& [data-selectpanel-primary-actions]': { animation: footerAnimationEnabled ? 'selectpanel-gelatine 350ms linear' : 'none', }, @@ -270,8 +275,16 @@ const Panel: React.FC = ({ '100%': {transform: 'scale(1, 1)'}, }, - // always full screen on narrow screen - '@media (max-width: 768px)': { + '&[data-variant=anchored], &[data-variant="full-screen"]': { + margin: 0, + top: position?.top, + left: position?.left, + '::backdrop': {backgroundColor: 'transparent'}, + }, + '&[data-variant=modal]': { + '::backdrop': {backgroundColor: 'primer.canvas.backdrop'}, + }, + '&[data-variant="full-screen"]': { margin: 0, top: 0, left: 0, From 84baa82420d5de6df349229f8c437ddc4b1c6aec Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Wed, 14 Feb 2024 17:13:58 +0100 Subject: [PATCH 05/10] add responsive story --- .../SelectPanel.features.stories.tsx | 152 +++++++++++++++++- 1 file changed, 151 insertions(+), 1 deletion(-) diff --git a/packages/react/src/drafts/SelectPanel2/SelectPanel.features.stories.tsx b/packages/react/src/drafts/SelectPanel2/SelectPanel.features.stories.tsx index f3750e1e6fe..9a5be1afdd0 100644 --- a/packages/react/src/drafts/SelectPanel2/SelectPanel.features.stories.tsx +++ b/packages/react/src/drafts/SelectPanel2/SelectPanel.features.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' import {SelectPanel} from './SelectPanel' -import {ActionList, Avatar, Box, Button, Link, Text, ToggleSwitch} from '../../index' +import {ActionList, Avatar, Box, Button, Link, SegmentedControl, Text, ToggleSwitch} from '../../index' import {TagIcon, GearIcon} from '@primer/octicons-react' import data from './mock-story-data' @@ -437,3 +437,153 @@ export const AsModal = () => { ) } + +export const ResponsiveVariants = () => { + /* Selection */ + const initialAssigneeIds = data.issue.assigneeIds // mock initial state + const [selectedAssigneeIds, setSelectedAssigneeIds] = React.useState(initialAssigneeIds) + + const onCollaboratorSelect = (colloratorId: string) => { + if (!selectedAssigneeIds.includes(colloratorId)) setSelectedAssigneeIds([...selectedAssigneeIds, colloratorId]) + else setSelectedAssigneeIds(selectedAssigneeIds.filter(id => id !== colloratorId)) + } + + const onClearSelection = () => setSelectedAssigneeIds([]) + const onSubmit = () => { + data.issue.assigneeIds = selectedAssigneeIds // pretending to persist changes + } + + /* Filtering */ + const [filteredUsers, setFilteredUsers] = React.useState(data.collaborators) + const [query, setQuery] = React.useState('') + + const onSearchInputChange: React.ChangeEventHandler = event => { + const query = event.currentTarget.value + setQuery(query) + + if (query === '') setFilteredUsers(data.collaborators) + else { + setFilteredUsers( + data.collaborators + .map(collaborator => { + if (collaborator.login.toLowerCase().startsWith(query)) return {priority: 1, collaborator} + else if (collaborator.name.startsWith(query)) return {priority: 2, collaborator} + else if (collaborator.login.toLowerCase().includes(query)) return {priority: 3, collaborator} + else if (collaborator.name.toLowerCase().includes(query)) return {priority: 4, collaborator} + else return {priority: -1, collaborator} + }) + .filter(result => result.priority > 0) + .map(result => result.collaborator), + ) + } + } + + const sortingFn = (itemA: {id: string}, itemB: {id: string}) => { + const initialSelectedIds = data.issue.assigneeIds + if (initialSelectedIds.includes(itemA.id) && initialSelectedIds.includes(itemB.id)) return 1 + else if (initialSelectedIds.includes(itemA.id)) return -1 + else if (initialSelectedIds.includes(itemB.id)) return 1 + else return 1 + } + + const itemsToShow = query ? filteredUsers : data.collaborators.sort(sortingFn) + + /** Controls for story/example */ + const {variant, Controls} = useResponsiveControlsForStory() + + return ( + <> +

Responsive SelectPanel

+ + {Controls} + + + + Assignees + + + + + + {itemsToShow.length === 0 ? ( + + Try a different search term + + ) : ( + + {itemsToShow.map(collaborator => ( + onCollaboratorSelect(collaborator.id)} + selected={selectedAssigneeIds.includes(collaborator.id)} + > + + + + {collaborator.login} + {collaborator.login} + + ))} + + )} + + + + + ) +} + +// pulling this out of story so that the docs look clean +const useResponsiveControlsForStory = () => { + const [variant, setVariant] = React.useState<{regular: 'anchored' | 'modal'; narrow: 'full-screen' | 'bottom-sheet'}>( + {regular: 'anchored', narrow: 'full-screen'}, + ) + + const Controls = ( + + + Regular variant + + setVariant({...variant, regular: 'anchored'})} + > + Anchored + + setVariant({...variant, regular: 'modal'})} + > + Modal + + + + + + Narrow variant + Resize screen to see narrow variant + + + setVariant({...variant, narrow: 'full-screen'})} + > + Full screen + + setVariant({...variant, narrow: 'bottom-sheet'})} + > + Bottom sheet + + + + + ) + + return {variant, Controls} +} From 49eccabbf7e0cdf8b8b06a3a0346e07d93f1226f Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Wed, 14 Feb 2024 17:32:23 +0100 Subject: [PATCH 06/10] add bottom-sheet styles --- .../SelectPanel.features.stories.tsx | 35 +++++++++++++++---- .../src/drafts/SelectPanel2/SelectPanel.tsx | 21 ++++++++--- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/packages/react/src/drafts/SelectPanel2/SelectPanel.features.stories.tsx b/packages/react/src/drafts/SelectPanel2/SelectPanel.features.stories.tsx index 9a5be1afdd0..4e611443e24 100644 --- a/packages/react/src/drafts/SelectPanel2/SelectPanel.features.stories.tsx +++ b/packages/react/src/drafts/SelectPanel2/SelectPanel.features.stories.tsx @@ -1,7 +1,17 @@ import React from 'react' import {SelectPanel} from './SelectPanel' -import {ActionList, Avatar, Box, Button, Link, SegmentedControl, Text, ToggleSwitch} from '../../index' -import {TagIcon, GearIcon} from '@primer/octicons-react' +import { + ActionList, + Avatar, + Box, + Button, + Link, + SegmentedControl, + Text, + ToggleSwitch, + useResponsiveValue, +} from '../../index' +import {TagIcon, GearIcon, ArrowBothIcon} from '@primer/octicons-react' import data from './mock-story-data' export default { @@ -543,10 +553,19 @@ const useResponsiveControlsForStory = () => { {regular: 'anchored', narrow: 'full-screen'}, ) + const isNarrow = useResponsiveValue({narrow: true}, false) + const Controls = ( - - Regular variant + + + Regular variant + {isNarrow ? ( + + Resize screen to see regular variant + + ) : null} + { - + Narrow variant - Resize screen to see narrow variant + {isNarrow ? null : ( + + Resize screen to see narrow variant + + )} = {narrow: 'medium', regular: 'small'} -type ResponsiveVariant = ResponsiveValue<'anchored' | 'modal', 'full-screen' | 'bottom-sheet'> export type SelectPanelProps = { title: string description?: string - variant?: 'anchored' | 'modal' | ResponsiveVariant + variant?: 'anchored' | 'modal' | ResponsiveValue<'anchored' | 'modal', 'full-screen' | 'bottom-sheet'> selectionVariant?: ActionListProps['selectionVariant'] | 'instant' id?: string @@ -100,7 +99,7 @@ const Panel: React.FC = ({ const responsiveVariants = Object.assign( {regular: 'anchored', narrow: 'full-screen'}, // defaults - typeof propsVariant === 'object' ? propsVariant : {regular: propsVariant}, + typeof propsVariant === 'string' ? {regular: propsVariant} : propsVariant, ) const currentVariant = useResponsiveValue(responsiveVariants, 'anchored') @@ -275,13 +274,13 @@ const Panel: React.FC = ({ '100%': {transform: 'scale(1, 1)'}, }, - '&[data-variant=anchored], &[data-variant="full-screen"]': { + '&[data-variant="anchored"], &[data-variant="full-screen"]': { margin: 0, top: position?.top, left: position?.left, '::backdrop': {backgroundColor: 'transparent'}, }, - '&[data-variant=modal]': { + '&[data-variant="modal"]': { '::backdrop': {backgroundColor: 'primer.canvas.backdrop'}, }, '&[data-variant="full-screen"]': { @@ -295,6 +294,18 @@ const Panel: React.FC = ({ '--max-height': '100vh', borderRadius: 'unset', }, + '&[data-variant="bottom-sheet"]': { + margin: 0, + top: 'auto', + bottom: 0, + left: 0, + width: '100%', + maxWidth: '100vw', + maxHeight: 'calc(100vh - 64px)', + '--max-height': 'calc(100vh - 64px)', + borderBottomRightRadius: 0, + borderBottomLeftRadius: 0, + }, }} {...props} onClick={event => { From ef9c8ec787dbf370266612d62e0557a6b776a92f Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Tue, 12 Mar 2024 17:18:43 +0100 Subject: [PATCH 07/10] Create proud-ears-travel.md --- .changeset/proud-ears-travel.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/proud-ears-travel.md diff --git a/.changeset/proud-ears-travel.md b/.changeset/proud-ears-travel.md new file mode 100644 index 00000000000..eb4e1e9d3f7 --- /dev/null +++ b/.changeset/proud-ears-travel.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +experimental/SelectPanel: Add responsive variants From d71e0f65c1e3b6d15c901add7b61de07d4481918 Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Wed, 13 Mar 2024 17:09:54 +0100 Subject: [PATCH 08/10] add matchMedia mock to test-helpers --- .../src/UnderlineNav/UnderlineNav.test.tsx | 16 ---------------- .../react/src/__tests__/ThemeProvider.test.tsx | 16 ---------------- packages/react/src/utils/test-helpers.tsx | 17 +++++++++++++++++ 3 files changed, 17 insertions(+), 32 deletions(-) diff --git a/packages/react/src/UnderlineNav/UnderlineNav.test.tsx b/packages/react/src/UnderlineNav/UnderlineNav.test.tsx index 87d38162ee1..5de3833db3e 100644 --- a/packages/react/src/UnderlineNav/UnderlineNav.test.tsx +++ b/packages/react/src/UnderlineNav/UnderlineNav.test.tsx @@ -15,22 +15,6 @@ import { import {UnderlineNav} from '.' import {checkExports, checkStoriesForAxeViolations} from '../utils/testing' -// window.matchMedia() is not implemented by JSDOM so we have to create a mock: -// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom -Object.defineProperty(window, 'matchMedia', { - writable: true, - value: jest.fn().mockImplementation(query => ({ - matches: false, - media: query, - onchange: null, - addListener: jest.fn(), // deprecated - removeListener: jest.fn(), // deprecated - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - dispatchEvent: jest.fn(), - })), -}) - const ResponsiveUnderlineNav = ({ selectedItemText = 'Code', loadingCounters = false, diff --git a/packages/react/src/__tests__/ThemeProvider.test.tsx b/packages/react/src/__tests__/ThemeProvider.test.tsx index c94e6d3fd72..9cb23e8ee4c 100644 --- a/packages/react/src/__tests__/ThemeProvider.test.tsx +++ b/packages/react/src/__tests__/ThemeProvider.test.tsx @@ -4,22 +4,6 @@ import 'jest-styled-components' import React from 'react' import {Text, ThemeProvider, useColorSchemeVar, useTheme} from '..' -// window.matchMedia() is not implemented by JSDOM so we have to create a mock: -// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom -Object.defineProperty(window, 'matchMedia', { - writable: true, - value: jest.fn().mockImplementation(query => ({ - matches: false, - media: query, - onchange: null, - addListener: jest.fn(), // deprecated - removeListener: jest.fn(), // deprecated - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - dispatchEvent: jest.fn(), - })), -}) - const exampleTheme = { colors: { text: '#f00', diff --git a/packages/react/src/utils/test-helpers.tsx b/packages/react/src/utils/test-helpers.tsx index 056c4c17e76..4b4cc8f868b 100644 --- a/packages/react/src/utils/test-helpers.tsx +++ b/packages/react/src/utils/test-helpers.tsx @@ -44,3 +44,20 @@ if (typeof document !== 'undefined') { if (global.Element.prototype.scrollIntoView === undefined) { global.Element.prototype.scrollIntoView = jest.fn() } + +// window.matchMedia() is not implemented by JSDOM so we have to create a mock: +// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom +// eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation(query => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // deprecated + removeListener: jest.fn(), // deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), +}) From c34700c5adf78b16411a12feaadce4342f3ea3a4 Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Thu, 14 Mar 2024 10:41:02 +0100 Subject: [PATCH 09/10] Revert "add matchMedia mock to test-helpers" This reverts commit d71e0f65c1e3b6d15c901add7b61de07d4481918. --- .../src/UnderlineNav/UnderlineNav.test.tsx | 16 ++++++++++++++++ .../react/src/__tests__/ThemeProvider.test.tsx | 16 ++++++++++++++++ packages/react/src/utils/test-helpers.tsx | 17 ----------------- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/packages/react/src/UnderlineNav/UnderlineNav.test.tsx b/packages/react/src/UnderlineNav/UnderlineNav.test.tsx index 5de3833db3e..87d38162ee1 100644 --- a/packages/react/src/UnderlineNav/UnderlineNav.test.tsx +++ b/packages/react/src/UnderlineNav/UnderlineNav.test.tsx @@ -15,6 +15,22 @@ import { import {UnderlineNav} from '.' import {checkExports, checkStoriesForAxeViolations} from '../utils/testing' +// window.matchMedia() is not implemented by JSDOM so we have to create a mock: +// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation(query => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // deprecated + removeListener: jest.fn(), // deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), +}) + const ResponsiveUnderlineNav = ({ selectedItemText = 'Code', loadingCounters = false, diff --git a/packages/react/src/__tests__/ThemeProvider.test.tsx b/packages/react/src/__tests__/ThemeProvider.test.tsx index 9cb23e8ee4c..c94e6d3fd72 100644 --- a/packages/react/src/__tests__/ThemeProvider.test.tsx +++ b/packages/react/src/__tests__/ThemeProvider.test.tsx @@ -4,6 +4,22 @@ import 'jest-styled-components' import React from 'react' import {Text, ThemeProvider, useColorSchemeVar, useTheme} from '..' +// window.matchMedia() is not implemented by JSDOM so we have to create a mock: +// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation(query => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // deprecated + removeListener: jest.fn(), // deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), +}) + const exampleTheme = { colors: { text: '#f00', diff --git a/packages/react/src/utils/test-helpers.tsx b/packages/react/src/utils/test-helpers.tsx index 4b4cc8f868b..056c4c17e76 100644 --- a/packages/react/src/utils/test-helpers.tsx +++ b/packages/react/src/utils/test-helpers.tsx @@ -44,20 +44,3 @@ if (typeof document !== 'undefined') { if (global.Element.prototype.scrollIntoView === undefined) { global.Element.prototype.scrollIntoView = jest.fn() } - -// window.matchMedia() is not implemented by JSDOM so we have to create a mock: -// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom -// eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope -Object.defineProperty(window, 'matchMedia', { - writable: true, - value: jest.fn().mockImplementation(query => ({ - matches: false, - media: query, - onchange: null, - addListener: jest.fn(), // deprecated - removeListener: jest.fn(), // deprecated - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - dispatchEvent: jest.fn(), - })), -}) From 4fba95ae3b46945aa32cd6284149660925c6ba7b Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Thu, 14 Mar 2024 10:42:04 +0100 Subject: [PATCH 10/10] mock matchMedia for SelectPanel test --- .../src/drafts/SelectPanel2/SelectPanel.test.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/react/src/drafts/SelectPanel2/SelectPanel.test.tsx b/packages/react/src/drafts/SelectPanel2/SelectPanel.test.tsx index f9c920df832..4b6504f2f60 100644 --- a/packages/react/src/drafts/SelectPanel2/SelectPanel.test.tsx +++ b/packages/react/src/drafts/SelectPanel2/SelectPanel.test.tsx @@ -8,6 +8,22 @@ import data from './mock-story-data' import type {SelectPanelProps} from './SelectPanel' import {SelectPanel} from './SelectPanel' +// window.matchMedia() is not implemented by JSDOM so we have to create a mock: +// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation(query => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // deprecated + removeListener: jest.fn(), // deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), +}) + const Fixture = ({onSubmit, onCancel}: Pick) => { const initialSelectedLabels = data.issue.labelIds // mock initial state: has selected labels const [selectedLabelIds, setSelectedLabelIds] = React.useState(initialSelectedLabels)