Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/thin-rocks-chew.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/react": minor
---

SelectPanel: Add `subtitle` prop
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion generated/components.json
Original file line number Diff line number Diff line change
Expand Up @@ -3626,7 +3626,7 @@
"stories": [
{
"id": "components-selectpanel--default",
"code": "() => {\n const [selected, setSelected] = React.useState<ItemInput[]>([\n items[0],\n items[1],\n ])\n const [filter, setFilter] = React.useState('')\n const filteredItems = items.filter((item) =>\n item.text.toLowerCase().startsWith(filter.toLowerCase()),\n )\n const [open, setOpen] = useState(false)\n return (\n <>\n <h1>Multi Select Panel</h1>\n <div>Please select labels that describe your issue:</div>\n <SelectPanel\n title=\"Select labels\"\n renderAnchor={({\n children,\n 'aria-labelledby': ariaLabelledBy,\n ...anchorProps\n }) => (\n <Button\n trailingAction={TriangleDownIcon}\n aria-labelledby={` ${ariaLabelledBy}`}\n {...anchorProps}\n >\n {children ?? 'Select Labels'}\n </Button>\n )}\n placeholderText=\"Filter labels\"\n open={open}\n onOpenChange={setOpen}\n items={filteredItems}\n selected={selected}\n onSelectedChange={setSelected}\n onFilterChange={setFilter}\n showItemDividers={true}\n overlayProps={{\n width: 'small',\n height: 'xsmall',\n }}\n />\n </>\n )\n}"
"code": "() => {\n const [selected, setSelected] = React.useState<ItemInput[]>([\n items[0],\n items[1],\n ])\n const [filter, setFilter] = React.useState('')\n const filteredItems = items.filter((item) =>\n item.text.toLowerCase().startsWith(filter.toLowerCase()),\n )\n const [open, setOpen] = useState(false)\n return (\n <>\n <h1>Multi Select Panel</h1>\n <SelectPanel\n title=\"Select labels\"\n subtitle=\"Use labels to organize issues and pull requests\"\n renderAnchor={({\n children,\n 'aria-labelledby': ariaLabelledBy,\n ...anchorProps\n }) => (\n <Button\n trailingAction={TriangleDownIcon}\n aria-labelledby={` ${ariaLabelledBy}`}\n {...anchorProps}\n >\n {children ?? 'Select Labels'}\n </Button>\n )}\n placeholderText=\"Filter labels\"\n open={open}\n onOpenChange={setOpen}\n items={filteredItems}\n selected={selected}\n onSelectedChange={setSelected}\n onFilterChange={setFilter}\n showItemDividers={true}\n overlayProps={{\n width: 'medium',\n height: 'medium',\n }}\n />\n </>\n )\n}"
}
],
"props": [
Expand All @@ -3636,6 +3636,12 @@
"defaultValue": "\"Select an item\" or \"Select items\"",
"description": "A descriptive title for the panel"
},
{
"name": "subtitle",
"type": "string | React.ReactElement",
"defaultValue": "",
"description": "When provided, a subtitle is displayed below the title"
},
{
"name": "onOpenChange",
"type": "( open: boolean, gesture: | 'anchor-click' | 'anchor-key-press' | 'click-outside' | 'escape' | 'selection' ) => void",
Expand Down
6 changes: 6 additions & 0 deletions src/SelectPanel/SelectPanel.docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
"defaultValue": "\"Select an item\" or \"Select items\"",
"description": "A descriptive title for the panel"
},
{
"name": "subtitle",
"type": "string | React.ReactElement",
"defaultValue": "",
"description": "When provided, a subtitle is displayed below the title"
},
{
"name": "onOpenChange",
"type": "( open: boolean, gesture: | 'anchor-click' | 'anchor-key-press' | 'click-outside' | 'escape' | 'selection' ) => void",
Expand Down
4 changes: 2 additions & 2 deletions src/SelectPanel/SelectPanel.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ export const Default = () => {
return (
<>
<h1>Multi Select Panel</h1>
<div>Please select labels that describe your issue:</div>
<SelectPanel
title="Select labels"
subtitle="Use labels to organize issues and pull requests"
renderAnchor={({children, 'aria-labelledby': ariaLabelledBy, ...anchorProps}) => (
<Button trailingAction={TriangleDownIcon} aria-labelledby={` ${ariaLabelledBy}`} {...anchorProps}>
{children ?? 'Select Labels'}
Expand All @@ -66,7 +66,7 @@ export const Default = () => {
onSelectedChange={setSelected}
onFilterChange={setFilter}
showItemDividers={true}
overlayProps={{width: 'small', height: 'xsmall'}}
overlayProps={{width: 'medium', height: 'medium'}}
/>
</>
)
Expand Down
15 changes: 14 additions & 1 deletion src/SelectPanel/SelectPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ interface SelectPanelMultiSelection {
interface SelectPanelBaseProps {
// TODO: Make `title` required in the next major version
title?: string | React.ReactElement
subtitle?: string | React.ReactElement
onOpenChange: (
open: boolean,
gesture: 'anchor-click' | 'anchor-key-press' | 'click-outside' | 'escape' | 'selection',
Expand Down Expand Up @@ -66,6 +67,7 @@ export function SelectPanel({
inputLabel = placeholderText,
selected,
title = isMultiSelectVariant(selected) ? 'Select items' : 'Select an item',
subtitle,
onSelectedChange,
filterValue: externalFilterValue,
onFilterChange: externalOnFilterChange,
Expand All @@ -76,6 +78,7 @@ export function SelectPanel({
...listProps
}: SelectPanelProps): JSX.Element {
const titleId = useId()
const subtitleId = useId()
const [filterValue, setInternalFilterValue] = useProvidedStateOrCreate(externalFilterValue, undefined, '')
const onFilterChange: FilteredActionListProps['onFilterChange'] = useCallback(
(value, e) => {
Expand Down Expand Up @@ -168,7 +171,12 @@ export function SelectPanel({
open={open}
onOpen={onOpen}
onClose={onClose}
overlayProps={{role: 'dialog', 'aria-labelledby': titleId, ...overlayProps}}
overlayProps={{
role: 'dialog',
'aria-labelledby': titleId,
'aria-describedby': subtitle ? subtitleId : undefined,
...overlayProps,
}}
focusTrapSettings={focusTrapSettings}
focusZoneSettings={focusZoneSettings}
>
Expand All @@ -187,6 +195,11 @@ export function SelectPanel({
<Heading as="h1" id={titleId} sx={{fontSize: 1}}>
{title}
</Heading>
{subtitle ? (
<Box id={subtitleId} sx={{fontSize: 0, color: 'fg.muted'}}>
{subtitle}
</Box>
) : null}
</Box>
<FilteredActionList
filterValue={filterValue}
Expand Down
2 changes: 1 addition & 1 deletion src/SelectPanel/__snapshots__/SelectPanel.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ exports[`SelectPanel renders consistently 1`] = `
<button
aria-haspopup="true"
className="c1"
id="react-aria-2"
id="react-aria-3"
onClick={[Function]}
onKeyDown={[Function]}
tabIndex={0}
Expand Down