Skip to content

Commit

Permalink
FilteredActionList inherits height and maxHeight from its parent (#1500)
Browse files Browse the repository at this point in the history
* FilteredActionList inherits height and maxHeight from its parent

* Switch to SelectPanel passing inherit rules via sx prop

* Ensure sx props passed to ListPanel are included
  • Loading branch information
jfuchs authored Oct 6, 2021
1 parent 916f50a commit 8c3531a
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 15 deletions.
5 changes: 5 additions & 0 deletions .changeset/slow-badgers-relate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/components': patch
---

Fixed a bug where SelectPanel would not scroll with height:'auto'; maxHeight:'medium' passed to Overlay (https://github.com/github/primer/issues/333)
9 changes: 7 additions & 2 deletions src/FilteredActionList/FilteredActionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ import {get} from '../constants'
import {useProvidedRefOrCreate} from '../hooks/useProvidedRefOrCreate'
import useScrollFlash from '../hooks/useScrollFlash'
import {useSSRSafeId} from '@react-aria/ssr'
import {SxProp} from '../sx'

export interface FilteredActionListProps extends Partial<Omit<GroupedListProps, keyof ListPropsBase>>, ListPropsBase {
export interface FilteredActionListProps
extends Partial<Omit<GroupedListProps, keyof ListPropsBase>>,
ListPropsBase,
SxProp {
loading?: boolean
placeholderText: string
filterValue?: string
Expand Down Expand Up @@ -57,6 +61,7 @@ export function FilteredActionList({
items,
textInputProps,
inputRef: providedInputRef,
sx,
...listProps
}: FilteredActionListProps): JSX.Element {
const [filterValue, setInternalFilterValue] = useProvidedStateOrCreate(externalFilterValue, undefined, '')
Expand Down Expand Up @@ -120,7 +125,7 @@ export function FilteredActionList({
useScrollFlash(scrollContainerRef)

return (
<Box display="flex" flexDirection="column" overflow="hidden">
<Box display="flex" flexDirection="column" overflow="hidden" sx={sx}>
<StyledHeader>
<TextInput
ref={inputRef}
Expand Down
27 changes: 14 additions & 13 deletions src/SelectPanel/SelectPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {FocusZoneHookSettings} from '../hooks/useFocusZone'
import {DropdownButton} from '../DropdownMenu'
import {ItemProps} from '../ActionList'
import {AnchoredOverlay, AnchoredOverlayProps} from '../AnchoredOverlay'
import Box from '../Box'
import {TextInputProps} from '../TextInput'
import {useProvidedStateOrCreate} from '../hooks/useProvidedStateOrCreate'
import {AnchoredOverlayWrapperAnchorProps} from '../AnchoredOverlay/AnchoredOverlay'
Expand Down Expand Up @@ -61,6 +60,7 @@ export function SelectPanel({
items,
textInputProps,
overlayProps,
sx,
...listProps
}: SelectPanelProps): JSX.Element {
const [filterValue, setInternalFilterValue] = useProvidedStateOrCreate(externalFilterValue, undefined, '')
Expand Down Expand Up @@ -153,18 +153,19 @@ export function SelectPanel({
focusTrapSettings={focusTrapSettings}
focusZoneSettings={focusZoneSettings}
>
<Box display="flex" flexDirection="column" width="100%" height="100%">
<FilteredActionList
filterValue={filterValue}
onFilterChange={onFilterChange}
{...listProps}
role="listbox"
items={itemsToRender}
selectionVariant={isMultiSelectVariant(selected) ? 'multiple' : 'single'}
textInputProps={extendedTextInputProps}
inputRef={inputRef}
/>
</Box>
<FilteredActionList
filterValue={filterValue}
onFilterChange={onFilterChange}
{...listProps}
role="listbox"
items={itemsToRender}
selectionVariant={isMultiSelectVariant(selected) ? 'multiple' : 'single'}
textInputProps={extendedTextInputProps}
inputRef={inputRef}
// inheriting height and maxHeight ensures that the FilteredActionList is never taller
// than the Overlay (which would break scrolling the items)
sx={{...sx, height: 'inherit', maxHeight: 'inherit'}}
/>
</AnchoredOverlay>
)
}
Expand Down
53 changes: 53 additions & 0 deletions src/stories/SelectPanel.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -298,3 +298,56 @@ export function SelectPanelAboveTallBody(): JSX.Element {
)
}
SelectPanelAboveTallBody.storyName = 'SelectPanel, Above a Tall Body'

export function SelectPanelHeightAndScroll(): JSX.Element {
const longItems = [...items, ...items, ...items, ...items, ...items, ...items, ...items, ...items]
const [selectedA, setSelectedA] = React.useState<ItemInput | undefined>(longItems[0])
const [selectedB, setSelectedB] = React.useState<ItemInput | undefined>(longItems[0])
const [filter, setFilter] = React.useState('')
const filteredItems = longItems.filter(item => item.text.toLowerCase().startsWith(filter.toLowerCase()))
const [openA, setOpenA] = useState(false)
const [openB, setOpenB] = useState(false)

return (
<>
<h2>With height:medium</h2>
<SelectPanel
renderAnchor={({children, 'aria-labelledby': ariaLabelledBy, ...anchorProps}) => (
<DropdownButton aria-labelledby={` ${ariaLabelledBy}`} {...anchorProps}>
{children ?? 'Select Labels'}
</DropdownButton>
)}
placeholderText="Filter Labels"
open={openA}
onOpenChange={setOpenA}
items={filteredItems}
selected={selectedA}
onSelectedChange={setSelectedA}
onFilterChange={setFilter}
showItemDividers={true}
overlayProps={{height: 'medium'}}
/>
<h2>With height:auto, maxheight:medium</h2>
<SelectPanel
renderAnchor={({children, 'aria-labelledby': ariaLabelledBy, ...anchorProps}) => (
<DropdownButton aria-labelledby={` ${ariaLabelledBy}`} {...anchorProps}>
{children ?? 'Select Labels'}
</DropdownButton>
)}
placeholderText="Filter Labels"
open={openB}
onOpenChange={setOpenB}
items={filteredItems}
selected={selectedB}
onSelectedChange={setSelectedB}
onFilterChange={setFilter}
showItemDividers={true}
overlayProps={{
height: 'auto',
maxHeight: 'medium'
}}
/>
</>
)
}
SelectPanelHeightAndScroll.storyName = 'SelectPanel, Height and Scroll'

0 comments on commit 8c3531a

Please sign in to comment.