Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
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