Skip to content

Commit

Permalink
Both internally and externally managed logic
Browse files Browse the repository at this point in the history
  • Loading branch information
broccolinisoup committed Oct 17, 2024
1 parent 2bf2821 commit 654de86
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ export interface FilteredActionListProps
onFilterChange: (value: string, e: React.ChangeEvent<HTMLInputElement>) => void
textInputProps?: Partial<Omit<TextInputProps, 'onChange'>>
inputRef?: React.RefObject<HTMLInputElement>
childrenToBeRendered?: React.ReactNode[]
emptyState?: boolean
maybeMutatedChildren?: React.ReactNode[]
}

const StyledHeader = styled.div`
Expand All @@ -58,8 +57,7 @@ export function FilteredActionList({
sx,
groupMetadata,
showItemDividers,
emptyState,
childrenToBeRendered,
maybeMutatedChildren,
...listProps
}: FilteredActionListProps): JSX.Element {
const [filterValue, setInternalFilterValue] = useProvidedStateOrCreate(externalFilterValue, undefined, '')
Expand Down Expand Up @@ -163,8 +161,8 @@ export function FilteredActionList({
<Box ref={scrollContainerRef} sx={{overflow: 'auto', height: '100%', display: 'flex', flexGrow: '1'}}>
{loading && scrollContainerRef.current && loadingType.appearsInBody ? (
<FilteredActionListBodyLoader loadingType={loadingType} height={scrollContainerRef.current.clientHeight} />
) : emptyState ? (
childrenToBeRendered
) : maybeMutatedChildren && maybeMutatedChildren.length > 0 ? (
maybeMutatedChildren
) : (
<ActionList
ref={listContainerRef}
Expand Down
93 changes: 59 additions & 34 deletions packages/react/src/SelectPanel/SelectPanel.features.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -445,17 +445,17 @@ export const CustomisedNoInitialItems = () => {
setFilteredItems([])
}, 0)
}
const [isOn, setIsOn] = React.useState(false)
const [isError, setIsError] = React.useState(true)

const onClick = React.useCallback(() => {
setIsOn(!isOn)
}, [setIsOn, isOn])
setIsError(!isError)
}, [setIsError, isError])
return (
<>
<Text id="toggle" fontWeight={'bold'} fontSize={2}>
Enable Error State :{isOn ? 'On' : 'Off'}
Enable Error State :{isError ? 'On' : 'Off'}
</Text>
<ToggleSwitch onClick={onClick} checked={isOn} aria-labelledby="switchLabel" />
<ToggleSwitch onClick={onClick} checked={isError} aria-labelledby="switchLabel" />
<SelectPanel
title="Set projects"
renderAnchor={({children, 'aria-labelledby': ariaLabelledBy, ...anchorProps}) => (
Expand All @@ -471,13 +471,17 @@ export const CustomisedNoInitialItems = () => {
onFilterChange={onFilterChange}
overlayProps={{width: 'medium', height: 'large'}}
>
<SelectPanel.Message variant="noInitialItems" title="You haven't created any projects yet">
<Link href="https://github.com/projects">Start your first project </Link> to organise your issues.
</SelectPanel.Message>
<SelectPanel.Message variant="noFilteredItems" title={`No language found for `}>
Adjust your search term to find other languages
</SelectPanel.Message>
{isOn ? (
{!isError ? (
<SelectPanel.Message variant="noInitialItems" title="You haven't created any projects yet">
<Link href="https://github.com/projects">Start your first project </Link> to organise your issues.
</SelectPanel.Message>
) : null}
{!isError ? (
<SelectPanel.Message variant="noFilteredItems" title={`No language found for `}>
Adjust your search term to find other languages
</SelectPanel.Message>
) : null}
{isError ? (
<SelectPanel.Message variant="error" title={`Ooops`}>
Something is wrong.
</SelectPanel.Message>
Expand All @@ -493,28 +497,49 @@ export const CustomisedNoFilteredItems = () => {
const [open, setOpen] = useState(true)

const filteredItems = items.filter(item => item.text.toLowerCase().startsWith(filter.toLowerCase()))
const [isError, setIsError] = React.useState(true)

const onClick = React.useCallback(() => {
setIsError(!isError)
}, [setIsError, isError])

return (
<SelectPanel
title="Set projects"
renderAnchor={({children, 'aria-labelledby': ariaLabelledBy, ...anchorProps}) => (
<Button trailingAction={TriangleDownIcon} aria-labelledby={` ${ariaLabelledBy}`} {...anchorProps}>
{children ?? 'Select Labels'}
</Button>
)}
open={open}
onOpenChange={setOpen}
items={filteredItems}
selected={selected}
onSelectedChange={setSelected}
onFilterChange={setFilter}
overlayProps={{width: 'medium', height: 'small'}}
>
<SelectPanel.Message variant="noInitialItems" title="You haven't created any projects yet">
<Link href="https://github.com/projects">Start your first project </Link> to organise your issues.
</SelectPanel.Message>
<SelectPanel.Message variant="noFilteredItems" title={`No language found for ${filter}`}>
Adjust your search term to find other languages
</SelectPanel.Message>
</SelectPanel>
<>
<Text id="toggle" fontWeight={'bold'} fontSize={2}>
Enable Error State :{isError ? 'On' : 'Off'}
</Text>
<ToggleSwitch onClick={onClick} checked={isError} aria-labelledby="switchLabel" />
<SelectPanel
title="Set projects"
renderAnchor={({children, 'aria-labelledby': ariaLabelledBy, ...anchorProps}) => (
<Button trailingAction={TriangleDownIcon} aria-labelledby={` ${ariaLabelledBy}`} {...anchorProps}>
{children ?? 'Select Labels'}
</Button>
)}
open={open}
onOpenChange={setOpen}
items={filteredItems}
selected={selected}
onSelectedChange={setSelected}
onFilterChange={setFilter}
overlayProps={{width: 'medium', height: 'small'}}
>
{!isError ? (
<SelectPanel.Message variant="noInitialItems" title="You haven't created any projects yet">
<Link href="https://github.com/projects">Start your first project </Link> to organise your issues.
</SelectPanel.Message>
) : null}
{!isError ? (
<SelectPanel.Message variant="noFilteredItems" title={`No language found for `}>
Adjust your search term to find other languages
</SelectPanel.Message>
) : null}
{isError ? (
<SelectPanel.Message variant="error" title={`Ooops`}>
Something is wrong.
</SelectPanel.Message>
) : null}
</SelectPanel>
</>
)
}
51 changes: 14 additions & 37 deletions packages/react/src/SelectPanel/SelectPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -271,45 +271,23 @@ function Panel({
const isNoItemsState = items.length === 0 && dataLoadedOnce && !loading && filterValue === ''
const isNoMatchState = items.length === 0 && dataLoadedOnce && !loading && filterValue !== ''
const emptyState = isNoItemsState || isNoMatchState ? true : false

Check failure on line 273 in packages/react/src/SelectPanel/SelectPanel.tsx

View workflow job for this annotation

GitHub Actions / lint

'emptyState' is assigned a value but never used
// I don't know anything about error or warning here. They manage their visibility.

// const deconstructChildren = (children: React.ReactNode) => {
// const childrenObject = {}
// // eslint-disable-next-line github/array-foreach
// React.Children.toArray(children).forEach(child => {
// if (!React.isValidElement(child)) return
// if (child.props.variant === 'noInitialItems') childrenObject.noInitialItems = child
// if (child.props.variant === 'noFilteredItems') childrenObject.noFilteredItems = child
// if (child.props.variant === 'error') childrenObject.error = child
// if (child.props.variant === 'warning') childrenObject.warning = child
// })
// return childrenObject
// }

type DeconstructedChild = {
type: React.ElementType
props: Record<string, any>
}

function getChildrenToBeRendered(children: ReactNode): (DeconstructedChild | null)[] {
return React.Children.map(children, child => {
function maybeMutateChildren(children: ReactNode): ReactNode[] {
const newChildren = new Set()

for (const child of React.Children.toArray(children)) {
if (React.isValidElement(child)) {
const {type, props} = child
const variant = props.variant ?? null
if (variant === 'noInitialItems') return isNoItemsState ? child : null
else if (variant === 'noFilteredItems') return isNoMatchState ? child : null
return child
const variant = child.props.variant ?? null
if (variant === 'noInitialItems' && isNoItemsState) newChildren.add(child)
else if (variant === 'noFilteredItems' && isNoMatchState) newChildren.add(child)
else if (variant === 'error' || variant === 'warning') newChildren.add(child)
else () => {}
}
return null
})
}
// @ts-ignore shh
return Array.from(newChildren)
}

// const childrenObject =
const childrenToBeRendered = getChildrenToBeRendered(children)
// The expected return is
console.log(childrenToBeRendered)
// { noInitialItems: child1, noFilteredItems: child2, error: child3, warning: child4 }
// }
const maybeMutatedChildren = maybeMutateChildren(children)

return (
<LiveRegion>
Expand Down Expand Up @@ -368,8 +346,7 @@ function Panel({
inputRef={inputRef}
loading={isLoading}
loadingType={loadingType()}
{...(usingModernActionList ? {childrenToBeRendered: childrenToBeRendered} : {})}
{...(usingModernActionList ? {emptyState} : {})}
{...(usingModernActionList ? {maybeMutatedChildren} : {})}
// 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'}}
Expand Down
12 changes: 7 additions & 5 deletions packages/react/src/SelectPanel/SelectPanelMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import React from 'react'
import Text from '../Text'
import Box from '../Box'
import Octicon from '../Octicon'
import {AlertIcon} from '@primer/octicons-react'

export type SelectPanelMessageProps = {
children: React.ReactNode
title: string
variant: 'noInitialItems' | 'noFilteredItems' | 'error' | 'warning'
}

export const SelectPanelMessage: React.FC<SelectPanelMessageProps> = ({
variant = 'noInitialItems',
title,
children,
}) => {
export const SelectPanelMessage: React.FC<SelectPanelMessageProps> = ({variant, title, children}) => {
// console.log({variant})
return (
<Box
sx={{
Expand All @@ -30,6 +29,9 @@ export const SelectPanelMessage: React.FC<SelectPanelMessageProps> = ({
// maxHeight of dialog - (header & footer)
}}
>
{variant !== 'noInitialItems' && variant !== 'noFilteredItems' ? (
<Octicon icon={AlertIcon} sx={{color: variant === 'error' ? 'danger.fg' : 'attention.fg', marginBottom: 2}} />
) : null}
<Text sx={{fontSize: 1, fontWeight: 'semibold'}}>{title}</Text>
<Text
sx={{fontSize: 1, color: 'fg.muted', display: 'flex', flexDirection: 'column', gap: 2, alignItems: 'center'}}
Expand Down

0 comments on commit 654de86

Please sign in to comment.