From 1db6c0e828ebda6afd9376c98ea2e87db87fc214 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Tue, 1 Dec 2020 14:05:58 -0800 Subject: [PATCH 1/7] combobox menu should remeasure whenever the combobox input/button change size --- .../@react-spectrum/combobox/src/ComboBox.tsx | 17 ++++++----- .../combobox/stories/ComboBox.stories.tsx | 28 +++++++++++++++++-- .../@react-spectrum/picker/src/Picker.tsx | 15 +++++++--- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/packages/@react-spectrum/combobox/src/ComboBox.tsx b/packages/@react-spectrum/combobox/src/ComboBox.tsx index 3840bd0bc57..a327147a739 100644 --- a/packages/@react-spectrum/combobox/src/ComboBox.tsx +++ b/packages/@react-spectrum/combobox/src/ComboBox.tsx @@ -12,7 +12,7 @@ import {AriaButtonProps} from '@react-types/button'; import ChevronDownMedium from '@spectrum-icons/ui/ChevronDownMedium'; -import {classNames, unwrapDOMRef, useFocusableRef, useIsMobileDevice} from '@react-spectrum/utils'; +import {classNames, unwrapDOMRef, useFocusableRef, useIsMobileDevice, useResizeObserver} from '@react-spectrum/utils'; import {DismissButton, useOverlayPosition} from '@react-aria/overlays'; import {DOMRefValue, FocusableRef, FocusableRefValue} from '@react-types/shared'; import {Field} from '@react-spectrum/label'; @@ -23,15 +23,14 @@ import {MobileComboBox} from './MobileComboBox'; import {Placement} from '@react-types/overlays'; import {Popover} from '@react-spectrum/overlays'; import {PressResponder, useHover} from '@react-aria/interactions'; -import React, {InputHTMLAttributes, ReactElement, RefObject, useRef, useState} from 'react'; +import React, {InputHTMLAttributes, ReactElement, RefObject, useCallback, useRef, useState} from 'react'; import {SpectrumComboBoxProps} from '@react-types/combobox'; import styles from '@adobe/spectrum-css-temp/components/inputgroup/vars.css'; import {TextFieldBase} from '@react-spectrum/textfield'; import {useComboBox} from '@react-aria/combobox'; import {useComboBoxState} from '@react-stately/combobox'; import {useFilter} from '@react-aria/i18n'; -import {useLayoutEffect} from '@react-aria/utils'; -import {useProvider, useProviderProps} from '@react-spectrum/provider'; +import {useProviderProps} from '@react-spectrum/provider'; function ComboBox(props: SpectrumComboBoxProps, ref: FocusableRef) { props = useProviderProps(props); @@ -86,13 +85,17 @@ const ComboBoxBase = React.forwardRef(function ComboBoxBase(pr // Measure the width of the inputfield and the button to inform the width of the menu (below). let [menuWidth, setMenuWidth] = useState(null); - let {scale} = useProvider(); - useLayoutEffect(() => { + let onResize = useCallback(() => { let buttonWidth = buttonRef.current.UNSAFE_getDOMNode().offsetWidth; let inputWidth = inputRef.current.offsetWidth; setMenuWidth(buttonWidth + inputWidth); - }, [scale, buttonRef, inputRef]); + }, [buttonRef, inputRef, setMenuWidth]); + + useResizeObserver({ + ref: domRef, + onResize: onResize + }); let style = { ...overlayProps.style, diff --git a/packages/@react-spectrum/combobox/stories/ComboBox.stories.tsx b/packages/@react-spectrum/combobox/stories/ComboBox.stories.tsx index 9ea867143e8..f86b0e0872b 100644 --- a/packages/@react-spectrum/combobox/stories/ComboBox.stories.tsx +++ b/packages/@react-spectrum/combobox/stories/ComboBox.stories.tsx @@ -14,13 +14,13 @@ import {action} from '@storybook/addon-actions'; import Add from '@spectrum-icons/workflow/Add'; import Alert from '@spectrum-icons/workflow/Alert'; import Bell from '@spectrum-icons/workflow/Bell'; -import {Button} from '@react-spectrum/button'; +import {ActionButton, Button} from '@react-spectrum/button'; import {ButtonGroup} from '@react-spectrum/buttongroup'; import {ComboBox, Item, Section} from '../'; import Copy from '@spectrum-icons/workflow/Copy'; import Draw from '@spectrum-icons/workflow/Draw'; import {Flex} from '@react-spectrum/layout'; -import React from 'react'; +import React, {useState} from 'react'; import {storiesOf} from '@storybook/react'; import {Text} from '@react-spectrum/text'; import {TextField} from '@react-spectrum/textfield'; @@ -343,6 +343,10 @@ storiesOf('ComboBox', module) ) ) + .add( + 'resize', + () => + ) .add( 'in small div', () => ( @@ -659,6 +663,26 @@ function AllControlledOpenComboBox(props) { ); } +function ResizeCombobox() { + let [size, setSize] = useState(true); + + return ( + +
+ + Item One + + + Item Two + + Item Three + +
+ setSize(prev => !prev)}>Toggle size +
+ ); +} + function render(props = {}) { return ( diff --git a/packages/@react-spectrum/picker/src/Picker.tsx b/packages/@react-spectrum/picker/src/Picker.tsx index 4ea1c424f18..1fee1824217 100644 --- a/packages/@react-spectrum/picker/src/Picker.tsx +++ b/packages/@react-spectrum/picker/src/Picker.tsx @@ -12,7 +12,16 @@ import AlertMedium from '@spectrum-icons/ui/AlertMedium'; import ChevronDownMedium from '@spectrum-icons/ui/ChevronDownMedium'; -import {classNames, dimensionValue, SlotProvider, unwrapDOMRef, useDOMRef, useIsMobileDevice, useStyleProps} from '@react-spectrum/utils'; +import { + classNames, + dimensionValue, + SlotProvider, + unwrapDOMRef, + useDOMRef, + useIsMobileDevice, + useStyleProps, + useUnwrapDOMRef +} from '@react-spectrum/utils'; import {DismissButton, useOverlayPosition} from '@react-aria/overlays'; import {DOMRef, DOMRefValue, FocusableRefValue, LabelPosition} from '@react-types/shared'; import {FieldButton} from '@react-spectrum/button'; @@ -134,9 +143,7 @@ function Picker(props: SpectrumPickerProps, ref: DOMRef unwrapDOMRef(triggerRef), [triggerRef]); + let resizeRef = useUnwrapDOMRef(triggerRef); let onResize = useCallback(() => { let width = resizeRef.current.offsetWidth; From 8019a707454883d247c691997720c278c69cca09 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Tue, 1 Dec 2020 14:29:10 -0800 Subject: [PATCH 2/7] fix lint --- packages/@react-spectrum/combobox/stories/ComboBox.stories.tsx | 2 +- packages/@react-spectrum/picker/src/Picker.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@react-spectrum/combobox/stories/ComboBox.stories.tsx b/packages/@react-spectrum/combobox/stories/ComboBox.stories.tsx index f86b0e0872b..875cb846bdd 100644 --- a/packages/@react-spectrum/combobox/stories/ComboBox.stories.tsx +++ b/packages/@react-spectrum/combobox/stories/ComboBox.stories.tsx @@ -11,10 +11,10 @@ */ import {action} from '@storybook/addon-actions'; +import {ActionButton, Button} from '@react-spectrum/button'; import Add from '@spectrum-icons/workflow/Add'; import Alert from '@spectrum-icons/workflow/Alert'; import Bell from '@spectrum-icons/workflow/Bell'; -import {ActionButton, Button} from '@react-spectrum/button'; import {ButtonGroup} from '@react-spectrum/buttongroup'; import {ComboBox, Item, Section} from '../'; import Copy from '@spectrum-icons/workflow/Copy'; diff --git a/packages/@react-spectrum/picker/src/Picker.tsx b/packages/@react-spectrum/picker/src/Picker.tsx index 1fee1824217..63fa454bf0e 100644 --- a/packages/@react-spectrum/picker/src/Picker.tsx +++ b/packages/@react-spectrum/picker/src/Picker.tsx @@ -37,7 +37,7 @@ import {Placement} from '@react-types/overlays'; import {Popover, Tray} from '@react-spectrum/overlays'; import {PressResponder, useHover} from '@react-aria/interactions'; import {ProgressCircle} from '@react-spectrum/progress'; -import React, {ReactElement, useCallback, useMemo, useRef, useState} from 'react'; +import React, {ReactElement, useCallback, useRef, useState} from 'react'; import {SpectrumPickerProps} from '@react-types/select'; import styles from '@adobe/spectrum-css-temp/components/dropdown/vars.css'; import {Text} from '@react-spectrum/text'; From aa1c1aca3e7cfcffc4bf1a02cd6a70a80e570a4c Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Tue, 1 Dec 2020 14:56:47 -0800 Subject: [PATCH 3/7] Merge in changes from tomsontom --- .../@react-spectrum/picker/src/Picker.tsx | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/packages/@react-spectrum/picker/src/Picker.tsx b/packages/@react-spectrum/picker/src/Picker.tsx index 63fa454bf0e..a1d39989f81 100644 --- a/packages/@react-spectrum/picker/src/Picker.tsx +++ b/packages/@react-spectrum/picker/src/Picker.tsx @@ -16,7 +16,6 @@ import { classNames, dimensionValue, SlotProvider, - unwrapDOMRef, useDOMRef, useIsMobileDevice, useStyleProps, @@ -43,7 +42,7 @@ import styles from '@adobe/spectrum-css-temp/components/dropdown/vars.css'; import {Text} from '@react-spectrum/text'; import {useFormProps} from '@react-spectrum/form'; import {useMessageFormatter} from '@react-aria/i18n'; -import {useProvider, useProviderProps} from '@react-spectrum/provider'; +import {useProviderProps} from '@react-spectrum/provider'; import {useSelectState} from '@react-stately/select'; function Picker(props: SpectrumPickerProps, ref: DOMRef) { @@ -72,7 +71,9 @@ function Picker(props: SpectrumPickerProps, ref: DOMRef>(); + let unwrappedPopoverRef = useUnwrapDOMRef(popoverRef); let triggerRef = useRef>(); + let unwrappedTriggerRef = useUnwrapDOMRef(triggerRef); let listboxRef = useRef(); // We create the listbox layout in Picker and pass it to ListBoxBase below @@ -82,12 +83,12 @@ function Picker(props: SpectrumPickerProps, ref: DOMRef(props: SpectrumPickerProps, ref: DOMRef { - if (!isMobile) { - let width = triggerRef.current.UNSAFE_getDOMNode().offsetWidth; - setButtonWidth(width); - } - }, [scale, isMobile, triggerRef, state.selectedKey]); - - let resizeRef = useUnwrapDOMRef(triggerRef); let onResize = useCallback(() => { - let width = resizeRef.current.offsetWidth; + let width = unwrappedTriggerRef.current.offsetWidth; setButtonWidth(width); - }, [resizeRef, setButtonWidth]); + }, [unwrappedTriggerRef, setButtonWidth]); useResizeObserver({ - ref: resizeRef, + ref: unwrappedTriggerRef, onResize: onResize }); @@ -209,7 +201,7 @@ function Picker(props: SpectrumPickerProps, ref: DOMRef From 0501f7dec807cac9a5ea6ad2b7f61deb87b200ff Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Tue, 1 Dec 2020 17:00:20 -0800 Subject: [PATCH 4/7] put back in the fallback for non-resize observers --- .../@react-spectrum/combobox/src/ComboBox.tsx | 42 +++++++++++++++---- .../@react-spectrum/picker/src/Picker.tsx | 16 +++++-- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/packages/@react-spectrum/combobox/src/ComboBox.tsx b/packages/@react-spectrum/combobox/src/ComboBox.tsx index a327147a739..0e97ae1fd35 100644 --- a/packages/@react-spectrum/combobox/src/ComboBox.tsx +++ b/packages/@react-spectrum/combobox/src/ComboBox.tsx @@ -12,7 +12,14 @@ import {AriaButtonProps} from '@react-types/button'; import ChevronDownMedium from '@spectrum-icons/ui/ChevronDownMedium'; -import {classNames, unwrapDOMRef, useFocusableRef, useIsMobileDevice, useResizeObserver} from '@react-spectrum/utils'; +import { + classNames, + unwrapDOMRef, + useFocusableRef, + useIsMobileDevice, + useResizeObserver, + useUnwrapDOMRef +} from '@react-spectrum/utils'; import {DismissButton, useOverlayPosition} from '@react-aria/overlays'; import {DOMRefValue, FocusableRef, FocusableRefValue} from '@react-types/shared'; import {Field} from '@react-spectrum/label'; @@ -23,14 +30,22 @@ import {MobileComboBox} from './MobileComboBox'; import {Placement} from '@react-types/overlays'; import {Popover} from '@react-spectrum/overlays'; import {PressResponder, useHover} from '@react-aria/interactions'; -import React, {InputHTMLAttributes, ReactElement, RefObject, useCallback, useRef, useState} from 'react'; +import React, { + InputHTMLAttributes, + ReactElement, + RefObject, + useCallback, + useRef, + useState +} from 'react'; import {SpectrumComboBoxProps} from '@react-types/combobox'; import styles from '@adobe/spectrum-css-temp/components/inputgroup/vars.css'; import {TextFieldBase} from '@react-spectrum/textfield'; import {useComboBox} from '@react-aria/combobox'; import {useComboBoxState} from '@react-stately/combobox'; import {useFilter} from '@react-aria/i18n'; -import {useProviderProps} from '@react-spectrum/provider'; +import {useLayoutEffect} from '@react-aria/utils'; +import {useProvider, useProviderProps} from '@react-spectrum/provider'; function ComboBox(props: SpectrumComboBoxProps, ref: FocusableRef) { props = useProviderProps(props); @@ -51,7 +66,9 @@ const ComboBoxBase = React.forwardRef(function ComboBoxBase(pr } = props; let popoverRef = useRef>(); + let unwrappedPopoverRef = useUnwrapDOMRef(popoverRef); let buttonRef = useRef>(); + let unwrappedButtonRef = useUnwrapDOMRef(buttonRef); let listBoxRef = useRef(); let inputRef = useRef(); let domRef = useFocusableRef(ref, inputRef); @@ -64,8 +81,8 @@ const ComboBoxBase = React.forwardRef(function ComboBoxBase(pr { ...props, keyboardDelegate: layout, - buttonRef: unwrapDOMRef(buttonRef), - popoverRef: unwrapDOMRef(popoverRef), + buttonRef: unwrappedButtonRef, + popoverRef: unwrappedPopoverRef, listBoxRef, inputRef: inputRef, menuTrigger @@ -74,8 +91,8 @@ const ComboBoxBase = React.forwardRef(function ComboBoxBase(pr ); let {overlayProps, placement} = useOverlayPosition({ - targetRef: unwrapDOMRef(buttonRef), - overlayRef: unwrapDOMRef(popoverRef), + targetRef: unwrappedButtonRef, + overlayRef: unwrappedPopoverRef, scrollRef: listBoxRef, placement: `${direction} end` as Placement, shouldFlip: shouldFlip, @@ -85,18 +102,25 @@ const ComboBoxBase = React.forwardRef(function ComboBoxBase(pr // Measure the width of the inputfield and the button to inform the width of the menu (below). let [menuWidth, setMenuWidth] = useState(null); + let {scale} = useProvider(); let onResize = useCallback(() => { - let buttonWidth = buttonRef.current.UNSAFE_getDOMNode().offsetWidth; + let buttonWidth = unwrappedButtonRef.current.offsetWidth; let inputWidth = inputRef.current.offsetWidth; setMenuWidth(buttonWidth + inputWidth); - }, [buttonRef, inputRef, setMenuWidth]); + }, [unwrappedButtonRef, inputRef, setMenuWidth]); useResizeObserver({ ref: domRef, onResize: onResize }); + useLayoutEffect(() => { + let buttonWidth = unwrappedButtonRef.current.offsetWidth; + let inputWidth = inputRef.current.offsetWidth; + setMenuWidth(buttonWidth + inputWidth); + }, [scale, unwrappedButtonRef, inputRef]); + let style = { ...overlayProps.style, width: menuWidth diff --git a/packages/@react-spectrum/picker/src/Picker.tsx b/packages/@react-spectrum/picker/src/Picker.tsx index a1d39989f81..3242ac4624b 100644 --- a/packages/@react-spectrum/picker/src/Picker.tsx +++ b/packages/@react-spectrum/picker/src/Picker.tsx @@ -42,7 +42,7 @@ import styles from '@adobe/spectrum-css-temp/components/dropdown/vars.css'; import {Text} from '@react-spectrum/text'; import {useFormProps} from '@react-spectrum/form'; import {useMessageFormatter} from '@react-aria/i18n'; -import {useProviderProps} from '@react-spectrum/provider'; +import {useProvider, useProviderProps} from '@react-spectrum/provider'; import {useSelectState} from '@react-stately/select'; function Picker(props: SpectrumPickerProps, ref: DOMRef) { @@ -136,10 +136,13 @@ function Picker(props: SpectrumPickerProps, ref: DOMRef { - let width = unwrappedTriggerRef.current.offsetWidth; - setButtonWidth(width); + if (!isMobile) { + let width = unwrappedTriggerRef.current.offsetWidth; + setButtonWidth(width); + } }, [unwrappedTriggerRef, setButtonWidth]); useResizeObserver({ @@ -147,6 +150,13 @@ function Picker(props: SpectrumPickerProps, ref: DOMRef { + if (!isMobile) { + let width = unwrappedTriggerRef.current.offsetWidth; + setButtonWidth(width); + } + }, [scale, isMobile, unwrappedTriggerRef, state.selectedKey]); + let overlay; if (isMobile) { overlay = ( From 12697ef6b470be5c5a35da58e65a676d14c9e65f Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Tue, 1 Dec 2020 17:02:24 -0800 Subject: [PATCH 5/7] fix lint --- packages/@react-spectrum/combobox/src/ComboBox.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@react-spectrum/combobox/src/ComboBox.tsx b/packages/@react-spectrum/combobox/src/ComboBox.tsx index 0e97ae1fd35..9f10b5b7f93 100644 --- a/packages/@react-spectrum/combobox/src/ComboBox.tsx +++ b/packages/@react-spectrum/combobox/src/ComboBox.tsx @@ -14,7 +14,6 @@ import {AriaButtonProps} from '@react-types/button'; import ChevronDownMedium from '@spectrum-icons/ui/ChevronDownMedium'; import { classNames, - unwrapDOMRef, useFocusableRef, useIsMobileDevice, useResizeObserver, From a0a8240ada3e74003c18943edb6ea38e2ce0d4bf Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Wed, 2 Dec 2020 10:04:09 -0800 Subject: [PATCH 6/7] reuse code --- packages/@react-spectrum/combobox/src/ComboBox.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/@react-spectrum/combobox/src/ComboBox.tsx b/packages/@react-spectrum/combobox/src/ComboBox.tsx index 9f10b5b7f93..bb466e7d940 100644 --- a/packages/@react-spectrum/combobox/src/ComboBox.tsx +++ b/packages/@react-spectrum/combobox/src/ComboBox.tsx @@ -114,11 +114,7 @@ const ComboBoxBase = React.forwardRef(function ComboBoxBase(pr onResize: onResize }); - useLayoutEffect(() => { - let buttonWidth = unwrappedButtonRef.current.offsetWidth; - let inputWidth = inputRef.current.offsetWidth; - setMenuWidth(buttonWidth + inputWidth); - }, [scale, unwrappedButtonRef, inputRef]); + useLayoutEffect(onResize, [scale, onResize]); let style = { ...overlayProps.style, From 2aff420a6385af97c5f56cf57b3d7e099314dc1d Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Wed, 2 Dec 2020 10:05:51 -0800 Subject: [PATCH 7/7] reuse code --- packages/@react-spectrum/picker/src/Picker.tsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/@react-spectrum/picker/src/Picker.tsx b/packages/@react-spectrum/picker/src/Picker.tsx index 3242ac4624b..90bbb9c935d 100644 --- a/packages/@react-spectrum/picker/src/Picker.tsx +++ b/packages/@react-spectrum/picker/src/Picker.tsx @@ -143,19 +143,14 @@ function Picker(props: SpectrumPickerProps, ref: DOMRef { - if (!isMobile) { - let width = unwrappedTriggerRef.current.offsetWidth; - setButtonWidth(width); - } - }, [scale, isMobile, unwrappedTriggerRef, state.selectedKey]); + useLayoutEffect(onResize, [scale, state.selectedKey, onResize]); let overlay; if (isMobile) {