Skip to content
1 change: 1 addition & 0 deletions packages/react/src/FeatureFlags/DefaultFeatureFlags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export const DefaultFeatureFlags = FeatureFlagScope.create({
primer_react_overlay_overflow: false,
primer_react_segmented_control_tooltip: false,
primer_react_select_panel_fullscreen_on_narrow: false,
primer_react_select_panel_order_selected_at_top: true,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any issues with having a FF on by default? 🤔

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope! Should be okay 👍

})
6 changes: 6 additions & 0 deletions packages/react/src/SelectPanel/SelectPanel.docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@
"type": "React.ReactElement",
"defaultValue": "null",
"description": "Secondary action, it will be rendered in the footer of the panel"
},
{
"name": "showSelectedOptionsFirst",
"type": "boolean",
"description": "Whether to display the selected items at the top of the list",
"default": "true"
}
],
"subcomponents": []
Expand Down
100 changes: 24 additions & 76 deletions packages/react/src/SelectPanel/SelectPanel.examples.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,7 @@ export const HeightInitialWithOverflowingItemsStory = () => {
const [selected, setSelected] = useState<ItemInput[]>(items.slice(1, 3))
const [filter, setFilter] = useState('')
const filteredItems = items.filter(item => item.text.toLowerCase().startsWith(filter.toLowerCase()))
// design guidelines say to sort selected items first
const selectedItemsSortedFirst = filteredItems.sort((a, b) => {
const aIsSelected = selected.some(selectedItem => selectedItem.text === a.text)
const bIsSelected = selected.some(selectedItem => selectedItem.text === b.text)
if (aIsSelected && !bIsSelected) return -1
if (!aIsSelected && bIsSelected) return 1
return 0
})

const [open, setOpen] = useState(false)

return (
Expand All @@ -79,12 +72,12 @@ export const HeightInitialWithOverflowingItemsStory = () => {
placeholder="Select labels" // button text when no items are selected
open={open}
onOpenChange={setOpen}
items={selectedItemsSortedFirst}
items={filteredItems}
selected={selected}
onSelectedChange={setSelected}
onFilterChange={setFilter}
overlayProps={{width: 'small', height: 'initial', maxHeight: 'xsmall'}}
message={selectedItemsSortedFirst.length === 0 ? NoResultsMessage(filter) : undefined}
message={filteredItems.length === 0 ? NoResultsMessage(filter) : undefined}
/>
</FormControl>
)
Expand All @@ -96,14 +89,7 @@ export const HeightInitialWithUnderflowingItemsStory = () => {
const [selected, setSelected] = useState<ItemInput[]>([underflowingItems[0]])
const [filter, setFilter] = useState('')
const filteredItems = underflowingItems.filter(item => item.text.toLowerCase().startsWith(filter.toLowerCase()))
// design guidelines say to sort selected items first
const selectedItemsSortedFirst = filteredItems.sort((a, b) => {
const aIsSelected = selected.some(selectedItem => selectedItem.text === a.text)
const bIsSelected = selected.some(selectedItem => selectedItem.text === b.text)
if (aIsSelected && !bIsSelected) return -1
if (!aIsSelected && bIsSelected) return 1
return 0
})

const [open, setOpen] = useState(false)

return (
Expand All @@ -118,13 +104,13 @@ export const HeightInitialWithUnderflowingItemsStory = () => {
placeholder="Select labels" // button text when no items are selected
open={open}
onOpenChange={setOpen}
items={selectedItemsSortedFirst}
items={filteredItems}
selected={selected}
onSelectedChange={setSelected}
onFilterChange={setFilter}
showItemDividers={true}
overlayProps={{width: 'small', height: 'initial', maxHeight: 'xsmall'}}
message={selectedItemsSortedFirst.length === 0 ? NoResultsMessage(filter) : undefined}
message={filteredItems.length === 0 ? NoResultsMessage(filter) : undefined}
/>
</FormControl>
)
Expand All @@ -139,14 +125,7 @@ export const HeightInitialWithUnderflowingItemsAfterFetch = () => {
() => fetchedItems.filter(item => item.text.toLowerCase().startsWith(filter.toLowerCase())),
[fetchedItems, filter],
)
// design guidelines say to sort selected items first
const selectedItemsSortedFirst = filteredItems.sort((a, b) => {
const aIsSelected = selected.some(selectedItem => selectedItem.text === a.text)
const bIsSelected = selected.some(selectedItem => selectedItem.text === b.text)
if (aIsSelected && !bIsSelected) return -1
if (!aIsSelected && bIsSelected) return 1
return 0
})

const [open, setOpen] = useState(false)
const [height, setHeight] = useState<OverlayProps['height']>('auto')

Expand All @@ -171,13 +150,13 @@ export const HeightInitialWithUnderflowingItemsAfterFetch = () => {
open={open}
onOpenChange={onOpenChange}
loading={filteredItems.length === 0 && !filter}
items={selectedItemsSortedFirst}
items={filteredItems}
selected={selected}
onSelectedChange={setSelected}
onFilterChange={setFilter}
showItemDividers={true}
overlayProps={{width: 'small', height, maxHeight: 'xsmall'}}
message={selectedItemsSortedFirst.length === 0 ? NoResultsMessage(filter) : undefined}
message={filteredItems.length === 0 ? NoResultsMessage(filter) : undefined}
/>
</FormControl>
)
Expand All @@ -188,14 +167,7 @@ export const AboveTallBody = () => {
const [selected, setSelected] = useState<ItemInput[]>(items.slice(1, 3))
const [filter, setFilter] = useState('')
const filteredItems = items.filter(item => item.text.toLowerCase().startsWith(filter.toLowerCase()))
// design guidelines say to sort selected items first
const selectedItemsSortedFirst = filteredItems.sort((a, b) => {
const aIsSelected = selected.some(selectedItem => selectedItem.text === a.text)
const bIsSelected = selected.some(selectedItem => selectedItem.text === b.text)
if (aIsSelected && !bIsSelected) return -1
if (!aIsSelected && bIsSelected) return 1
return 0
})

const [open, setOpen] = useState(false)
return (
<FormControl>
Expand All @@ -209,12 +181,12 @@ export const AboveTallBody = () => {
placeholder="Select labels" // button text when no items are selected
open={open}
onOpenChange={setOpen}
items={selectedItemsSortedFirst}
items={filteredItems}
selected={selected}
onSelectedChange={setSelected}
onFilterChange={setFilter}
showItemDividers={true}
message={selectedItemsSortedFirst.length === 0 ? NoResultsMessage(filter) : undefined}
message={filteredItems.length === 0 ? NoResultsMessage(filter) : undefined}
/>
<div
style={{
Expand All @@ -238,23 +210,13 @@ export const HeightVariationsAndScroll = () => {
// Example A
const [selectedA, setSelectedA] = React.useState<ItemInput | undefined>(longItems[0])
const filteredItemsA = longItems.filter(item => item.text.toLowerCase().startsWith(filter.toLowerCase()))
// design guidelines say to sort selected items first
const selectedItemsSortedFirstA = filteredItemsA.sort((a, b) => {
if (a.text === selectedA?.text) return -1
if (b.text === selectedA?.text) return 1
return 0
})

const [openA, setOpenA] = useState(false)

// Example B
const [selectedB, setSelectedB] = React.useState<ItemInput | undefined>(longItems[0])
const filteredItemsB = longItems.filter(item => item.text.toLowerCase().startsWith(filter.toLowerCase()))
// design guidelines say to sort selected items first
const selectedItemsSortedFirstB = filteredItemsB.sort((a, b) => {
if (a.text === selectedB?.text) return -1
if (b.text === selectedB?.text) return 1
return 0
})

const [openB, setOpenB] = useState(false)

return (
Expand All @@ -270,13 +232,13 @@ export const HeightVariationsAndScroll = () => {
placeholder="Select labels" // button text when no items are selected
open={openA}
onOpenChange={setOpenA}
items={selectedItemsSortedFirstA}
items={filteredItemsA}
selected={selectedA}
onSelectedChange={setSelectedA}
onFilterChange={setFilter}
showItemDividers={true}
overlayProps={{height: 'medium'}}
message={selectedItemsSortedFirstA.length === 0 ? NoResultsMessage(filter) : undefined}
message={filteredItemsA.length === 0 ? NoResultsMessage(filter) : undefined}
/>
</FormControl>
<br />
Expand All @@ -291,7 +253,7 @@ export const HeightVariationsAndScroll = () => {
placeholder="Select labels" // button text when no items are selected
open={openB}
onOpenChange={setOpenB}
items={selectedItemsSortedFirstB}
items={filteredItemsB}
selected={selectedB}
onSelectedChange={setSelectedB}
onFilterChange={setFilter}
Expand All @@ -300,7 +262,7 @@ export const HeightVariationsAndScroll = () => {
height: 'auto',
maxHeight: 'medium',
}}
message={selectedItemsSortedFirstB.length === 0 ? NoResultsMessage(filter) : undefined}
message={filteredItemsB.length === 0 ? NoResultsMessage(filter) : undefined}
/>
</FormControl>
</>
Expand All @@ -317,14 +279,7 @@ export const CustomItemRenderer = () => {
const [selected, setSelected] = useState<ItemInput[]>(items.slice(1, 3))
const [filter, setFilter] = useState('')
const filteredItems = items.filter(item => item.text.toLowerCase().startsWith(filter.toLowerCase()))
// design guidelines say to sort selected items first
const selectedItemsSortedFirst = filteredItems.sort((a, b) => {
const aIsSelected = selected.some(selectedItem => selectedItem.text === a.text)
const bIsSelected = selected.some(selectedItem => selectedItem.text === b.text)
if (aIsSelected && !bIsSelected) return -1
if (!aIsSelected && bIsSelected) return 1
return 0
})

const [open, setOpen] = useState(false)

return (
Expand All @@ -339,7 +294,7 @@ export const CustomItemRenderer = () => {
)}
open={open}
onOpenChange={setOpen}
items={selectedItemsSortedFirst}
items={filteredItems}
selected={selected}
onSelectedChange={setSelected}
onFilterChange={setFilter}
Expand Down Expand Up @@ -369,7 +324,7 @@ export const CustomItemRenderer = () => {
</Box>
</ActionList.Item>
)}
message={selectedItemsSortedFirst.length === 0 ? NoResultsMessage(filter) : undefined}
message={filteredItems.length === 0 ? NoResultsMessage(filter) : undefined}
/>
</FormControl>
)
Expand All @@ -392,14 +347,7 @@ export const ItemsInScope = () => {
const [selected, setSelected] = useState<ItemInput[]>(items.slice(1, 3))
const [filter, setFilter] = useState('')
const filteredItems = items.filter(item => item.text.toLowerCase().startsWith(filter.toLowerCase()))
// design guidelines say to sort selected items first
const selectedItemsSortedFirst = filteredItems.sort((a, b) => {
const aIsSelected = selected.some(selectedItem => selectedItem.text === a.text)
const bIsSelected = selected.some(selectedItem => selectedItem.text === b.text)
if (aIsSelected && !bIsSelected) return -1
if (!aIsSelected && bIsSelected) return 1
return 0
})

const [open, setOpen] = useState(false)
return (
<FormControl>
Expand All @@ -409,11 +357,11 @@ export const ItemsInScope = () => {
placeholder="Select labels" // button text when no items are selected
open={open}
onOpenChange={setOpen}
items={selectedItemsSortedFirst}
items={filteredItems}
selected={selected}
onSelectedChange={setSelected}
onFilterChange={setFilter}
message={selectedItemsSortedFirst.length === 0 ? NoResultsMessage(filter) : undefined}
message={filteredItems.length === 0 ? NoResultsMessage(filter) : undefined}
/>
</FormControl>
)
Expand Down
Loading