diff --git a/.changeset/fair-sloths-kick.md b/.changeset/fair-sloths-kick.md new file mode 100644 index 00000000000..d2ba47a2483 --- /dev/null +++ b/.changeset/fair-sloths-kick.md @@ -0,0 +1,5 @@ +--- +"@primer/react": minor +--- + +experimental/SelectPanel: Add back button diff --git a/packages/react/src/ActionList/Selection.tsx b/packages/react/src/ActionList/Selection.tsx index d739911003e..e5b9c3e1617 100644 --- a/packages/react/src/ActionList/Selection.tsx +++ b/packages/react/src/ActionList/Selection.tsx @@ -30,7 +30,9 @@ export const Selection: React.FC> = ({se } if (selectionVariant === 'single' || listRole === 'menu') { - return {selected && } + return ( + {selected && } + ) } /** @@ -59,7 +61,7 @@ export const Selection: React.FC> = ({se } return ( - +
{ ) } +export const NestedSelection = () => { + const [panelToShow, setPanelToShow] = React.useState(null) + + const anchorRef = React.useRef(null) + + /* First level: Repo selection */ + const [selectedRepo, setSelectedRepo] = React.useState('') + + const reposToShow = data.repos + + /* Second level: Pull request selection */ + const iconMap = { + open: , + merged: , + draft: , + } + + const initialSelectedPullRequestIds = ['4278'] + const [selectedPullRequestIds, setSelectedPullRequestIds] = React.useState(initialSelectedPullRequestIds) + /* Selection */ + const onPullRequestSelect = (pullId: string) => { + if (!selectedPullRequestIds.includes(pullId)) setSelectedPullRequestIds([...selectedPullRequestIds, pullId]) + else setSelectedPullRequestIds(selectedPullRequestIds.filter(id => id !== pullId)) + } + + return ( + <> +

Nested selection

+ + + This story is not fully accesible, do not copy it without review! + + + + + + {data.pulls + .filter(pull => selectedPullRequestIds.includes(pull.id)) + .map(pull => ( + + {iconMap[pull.status as keyof typeof iconMap]} + {pull.name} + #{pull.id} + {pull.description} + + ))} + + + setPanelToShow('pull_requests')} + onCancel={() => setPanelToShow(null)} + > + + + + + + {reposToShow.map(repo => ( + setSelectedRepo(`${repo.org}/${repo.name}`)} + sx={{'[data-component="ActionList.Selection"]': {display: 'none'}}} + > + + + + {repo.org}/{repo.name} + {repo.description} + + + + + ))} + + + + + + setPanelToShow(null)} + onCancel={() => { + setSelectedPullRequestIds(initialSelectedPullRequestIds) + setPanelToShow('repos') + }} + > + setPanelToShow('repos')}> + + + + + {data.pulls.map(pull => ( + onPullRequestSelect(pull.id)} + > + {iconMap[pull.status as keyof typeof iconMap]} + {pull.name} + #{pull.id} + {pull.description} + + ))} + + + + + + ) +} + // ----- Suspense implementation details ---- const cache = new Map() diff --git a/packages/react/src/drafts/SelectPanel2/SelectPanel.tsx b/packages/react/src/drafts/SelectPanel2/SelectPanel.tsx index ad88709f7dc..9943e1862f2 100644 --- a/packages/react/src/drafts/SelectPanel2/SelectPanel.tsx +++ b/packages/react/src/drafts/SelectPanel2/SelectPanel.tsx @@ -1,5 +1,5 @@ import React from 'react' -import {SearchIcon, XCircleFillIcon, XIcon, FilterRemoveIcon, AlertIcon} from '@primer/octicons-react' +import {SearchIcon, XCircleFillIcon, XIcon, FilterRemoveIcon, AlertIcon, ArrowLeftIcon} from '@primer/octicons-react' import {FocusKeys} from '@primer/behaviors' import type {ButtonProps, TextInputProps, ActionListProps, LinkProps, CheckboxProps} from '../../index' @@ -192,7 +192,10 @@ const Panel: React.FC = ({ // tl;dr: react takes over autofocus instead of letting the browser handle it, // but not for dialogs, so we have to do it React.useEffect(() => { - if (internalOpen) document.querySelector('input')?.focus() + if (internalOpen) { + const searchInput = document.querySelector('dialog[open] input') as HTMLInputElement | undefined + searchInput?.focus() + } }, [internalOpen]) /* Anchored */ @@ -307,7 +310,7 @@ const SelectPanelButton = React.forwardRef((prop return