Skip to content

Commit

Permalink
Fix experimental SelectPanel anchoring behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
camertron committed Jan 24, 2025
1 parent 88ffc0d commit ff93686
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
--position-top: 0;
--position-left: 0;

&[data-visibility='visible'] {
visibility: visible;
}

&[data-visibility='hidden'] {
visibility: hidden;
}

&:where([open]) {
display: flex; /* to fit children */
}
Expand Down
26 changes: 26 additions & 0 deletions packages/react/src/experimental/SelectPanel2/SelectPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {clsx} from 'clsx'
import {useFeatureFlag} from '../../FeatureFlags'

import classes from './SelectPanel.module.css'
import type {PositionSettings} from '@primer/behaviors'

const CSS_MODULES_FEATURE_FLAG = 'primer_react_css_modules_ga'

Expand Down Expand Up @@ -66,6 +67,7 @@ export type SelectPanelProps = {
defaultOpen?: boolean
open?: boolean
anchorRef?: React.RefObject<HTMLButtonElement>
anchoredPositionSettings?: Partial<PositionSettings>

onCancel?: () => void
onClearSelection?: undefined | (() => void)
Expand All @@ -89,6 +91,7 @@ const Panel: React.FC<SelectPanelProps> = ({
defaultOpen = false,
open: propsOpen,
anchorRef: providedAnchorRef,
anchoredPositionSettings,

onCancel: propsOnCancel,
onClearSelection: propsOnClearSelection,
Expand Down Expand Up @@ -228,6 +231,7 @@ const Panel: React.FC<SelectPanelProps> = ({
floatingElementRef: dialogRef,
side: 'outside-bottom',
align: 'start',
...anchoredPositionSettings,
},
[internalOpen, anchorRef.current, dialogRef.current],
)
Expand All @@ -245,6 +249,20 @@ const Panel: React.FC<SelectPanelProps> = ({
maxHeightValue = '100vh'
}

const [isVisible, setIsVisible] = useState(internalOpen)

useEffect(() => {
if (internalOpen) {
// give the browser time to render the panel and for useAnchoredPosition
// to calculate its actual size
window.requestAnimationFrame(() => {
setIsVisible(true)
})
} else {
setIsVisible(false)
}
}, [internalOpen, setIsVisible])

return (
<>
{Anchor}
Expand All @@ -258,10 +276,18 @@ const Panel: React.FC<SelectPanelProps> = ({
height="fit-content"
maxHeight={maxHeight}
data-variant={currentVariant}
data-visibility={isVisible ? 'visible' : 'hidden'}
sx={
enabled
? undefined
: {
'&[data-visibility="visible"]': {
visibility: 'visible',
},
'&[data-visibility="hidden"]': {
visibility: 'hidden',
},

'--max-height': heightMap[maxHeight],
// reset dialog default styles
border: 'none',
Expand Down
6 changes: 5 additions & 1 deletion packages/react/src/hooks/useAnchoredPosition.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import React, {type RefObject} from 'react'
import {getAnchoredPosition} from '@primer/behaviors'
import type {AnchorPosition, PositionSettings} from '@primer/behaviors'
import {useProvidedRefOrCreate} from './useProvidedRefOrCreate'
Expand Down Expand Up @@ -45,8 +45,12 @@ export function useAnchoredPosition(

useLayoutEffect(updatePosition, [updatePosition])

// recalculate position if viewport changes size
useResizeObserver(updatePosition)

// recalculate position if the floating element changes size
useResizeObserver(updatePosition, floatingElementRef as RefObject<HTMLElement>)

return {
floatingElementRef,
anchorElementRef,
Expand Down

0 comments on commit ff93686

Please sign in to comment.