From 8206fc947b0efdc32917cc17c7289dd348c32974 Mon Sep 17 00:00:00 2001 From: Titani Date: Thu, 8 Sep 2022 22:24:16 -0400 Subject: [PATCH 01/13] feat(Dropdown next): Added the next version of the dropdown component --- .../src/next/components/Dropdown/Dropdown.tsx | 122 ++++++++++++++++++ .../components/Dropdown/DropdownGroup.tsx | 27 ++++ .../next/components/Dropdown/DropdownItem.tsx | 25 ++++ .../next/components/Dropdown/DropdownList.tsx | 21 +++ .../components/Dropdown/examples/Dropdown.md | 31 +++++ .../Dropdown/examples/DropdownBasic.tsx | 78 +++++++++++ .../examples/DropdownWithDescriptions.tsx | 67 ++++++++++ .../Dropdown/examples/DropdownWithGroups.tsx | 70 ++++++++++ .../examples/DropdownWithKebabToggle.tsx | 63 +++++++++ .../src/next/components/Dropdown/index.ts | 4 + .../react-core/src/next/components/index.ts | 1 + 11 files changed, 509 insertions(+) create mode 100644 packages/react-core/src/next/components/Dropdown/Dropdown.tsx create mode 100644 packages/react-core/src/next/components/Dropdown/DropdownGroup.tsx create mode 100644 packages/react-core/src/next/components/Dropdown/DropdownItem.tsx create mode 100644 packages/react-core/src/next/components/Dropdown/DropdownList.tsx create mode 100644 packages/react-core/src/next/components/Dropdown/examples/Dropdown.md create mode 100644 packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx create mode 100644 packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx create mode 100644 packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx create mode 100644 packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx create mode 100644 packages/react-core/src/next/components/Dropdown/index.ts diff --git a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx new file mode 100644 index 00000000000..7da917633cc --- /dev/null +++ b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx @@ -0,0 +1,122 @@ +import React from 'react'; +import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; +import { css } from '@patternfly/react-styles'; +import { Menu, MenuContent, MenuProps } from '../../../components/Menu'; +import { MenuToggleProps } from '../../../components/MenuToggle'; +import { Popper } from '../../../helpers/Popper/Popper'; + +export interface DropdownToggleProps extends MenuToggleProps { + /** Toggle text */ + toggleText: React.ReactNode; + /** toggle variant*/ + variant?: 'default' | 'plain' | 'primary' | 'plainText' | 'secondary' | 'typeahead'; + /** Additional toggle props */ + toggleProps?: any; +} + +export interface DropdownProps extends MenuProps { + /** Anything which can be rendered in a dropdown */ + children?: React.ReactNode; + /** Classes applied to root element of dropdown */ + className?: string; + /** The default toggle options */ + // toggleProps?: DropdownToggleProps; + /** Renderer for a custom dropdown toggle. Forwards a ref to the toggle. */ + toggleRender?: (toggleRef: React.RefObject) => React.ReactNode; + /** Flag to indicate if menu is opened. If is open */ + isOpen?: boolean; + /** Function callback called when user selects item */ + onSelect?: (event?: React.MouseEvent, itemId?: string | number) => void; + /* Callback to be called when the component changes the open state of the Component. + * E.g. The component closes the menu when there is a click outside of the menu. */ + onIsOpenChange?: (isOpen: boolean) => void; + /** Indicates if the menu should be without the outer box-shadow */ + isPlain?: boolean; + /** Indicates if the menu should be srollable */ + isScrollable?: boolean; + /* min width of the menu */ + minWidth?: string; +} + +export const Dropdown: React.FunctionComponent = ({ + children, + className, + onSelect, + isOpen, + toggleRender, + onIsOpenChange, + isPlain, + isScrollable, + minWidth, + // ouiaId, + // ouiaSafe, + // alignments, + ...props +}: DropdownProps) => { + const localMenuRef = React.useRef(); + const toggleRef = React.useRef(); + const containerRef = React.useRef(); + + const menuRef = (props.innerRef as React.RefObject) || localMenuRef; + React.useEffect(() => { + const handleMenuKeys = (event: KeyboardEvent) => { + // console.log('dropdown', toggleRef?.current?.contains(event.target as Node)); + if (isOpen && menuRef?.current && toggleRef?.current?.contains(event.target as Node)) { + // toggle was clicked open, focus on first menu item + if (document.activeElement !== toggleRef.current) { + setTimeout(() => { + const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); + firstElement && (firstElement as HTMLElement).focus(); + }, 0); + } + } + }; + + const handleClickOutside = (event: MouseEvent) => { + // If the event is not on the toggle, close the menu + if (isOpen && onIsOpenChange && !toggleRef?.current?.contains(event.target as Node)) { + if (isOpen && !menuRef.current?.contains(event.target as Node)) { + onIsOpenChange(false); + } + } + }; + + window.addEventListener('keydown', handleMenuKeys); + window.addEventListener('click', handleClickOutside); + + return () => { + window.removeEventListener('keydown', handleMenuKeys); + window.removeEventListener('click', handleClickOutside); + }; + }, [isOpen, menuRef, onIsOpenChange]); + + const menu = ( + // eslint-disable-next-line no-console + onSelect(event, itemId)} + isPlain={isPlain} + isScrollable={isScrollable} + {...(minWidth && { + style: { + '--pf-c-menu--MinWidth': minWidth + } as React.CSSProperties + })} + {...props} + > + {children} + + ); + return ( +
+ +
+ ); +}; +Dropdown.displayName = 'Dropdown'; diff --git a/packages/react-core/src/next/components/Dropdown/DropdownGroup.tsx b/packages/react-core/src/next/components/Dropdown/DropdownGroup.tsx new file mode 100644 index 00000000000..46a7040ee68 --- /dev/null +++ b/packages/react-core/src/next/components/Dropdown/DropdownGroup.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { css } from '@patternfly/react-styles'; +import { MenuGroupProps, MenuGroup } from '../../../components/Menu'; + +export interface DropdownGroupProps extends Omit { + /** Anything which can be rendered in a dropdown group. */ + children: React.ReactNode; + /** Classes applied to root element of dropdown list */ + className?: string; + /** Label of the dropdown group */ + label?: string; + /** Group label heading level.*/ + labelHeadingLevel?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; +} + +export const DropdownGroup: React.FunctionComponent = ({ + children, + className, + label, + labelHeadingLevel = 'h1', + ...props +}: DropdownGroupProps) => ( + + {children} + +); +DropdownGroup.displayName = 'DropdownGroup'; diff --git a/packages/react-core/src/next/components/Dropdown/DropdownItem.tsx b/packages/react-core/src/next/components/Dropdown/DropdownItem.tsx new file mode 100644 index 00000000000..24b7b14a393 --- /dev/null +++ b/packages/react-core/src/next/components/Dropdown/DropdownItem.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; +import { css } from '@patternfly/react-styles'; +import { MenuItemProps, MenuItem } from '../../../components/Menu'; + +export interface DropdownItemProps extends Omit { + /** Anything which can be rendered in a dropdown item */ + children?: React.ReactNode; + /** Classes applied to root element of dropdown */ + className?: string; + /** Description of the dropdown item */ + description?: React.ReactNode; +} + +export const DropdownItem: React.FunctionComponent = ({ + children, + className, + description, + ...props +}: DropdownItemProps) => ( + + {children} + +); +DropdownItem.displayName = 'DropdownItem'; diff --git a/packages/react-core/src/next/components/Dropdown/DropdownList.tsx b/packages/react-core/src/next/components/Dropdown/DropdownList.tsx new file mode 100644 index 00000000000..d4e46338346 --- /dev/null +++ b/packages/react-core/src/next/components/Dropdown/DropdownList.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { css } from '@patternfly/react-styles'; +import { MenuListProps, MenuList } from '../../../components/Menu'; + +export interface DropdownListProps extends MenuListProps { + /** Anything which can be rendered in a dropdown list */ + children: React.ReactNode; + /** Classes applied to root element of dropdown list */ + className?: string; +} + +export const DropdownList: React.FunctionComponent = ({ + children, + className, + ...props +}: DropdownListProps) => ( + + {children} + +); +DropdownList.displayName = 'DropdownList'; diff --git a/packages/react-core/src/next/components/Dropdown/examples/Dropdown.md b/packages/react-core/src/next/components/Dropdown/examples/Dropdown.md new file mode 100644 index 00000000000..08b06814ffc --- /dev/null +++ b/packages/react-core/src/next/components/Dropdown/examples/Dropdown.md @@ -0,0 +1,31 @@ +--- +id: Dropdown +section: components +cssPrefix: pf-c-dropdown +propComponents: ['Dropdown', DropdownGroup, 'DropdownItem', 'DropdownList'] +beta: true +--- + +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; + +## Examples + +### Basic + +```ts file="./DropdownBasic.tsx" +``` + +### With kebab toggle + +```ts file="./DropdownWithKebabToggle.tsx" +``` + +### With groups + +```ts file="./DropdownWithGroups.tsx" +``` + +### With descriptions + +```ts file="./DropdownWithDescriptions.tsx" +``` diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx new file mode 100644 index 00000000000..0d59abb0214 --- /dev/null +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx @@ -0,0 +1,78 @@ +import React from 'react'; +import { Dropdown, DropdownItem, DropdownList } from '@patternfly/react-core/next'; +import { Checkbox, Divider, MenuToggle } from '@patternfly/react-core'; + +export const DropdownBasic: React.FunctionComponent = () => { + const [isOpen, setIsOpen] = React.useState(false); + const [isPlain, setIsPlain] = React.useState(false); + const menuRef = React.useRef(null); + + const onToggleClick = () => { + // setTimeout(() => { + // if (menuRef.current) { + // debugger; + // const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); + // firstElement && (firstElement as HTMLElement).focus(); + // } + // }, 0); + setIsOpen(!isOpen); + }; + + const onSelect = (_event: React.MouseEvent | undefined, itemId: string | number | undefined) => { + // eslint-disable-next-line no-console + console.log('selected', itemId); + setIsOpen(false); + }; + + const toggleIsPlain = () => { + setIsPlain(!isPlain); + }; + + return ( + <> +
+ +
+ setIsOpen(isOpen)} + toggleRender={toggleRef => ( + + Dropdown + + )} + > + + + Link + + ev.preventDefault()}> + Action + + + Disabled link + + + Disabled action + + , + + Separated link + + + Separated action + + + + + ); +}; diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx new file mode 100644 index 00000000000..af1035c9ef1 --- /dev/null +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx @@ -0,0 +1,67 @@ +import React from 'react'; +import { Dropdown, DropdownItem, DropdownList } from '@patternfly/react-core/next'; +import { MenuToggle } from '@patternfly/react-core'; + +export const DropdownWithDescriptions: React.FunctionComponent = () => { + const [isOpen, setIsOpen] = React.useState(false); + const menuRef = React.useRef(null); + + const onToggleClick = () => { + // setTimeout(() => { + // if (menuRef.current) { + // debugger; + // const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); + // firstElement && (firstElement as HTMLElement).focus(); + // } + // }, 0); + setIsOpen(!isOpen); + }; + + const onSelect = (_event: React.MouseEvent | undefined, itemId: string | number | undefined) => { + // eslint-disable-next-line no-console + console.log('selected', itemId); + setIsOpen(false); + }; + + return ( + setIsOpen(isOpen)} + toggleRender={toggleRef => ( + + Dropdown + + )} + > + + + Link + + ev.preventDefault()} + > + Action + + + Disabled link + + + Disabled action + + + + ); +}; diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx new file mode 100644 index 00000000000..d177871e905 --- /dev/null +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx @@ -0,0 +1,70 @@ +import React from 'react'; +import { Dropdown, DropdownGroup, DropdownItem, DropdownList } from '@patternfly/react-core/next'; +import { MenuToggle } from '@patternfly/react-core'; + +export const DropdownWithGroups: React.FunctionComponent = () => { + const [isOpen, setIsOpen] = React.useState(false); + const menuRef = React.useRef(null); + + const onToggleClick = () => { + // setTimeout(() => { + // if (menuRef.current) { + // debugger; + // const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); + // firstElement && (firstElement as HTMLElement).focus(); + // } + // }, 0); + setIsOpen(!isOpen); + }; + + const onSelect = (_event: React.MouseEvent | undefined, itemId: string | number | undefined) => { + // eslint-disable-next-line no-console + console.log('selected', itemId); + setIsOpen(false); + }; + + return ( + setIsOpen(isOpen)} + toggleRender={toggleRef => ( + + Dropdown + + )} + > + + + + Link + + ev.preventDefault()}> + Action + + + + + + + Group 2 link + + + group 2 action + + + + + + + Group 3 link + + + Group 3 action + + + + + ); +}; diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx new file mode 100644 index 00000000000..5836bcc1930 --- /dev/null +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx @@ -0,0 +1,63 @@ +import React from 'react'; +import { Dropdown, DropdownItem, DropdownList } from '@patternfly/react-core/next'; +import { Divider, MenuToggle } from '@patternfly/react-core'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; + +export const DropdownWithKebab: React.FunctionComponent = () => { + const [isOpen, setIsOpen] = React.useState(false); + const menuRef = React.useRef(null); + + const onToggleClick = () => { + // setTimeout(() => { + // if (menuRef.current) { + // debugger; + // const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); + // firstElement && (firstElement as HTMLElement).focus(); + // } + // }, 0); + setIsOpen(!isOpen); + }; + + const onSelect = (_event: React.MouseEvent | undefined, itemId: string | number | undefined) => { + // eslint-disable-next-line no-console + console.log('selected', itemId); + setIsOpen(false); + }; + + return ( + setIsOpen(isOpen)} + toggleRender={toggleRef => ( + + + + )} + > + + + Link + + ev.preventDefault()}> + Action + + + Disabled link + + + Disabled action + + , + + Separated link + + + Separated action + + + + ); +}; diff --git a/packages/react-core/src/next/components/Dropdown/index.ts b/packages/react-core/src/next/components/Dropdown/index.ts new file mode 100644 index 00000000000..0edc20d91ad --- /dev/null +++ b/packages/react-core/src/next/components/Dropdown/index.ts @@ -0,0 +1,4 @@ +export * from './Dropdown'; +export * from './DropdownGroup'; +export * from './DropdownItem'; +export * from './DropdownList'; diff --git a/packages/react-core/src/next/components/index.ts b/packages/react-core/src/next/components/index.ts index 4ad68566220..802328b87c6 100644 --- a/packages/react-core/src/next/components/index.ts +++ b/packages/react-core/src/next/components/index.ts @@ -1 +1,2 @@ export * from './Wizard'; +export * from './Dropdown'; From c198fd80d5e2a7e7b5098f90a90c797b76b8c8bb Mon Sep 17 00:00:00 2001 From: Titani Date: Fri, 9 Sep 2022 08:00:55 -0400 Subject: [PATCH 02/13] add aria label to kebab toggle --- .../Dropdown/examples/DropdownWithKebabToggle.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx index 5836bcc1930..1ae5607d3a0 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx @@ -32,7 +32,13 @@ export const DropdownWithKebab: React.FunctionComponent = () => { minWidth="150px" onIsOpenChange={isOpen => setIsOpen(isOpen)} toggleRender={toggleRef => ( - + )} From 872ebbc13550a329606dd2019383d72e4962e3d9 Mon Sep 17 00:00:00 2001 From: Titani Date: Fri, 9 Sep 2022 08:14:25 -0400 Subject: [PATCH 03/13] clean up commented code --- .../src/next/components/Dropdown/Dropdown.tsx | 13 ------------- .../components/Dropdown/examples/DropdownBasic.tsx | 14 +++++++------- .../Dropdown/examples/DropdownWithDescriptions.tsx | 14 +++++++------- .../Dropdown/examples/DropdownWithGroups.tsx | 14 +++++++------- .../Dropdown/examples/DropdownWithKebabToggle.tsx | 14 +++++++------- 5 files changed, 28 insertions(+), 41 deletions(-) diff --git a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx index 7da917633cc..bde2cb484b4 100644 --- a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx @@ -2,18 +2,8 @@ import React from 'react'; import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; import { css } from '@patternfly/react-styles'; import { Menu, MenuContent, MenuProps } from '../../../components/Menu'; -import { MenuToggleProps } from '../../../components/MenuToggle'; import { Popper } from '../../../helpers/Popper/Popper'; -export interface DropdownToggleProps extends MenuToggleProps { - /** Toggle text */ - toggleText: React.ReactNode; - /** toggle variant*/ - variant?: 'default' | 'plain' | 'primary' | 'plainText' | 'secondary' | 'typeahead'; - /** Additional toggle props */ - toggleProps?: any; -} - export interface DropdownProps extends MenuProps { /** Anything which can be rendered in a dropdown */ children?: React.ReactNode; @@ -48,9 +38,6 @@ export const Dropdown: React.FunctionComponent = ({ isPlain, isScrollable, minWidth, - // ouiaId, - // ouiaSafe, - // alignments, ...props }: DropdownProps) => { const localMenuRef = React.useRef(); diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx index 0d59abb0214..1fbd52877a4 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx @@ -8,13 +8,13 @@ export const DropdownBasic: React.FunctionComponent = () => { const menuRef = React.useRef(null); const onToggleClick = () => { - // setTimeout(() => { - // if (menuRef.current) { - // debugger; - // const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); - // firstElement && (firstElement as HTMLElement).focus(); - // } - // }, 0); + // TODO: move the logic for focus into the component + setTimeout(() => { + if (menuRef.current) { + const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); + firstElement && (firstElement as HTMLElement).focus(); + } + }, 0); setIsOpen(!isOpen); }; diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx index af1035c9ef1..97db7d90ff2 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx @@ -7,13 +7,13 @@ export const DropdownWithDescriptions: React.FunctionComponent = () => { const menuRef = React.useRef(null); const onToggleClick = () => { - // setTimeout(() => { - // if (menuRef.current) { - // debugger; - // const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); - // firstElement && (firstElement as HTMLElement).focus(); - // } - // }, 0); + // TODO: move the logic for focus into the component + setTimeout(() => { + if (menuRef.current) { + const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); + firstElement && (firstElement as HTMLElement).focus(); + } + }, 0); setIsOpen(!isOpen); }; diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx index d177871e905..e7ced74ff11 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx @@ -7,13 +7,13 @@ export const DropdownWithGroups: React.FunctionComponent = () => { const menuRef = React.useRef(null); const onToggleClick = () => { - // setTimeout(() => { - // if (menuRef.current) { - // debugger; - // const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); - // firstElement && (firstElement as HTMLElement).focus(); - // } - // }, 0); + // TODO: move the logic for focus into the component + setTimeout(() => { + if (menuRef.current) { + const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); + firstElement && (firstElement as HTMLElement).focus(); + } + }, 0); setIsOpen(!isOpen); }; diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx index 1ae5607d3a0..1c88d0f4bce 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx @@ -8,13 +8,13 @@ export const DropdownWithKebab: React.FunctionComponent = () => { const menuRef = React.useRef(null); const onToggleClick = () => { - // setTimeout(() => { - // if (menuRef.current) { - // debugger; - // const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); - // firstElement && (firstElement as HTMLElement).focus(); - // } - // }, 0); + // TODO: move the logic for focus into the component + setTimeout(() => { + if (menuRef.current) { + const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); + firstElement && (firstElement as HTMLElement).focus(); + } + }, 0); setIsOpen(!isOpen); }; From 354bcee8803a64a0bcfc20ec692df05b9160ee85 Mon Sep 17 00:00:00 2001 From: Titani Date: Fri, 9 Sep 2022 09:30:00 -0400 Subject: [PATCH 04/13] Fixed keyboard interactions --- .../src/next/components/Dropdown/Dropdown.tsx | 27 ++++++++++++------- .../Dropdown/examples/DropdownBasic.tsx | 8 +----- .../examples/DropdownWithDescriptions.tsx | 7 ----- .../Dropdown/examples/DropdownWithGroups.tsx | 7 ----- .../examples/DropdownWithKebabToggle.tsx | 7 ----- 5 files changed, 18 insertions(+), 38 deletions(-) diff --git a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx index bde2cb484b4..fdd93afd262 100644 --- a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx @@ -9,22 +9,20 @@ export interface DropdownProps extends MenuProps { children?: React.ReactNode; /** Classes applied to root element of dropdown */ className?: string; - /** The default toggle options */ - // toggleProps?: DropdownToggleProps; /** Renderer for a custom dropdown toggle. Forwards a ref to the toggle. */ toggleRender?: (toggleRef: React.RefObject) => React.ReactNode; /** Flag to indicate if menu is opened. If is open */ isOpen?: boolean; /** Function callback called when user selects item */ onSelect?: (event?: React.MouseEvent, itemId?: string | number) => void; - /* Callback to be called when the component changes the open state of the Component. - * E.g. The component closes the menu when there is a click outside of the menu. */ + /** Callback to for when the component needs to change the open state of the menu. + * If this is not provided the component will not close the menu when tab or escape are clicked. */ onIsOpenChange?: (isOpen: boolean) => void; /** Indicates if the menu should be without the outer box-shadow */ isPlain?: boolean; - /** Indicates if the menu should be srollable */ + /** Indicates if the menu should be scrollable */ isScrollable?: boolean; - /* min width of the menu */ + /** Min width of the menu */ minWidth?: string; } @@ -47,20 +45,29 @@ export const Dropdown: React.FunctionComponent = ({ const menuRef = (props.innerRef as React.RefObject) || localMenuRef; React.useEffect(() => { const handleMenuKeys = (event: KeyboardEvent) => { - // console.log('dropdown', toggleRef?.current?.contains(event.target as Node)); - if (isOpen && menuRef?.current && toggleRef?.current?.contains(event.target as Node)) { + if (!isOpen && toggleRef.current?.contains(event.target as Node)) { // toggle was clicked open, focus on first menu item - if (document.activeElement !== toggleRef.current) { + if (event.key === 'Enter') { setTimeout(() => { const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); firstElement && (firstElement as HTMLElement).focus(); }, 0); } } + // Close the menu on tab or escape if onIsOpenChange is provided + if ( + (isOpen && onIsOpenChange && menuRef.current?.contains(event.target as Node)) || + toggleRef.current?.contains(event.target as Node) + ) { + if (event.key === 'Escape' || event.key === 'Tab') { + onIsOpenChange(!isOpen); + toggleRef.current?.focus(); + } + } }; const handleClickOutside = (event: MouseEvent) => { - // If the event is not on the toggle, close the menu + // If the event is not on the toggle and onIsOpenChange callback is provided, close the menu if (isOpen && onIsOpenChange && !toggleRef?.current?.contains(event.target as Node)) { if (isOpen && !menuRef.current?.contains(event.target as Node)) { onIsOpenChange(false); diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx index 1fbd52877a4..7844a3e130c 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx @@ -8,13 +8,6 @@ export const DropdownBasic: React.FunctionComponent = () => { const menuRef = React.useRef(null); const onToggleClick = () => { - // TODO: move the logic for focus into the component - setTimeout(() => { - if (menuRef.current) { - const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); - firstElement && (firstElement as HTMLElement).focus(); - } - }, 0); setIsOpen(!isOpen); }; @@ -44,6 +37,7 @@ export const DropdownBasic: React.FunctionComponent = () => { innerRef={menuRef} isOpen={isOpen} onSelect={onSelect} + isPlain={isPlain} onIsOpenChange={isOpen => setIsOpen(isOpen)} toggleRender={toggleRef => ( diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx index 97db7d90ff2..0af5fc2a4df 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx @@ -7,13 +7,6 @@ export const DropdownWithDescriptions: React.FunctionComponent = () => { const menuRef = React.useRef(null); const onToggleClick = () => { - // TODO: move the logic for focus into the component - setTimeout(() => { - if (menuRef.current) { - const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); - firstElement && (firstElement as HTMLElement).focus(); - } - }, 0); setIsOpen(!isOpen); }; diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx index e7ced74ff11..a10293568d8 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx @@ -7,13 +7,6 @@ export const DropdownWithGroups: React.FunctionComponent = () => { const menuRef = React.useRef(null); const onToggleClick = () => { - // TODO: move the logic for focus into the component - setTimeout(() => { - if (menuRef.current) { - const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); - firstElement && (firstElement as HTMLElement).focus(); - } - }, 0); setIsOpen(!isOpen); }; diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx index 1c88d0f4bce..d31967e0b89 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx @@ -8,13 +8,6 @@ export const DropdownWithKebab: React.FunctionComponent = () => { const menuRef = React.useRef(null); const onToggleClick = () => { - // TODO: move the logic for focus into the component - setTimeout(() => { - if (menuRef.current) { - const firstElement = menuRef.current.querySelector('li > button:not(:disabled)'); - firstElement && (firstElement as HTMLElement).focus(); - } - }, 0); setIsOpen(!isOpen); }; From bcf37feea0a8ca71d40cfe23576aac2aa3fa96b2 Mon Sep 17 00:00:00 2001 From: Titani Date: Fri, 9 Sep 2022 13:39:32 -0400 Subject: [PATCH 05/13] some review updates --- .../src/next/components/Dropdown/Dropdown.tsx | 22 +++++++++---------- .../Dropdown/examples/DropdownBasic.tsx | 2 +- .../examples/DropdownWithDescriptions.tsx | 2 +- .../Dropdown/examples/DropdownWithGroups.tsx | 2 +- .../examples/DropdownWithKebabToggle.tsx | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx index fdd93afd262..a737cbc4278 100644 --- a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx @@ -5,24 +5,24 @@ import { Menu, MenuContent, MenuProps } from '../../../components/Menu'; import { Popper } from '../../../helpers/Popper/Popper'; export interface DropdownProps extends MenuProps { - /** Anything which can be rendered in a dropdown */ + /** Anything which can be rendered in a dropdown. */ children?: React.ReactNode; - /** Classes applied to root element of dropdown */ + /** Classes applied to root element of dropdown. */ className?: string; /** Renderer for a custom dropdown toggle. Forwards a ref to the toggle. */ - toggleRender?: (toggleRef: React.RefObject) => React.ReactNode; - /** Flag to indicate if menu is opened. If is open */ + toggle?: (toggleRef: React.RefObject) => React.ReactNode; + /** Flag to indicate if menu is opened.*/ isOpen?: boolean; - /** Function callback called when user selects item */ + /** Function callback called when user selects item. */ onSelect?: (event?: React.MouseEvent, itemId?: string | number) => void; - /** Callback to for when the component needs to change the open state of the menu. + /** Callback for when the component needs to change the open state of the menu. * If this is not provided the component will not close the menu when tab or escape are clicked. */ onIsOpenChange?: (isOpen: boolean) => void; - /** Indicates if the menu should be without the outer box-shadow */ + /** Indicates if the menu should be without the outer box-shadow. */ isPlain?: boolean; - /** Indicates if the menu should be scrollable */ + /** Indicates if the menu should be scrollable. */ isScrollable?: boolean; - /** Min width of the menu */ + /** Min width of the menu. */ minWidth?: string; } @@ -31,7 +31,7 @@ export const Dropdown: React.FunctionComponent = ({ className, onSelect, isOpen, - toggleRender, + toggle, onIsOpenChange, isPlain, isScrollable, @@ -105,7 +105,7 @@ export const Dropdown: React.FunctionComponent = ({ return (
{ onSelect={onSelect} isPlain={isPlain} onIsOpenChange={isOpen => setIsOpen(isOpen)} - toggleRender={toggleRef => ( + toggle={toggleRef => ( Dropdown diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx index 0af5fc2a4df..456aed3e811 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx @@ -23,7 +23,7 @@ export const DropdownWithDescriptions: React.FunctionComponent = () => { onSelect={onSelect} minWidth="150px" onIsOpenChange={isOpen => setIsOpen(isOpen)} - toggleRender={toggleRef => ( + toggle={toggleRef => ( Dropdown diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx index a10293568d8..73baf493214 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx @@ -22,7 +22,7 @@ export const DropdownWithGroups: React.FunctionComponent = () => { isOpen={isOpen} onSelect={onSelect} onIsOpenChange={isOpen => setIsOpen(isOpen)} - toggleRender={toggleRef => ( + toggle={toggleRef => ( Dropdown diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx index d31967e0b89..76e883c412e 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx @@ -24,7 +24,7 @@ export const DropdownWithKebab: React.FunctionComponent = () => { onSelect={onSelect} minWidth="150px" onIsOpenChange={isOpen => setIsOpen(isOpen)} - toggleRender={toggleRef => ( + toggle={toggleRef => ( Date: Fri, 9 Sep 2022 14:02:45 -0400 Subject: [PATCH 06/13] updates from comments --- packages/react-core/src/next/components/Dropdown/Dropdown.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx index a737cbc4278..395f348aaa8 100644 --- a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx @@ -15,7 +15,7 @@ export interface DropdownProps extends MenuProps { isOpen?: boolean; /** Function callback called when user selects item. */ onSelect?: (event?: React.MouseEvent, itemId?: string | number) => void; - /** Callback for when the component needs to change the open state of the menu. + /** Callback to allow the dropdown component change the open state of the menu that is set with the isOpen prop . * If this is not provided the component will not close the menu when tab or escape are clicked. */ onIsOpenChange?: (isOpen: boolean) => void; /** Indicates if the menu should be without the outer box-shadow. */ @@ -106,6 +106,7 @@ export const Dropdown: React.FunctionComponent = ({
Date: Fri, 9 Sep 2022 14:06:23 -0400 Subject: [PATCH 07/13] fixed comment --- packages/react-core/src/next/components/Dropdown/Dropdown.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx index 395f348aaa8..a935429814b 100644 --- a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx @@ -15,7 +15,7 @@ export interface DropdownProps extends MenuProps { isOpen?: boolean; /** Function callback called when user selects item. */ onSelect?: (event?: React.MouseEvent, itemId?: string | number) => void; - /** Callback to allow the dropdown component change the open state of the menu that is set with the isOpen prop . + /** Callback to allow the dropdown component to change the open state of the menu that is set with the isOpen prop . * If this is not provided the component will not close the menu when tab or escape are clicked. */ onIsOpenChange?: (isOpen: boolean) => void; /** Indicates if the menu should be without the outer box-shadow. */ From e10f7008c6e7bf8a56d52659a964a7118aacb3b1 Mon Sep 17 00:00:00 2001 From: Titani Date: Fri, 9 Sep 2022 14:16:29 -0400 Subject: [PATCH 08/13] add dropdown group styling --- .../src/next/components/Dropdown/DropdownGroup.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/react-core/src/next/components/Dropdown/DropdownGroup.tsx b/packages/react-core/src/next/components/Dropdown/DropdownGroup.tsx index 46a7040ee68..8f4717daa80 100644 --- a/packages/react-core/src/next/components/Dropdown/DropdownGroup.tsx +++ b/packages/react-core/src/next/components/Dropdown/DropdownGroup.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; import { css } from '@patternfly/react-styles'; import { MenuGroupProps, MenuGroup } from '../../../components/Menu'; @@ -20,7 +21,12 @@ export const DropdownGroup: React.FunctionComponent = ({ labelHeadingLevel = 'h1', ...props }: DropdownGroupProps) => ( - + {children} ); From 798d7151305c6fa452f95ccd0c2648f0c4391288 Mon Sep 17 00:00:00 2001 From: Titani Date: Fri, 9 Sep 2022 15:26:03 -0400 Subject: [PATCH 09/13] Add dividers to demo and remove plain menu checkbox --- .../Dropdown/examples/DropdownBasic.tsx | 86 ++++++++----------- .../Dropdown/examples/DropdownWithGroups.tsx | 4 +- 2 files changed, 37 insertions(+), 53 deletions(-) diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx index 31797fd89ef..37e9ce65537 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx @@ -1,10 +1,9 @@ import React from 'react'; import { Dropdown, DropdownItem, DropdownList } from '@patternfly/react-core/next'; -import { Checkbox, Divider, MenuToggle } from '@patternfly/react-core'; +import { Divider, MenuToggle } from '@patternfly/react-core'; export const DropdownBasic: React.FunctionComponent = () => { const [isOpen, setIsOpen] = React.useState(false); - const [isPlain, setIsPlain] = React.useState(false); const menuRef = React.useRef(null); const onToggleClick = () => { @@ -17,56 +16,39 @@ export const DropdownBasic: React.FunctionComponent = () => { setIsOpen(false); }; - const toggleIsPlain = () => { - setIsPlain(!isPlain); - }; - return ( - <> -
- -
- setIsOpen(isOpen)} - toggle={toggleRef => ( - - Dropdown - - )} - > - - - Link - - ev.preventDefault()}> - Action - - - Disabled link - - - Disabled action - - , - - Separated link - - - Separated action - - - - + setIsOpen(isOpen)} + toggle={toggleRef => ( + + Dropdown + + )} + > + + + Link + + ev.preventDefault()}> + Action + + + Disabled link + + + Disabled action + + , + + Separated link + + + Separated action + + + ); }; diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx index 73baf493214..c1f7de68a86 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Dropdown, DropdownGroup, DropdownItem, DropdownList } from '@patternfly/react-core/next'; +import { Dropdown, DropdownGroup, DropdownItem, DropdownList, Divider } from '@patternfly/react-core/next'; import { MenuToggle } from '@patternfly/react-core'; export const DropdownWithGroups: React.FunctionComponent = () => { @@ -38,6 +38,7 @@ export const DropdownWithGroups: React.FunctionComponent = () => { + @@ -48,6 +49,7 @@ export const DropdownWithGroups: React.FunctionComponent = () => { + From 6d56661330fcee4071ef139743124191110d1504 Mon Sep 17 00:00:00 2001 From: Titani Date: Fri, 9 Sep 2022 15:39:15 -0400 Subject: [PATCH 10/13] update imports, remove comma from list --- .../src/next/components/Dropdown/examples/DropdownBasic.tsx | 2 +- .../next/components/Dropdown/examples/DropdownWithGroups.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx index 37e9ce65537..853e6d6e044 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownBasic.tsx @@ -41,7 +41,7 @@ export const DropdownBasic: React.FunctionComponent = () => { Disabled action - , + Separated link diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx index c1f7de68a86..df1ed670552 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { Dropdown, DropdownGroup, DropdownItem, DropdownList, Divider } from '@patternfly/react-core/next'; -import { MenuToggle } from '@patternfly/react-core'; +import { Dropdown, DropdownGroup, DropdownItem, DropdownList } from '@patternfly/react-core/next'; +import { MenuToggle, Divider } from '@patternfly/react-core'; export const DropdownWithGroups: React.FunctionComponent = () => { const [isOpen, setIsOpen] = React.useState(false); From 8b27dd787d370948de0050d763bd9eb691bd4c9d Mon Sep 17 00:00:00 2001 From: Titani Date: Fri, 9 Sep 2022 16:44:58 -0400 Subject: [PATCH 11/13] fix descriptions and mark toggle required --- .../react-core/src/next/components/Dropdown/Dropdown.tsx | 5 ++--- .../src/next/components/Dropdown/DropdownGroup.tsx | 4 +--- .../react-core/src/next/components/Dropdown/DropdownItem.tsx | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx index a935429814b..ddb42558041 100644 --- a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx @@ -10,13 +10,13 @@ export interface DropdownProps extends MenuProps { /** Classes applied to root element of dropdown. */ className?: string; /** Renderer for a custom dropdown toggle. Forwards a ref to the toggle. */ - toggle?: (toggleRef: React.RefObject) => React.ReactNode; + toggle: (toggleRef: React.RefObject) => React.ReactNode; /** Flag to indicate if menu is opened.*/ isOpen?: boolean; /** Function callback called when user selects item. */ onSelect?: (event?: React.MouseEvent, itemId?: string | number) => void; /** Callback to allow the dropdown component to change the open state of the menu that is set with the isOpen prop . - * If this is not provided the component will not close the menu when tab or escape are clicked. */ + * If this is not provided the component will not close the menu when tab or escape are pressed. */ onIsOpenChange?: (isOpen: boolean) => void; /** Indicates if the menu should be without the outer box-shadow. */ isPlain?: boolean; @@ -85,7 +85,6 @@ export const Dropdown: React.FunctionComponent = ({ }, [isOpen, menuRef, onIsOpenChange]); const menu = ( - // eslint-disable-next-line no-console { /** Anything which can be rendered in a dropdown group. */ children: React.ReactNode; - /** Classes applied to root element of dropdown list */ + /** Classes applied to root element of dropdown group */ className?: string; /** Label of the dropdown group */ label?: string; - /** Group label heading level.*/ - labelHeadingLevel?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; } export const DropdownGroup: React.FunctionComponent = ({ diff --git a/packages/react-core/src/next/components/Dropdown/DropdownItem.tsx b/packages/react-core/src/next/components/Dropdown/DropdownItem.tsx index 24b7b14a393..82066d0b23c 100644 --- a/packages/react-core/src/next/components/Dropdown/DropdownItem.tsx +++ b/packages/react-core/src/next/components/Dropdown/DropdownItem.tsx @@ -6,7 +6,7 @@ import { MenuItemProps, MenuItem } from '../../../components/Menu'; export interface DropdownItemProps extends Omit { /** Anything which can be rendered in a dropdown item */ children?: React.ReactNode; - /** Classes applied to root element of dropdown */ + /** Classes applied to root element of dropdown item */ className?: string; /** Description of the dropdown item */ description?: React.ReactNode; From ee1023cff0281b9990e2f323823b518542a0e92e Mon Sep 17 00:00:00 2001 From: Titani Date: Mon, 12 Sep 2022 11:31:03 -0400 Subject: [PATCH 12/13] change prop name --- .../src/next/components/Dropdown/Dropdown.tsx | 22 +++++++++---------- .../Dropdown/examples/DropdownBasic.tsx | 2 +- .../examples/DropdownWithDescriptions.tsx | 2 +- .../Dropdown/examples/DropdownWithGroups.tsx | 2 +- .../examples/DropdownWithKebabToggle.tsx | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx index ddb42558041..2b79df3dfd9 100644 --- a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx @@ -15,9 +15,9 @@ export interface DropdownProps extends MenuProps { isOpen?: boolean; /** Function callback called when user selects item. */ onSelect?: (event?: React.MouseEvent, itemId?: string | number) => void; - /** Callback to allow the dropdown component to change the open state of the menu that is set with the isOpen prop . - * If this is not provided the component will not close the menu when tab or escape are pressed. */ - onIsOpenChange?: (isOpen: boolean) => void; + /** Callback to allow the dropdown component to change the open state of the menu. + * Triggered by clicking outside of the menu, or by pressing either tab or escape. */ + onOpenChange?: (isOpen: boolean) => void; /** Indicates if the menu should be without the outer box-shadow. */ isPlain?: boolean; /** Indicates if the menu should be scrollable. */ @@ -32,7 +32,7 @@ export const Dropdown: React.FunctionComponent = ({ onSelect, isOpen, toggle, - onIsOpenChange, + onOpenChange, isPlain, isScrollable, minWidth, @@ -54,23 +54,23 @@ export const Dropdown: React.FunctionComponent = ({ }, 0); } } - // Close the menu on tab or escape if onIsOpenChange is provided + // Close the menu on tab or escape if onOpenChange is provided if ( - (isOpen && onIsOpenChange && menuRef.current?.contains(event.target as Node)) || + (isOpen && onOpenChange && menuRef.current?.contains(event.target as Node)) || toggleRef.current?.contains(event.target as Node) ) { if (event.key === 'Escape' || event.key === 'Tab') { - onIsOpenChange(!isOpen); + onOpenChange(!isOpen); toggleRef.current?.focus(); } } }; const handleClickOutside = (event: MouseEvent) => { - // If the event is not on the toggle and onIsOpenChange callback is provided, close the menu - if (isOpen && onIsOpenChange && !toggleRef?.current?.contains(event.target as Node)) { + // If the event is not on the toggle and onOpenChange callback is provided, close the menu + if (isOpen && onOpenChange && !toggleRef?.current?.contains(event.target as Node)) { if (isOpen && !menuRef.current?.contains(event.target as Node)) { - onIsOpenChange(false); + onOpenChange(false); } } }; @@ -82,7 +82,7 @@ export const Dropdown: React.FunctionComponent = ({ window.removeEventListener('keydown', handleMenuKeys); window.removeEventListener('click', handleClickOutside); }; - }, [isOpen, menuRef, onIsOpenChange]); + }, [isOpen, menuRef, onOpenChange]); const menu = ( { innerRef={menuRef} isOpen={isOpen} onSelect={onSelect} - onIsOpenChange={isOpen => setIsOpen(isOpen)} + onOpenChange={isOpen => setIsOpen(isOpen)} toggle={toggleRef => ( Dropdown diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx index 456aed3e811..e675975046b 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithDescriptions.tsx @@ -22,7 +22,7 @@ export const DropdownWithDescriptions: React.FunctionComponent = () => { isOpen={isOpen} onSelect={onSelect} minWidth="150px" - onIsOpenChange={isOpen => setIsOpen(isOpen)} + onOpenChange={isOpen => setIsOpen(isOpen)} toggle={toggleRef => ( Dropdown diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx index df1ed670552..241b451fe9a 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithGroups.tsx @@ -21,7 +21,7 @@ export const DropdownWithGroups: React.FunctionComponent = () => { innerRef={menuRef} isOpen={isOpen} onSelect={onSelect} - onIsOpenChange={isOpen => setIsOpen(isOpen)} + onOpenChange={isOpen => setIsOpen(isOpen)} toggle={toggleRef => ( Dropdown diff --git a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx index 76e883c412e..22f0d584b40 100644 --- a/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx +++ b/packages/react-core/src/next/components/Dropdown/examples/DropdownWithKebabToggle.tsx @@ -23,7 +23,7 @@ export const DropdownWithKebab: React.FunctionComponent = () => { isOpen={isOpen} onSelect={onSelect} minWidth="150px" - onIsOpenChange={isOpen => setIsOpen(isOpen)} + onOpenChange={isOpen => setIsOpen(isOpen)} toggle={toggleRef => ( Date: Tue, 13 Sep 2022 16:30:30 -0400 Subject: [PATCH 13/13] remove old dropdown styles --- .../react-core/src/next/components/Dropdown/Dropdown.tsx | 3 +-- .../src/next/components/Dropdown/DropdownGroup.tsx | 8 +------- .../src/next/components/Dropdown/DropdownItem.tsx | 3 +-- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx index 2b79df3dfd9..f61e9c66672 100644 --- a/packages/react-core/src/next/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/next/components/Dropdown/Dropdown.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; import { css } from '@patternfly/react-styles'; import { Menu, MenuContent, MenuProps } from '../../../components/Menu'; import { Popper } from '../../../helpers/Popper/Popper'; @@ -86,7 +85,7 @@ export const Dropdown: React.FunctionComponent = ({ const menu = ( onSelect(event, itemId)} isPlain={isPlain} diff --git a/packages/react-core/src/next/components/Dropdown/DropdownGroup.tsx b/packages/react-core/src/next/components/Dropdown/DropdownGroup.tsx index acd579ddcb3..e39e60cb925 100644 --- a/packages/react-core/src/next/components/Dropdown/DropdownGroup.tsx +++ b/packages/react-core/src/next/components/Dropdown/DropdownGroup.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; import { css } from '@patternfly/react-styles'; import { MenuGroupProps, MenuGroup } from '../../../components/Menu'; @@ -19,12 +18,7 @@ export const DropdownGroup: React.FunctionComponent = ({ labelHeadingLevel = 'h1', ...props }: DropdownGroupProps) => ( - + {children} ); diff --git a/packages/react-core/src/next/components/Dropdown/DropdownItem.tsx b/packages/react-core/src/next/components/Dropdown/DropdownItem.tsx index 82066d0b23c..a070c9651f3 100644 --- a/packages/react-core/src/next/components/Dropdown/DropdownItem.tsx +++ b/packages/react-core/src/next/components/Dropdown/DropdownItem.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import styles from '@patternfly/react-styles/css/components/Dropdown/dropdown'; import { css } from '@patternfly/react-styles'; import { MenuItemProps, MenuItem } from '../../../components/Menu'; @@ -18,7 +17,7 @@ export const DropdownItem: React.FunctionComponent = ({ description, ...props }: DropdownItemProps) => ( - + {children} );