Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
1a70c2b
chore: add Selection type to ActionList exports
francinelucca Apr 14, 2026
faf7025
Merge branch 'main' into chore/export-selection-primitive
francinelucca Apr 16, 2026
82f780a
export VisualContainer, ActionListGroupHeadingProps, ActionListTraili…
francinelucca Apr 16, 2026
bb702e5
export GroupContext
francinelucca Apr 16, 2026
0b87ed6
Refactor FilteredActionList exports and types for improved clarity
francinelucca Apr 16, 2026
8b9b750
fix
francinelucca Apr 17, 2026
b3ccc6e
Merge branch 'main' of github.com:primer/react into chore/export-sele…
francinelucca Apr 22, 2026
5928110
refactor: remove unused imports and update useFocusZone export
francinelucca Apr 22, 2026
5abd238
Merge branch 'main' into chore/export-selection-primitive
francinelucca Apr 22, 2026
09fe81f
Merge branch 'main' into chore/export-selection-primitive
francinelucca Apr 22, 2026
47ba43a
Merge branch 'main' into chore/export-selection-primitive
francinelucca Apr 22, 2026
935b9c8
Merge branch 'main' into chore/export-selection-primitive
francinelucca Apr 22, 2026
e4ff662
feat(FilteredActionList): introduce FilteredActionListInput component…
francinelucca Apr 24, 2026
ecd5679
Merge branch 'chore/export-selection-primitive' of github.com:primer/…
francinelucca Apr 24, 2026
ce9843e
fix
francinelucca Apr 24, 2026
d36541c
change FilteredActionListInput API
francinelucca Apr 24, 2026
1155eff
re-add disable
francinelucca Apr 24, 2026
9ea6a8d
update snapshots
francinelucca Apr 24, 2026
a8e325a
Fix loading condition in FilteredActionList
francinelucca Apr 24, 2026
068e2e0
Merge branch 'main' into chore/export-selection-primitive
francinelucca Apr 27, 2026
4a792c6
Change '@primer/react' version and export new components
francinelucca Apr 27, 2026
de6fea8
fix typo
francinelucca Apr 27, 2026
fc61226
fix test
francinelucca Apr 27, 2026
c358995
chore: update @primer/react to version 38.21.0 and add ActionListSele…
francinelucca Apr 28, 2026
42191f7
Merge branch 'main' into chore/export-selection-primitive
francinelucca Apr 28, 2026
4517543
Merge branch 'main' into chore/export-selection-primitive
francinelucca Apr 28, 2026
9d0a423
Merge branch 'main' into chore/export-selection-primitive
francinelucca Apr 28, 2026
0e5c2a6
Refactor ActionList styles for aria attributes
francinelucca Apr 29, 2026
d2eb122
Clean up imports in ActionList index file
francinelucca Apr 29, 2026
e0db3f6
Update index.ts
francinelucca Apr 29, 2026
fbcdc30
Update exports.test.ts.snap
francinelucca Apr 29, 2026
c582d9f
Update index.ts
francinelucca Apr 29, 2026
bb7762b
Rename ActionListSelectionProps to SelectionProps
francinelucca Apr 29, 2026
5bd47a4
Fix import statement formatting in Selection.tsx
francinelucca Apr 29, 2026
732e2cf
Clean up exports in index.ts
francinelucca Apr 29, 2026
01b0cd9
export GroupContext
francinelucca Apr 29, 2026
78c44c5
export FocusKeys
francinelucca Apr 29, 2026
30fe2c4
update test snapshot
francinelucca Apr 29, 2026
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/metal-pumas-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/react": minor
---

feat: add ActionList, SelectPanel primitives exports and new FilteredActionList.Input components
5 changes: 4 additions & 1 deletion packages/react/src/ActionList/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {List} from './List'
import {Group, GroupHeading} from './Group'
import {Group, GroupContext, GroupHeading} from './Group'
import {Item} from './Item'
import {LinkItem} from './LinkItem'
import {Divider} from './Divider'
Expand Down Expand Up @@ -46,6 +46,9 @@ export const ActionList = Object.assign(List, {
/** Heading for an `ActionList`. */
Heading,

/** Context for `ActionList.Group` to propagate selectionVariant and other group-level props. */
GroupContext,

/** Heading for `ActionList.Group` */
GroupHeading,

Expand Down
41 changes: 14 additions & 27 deletions packages/react/src/FilteredActionList/FilteredActionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type {KeyboardEventHandler, JSX} from 'react'
import type React from 'react'
import {forwardRef, useCallback, useEffect, useMemo, useRef, useState} from 'react'
import type {TextInputProps} from '../TextInput'
import TextInput from '../TextInput'
import {ActionList, type ActionListProps} from '../ActionList'
import type {GroupedListProps, ListPropsBase, ItemInput, RenderItemFn} from './'
import {useFocusZone} from '../hooks/useFocusZone'
Expand All @@ -22,6 +21,7 @@ import {isValidElementType} from 'react-is'
import {useAnnouncements} from './useAnnouncements'
import {clsx} from 'clsx'
import {useVirtualizer} from '@tanstack/react-virtual'
import {FilteredActionListInput} from './FilteredActionListInput'

const menuScrollMargins: ScrollIntoViewOptions = {startMargin: 0, endMargin: 8}

Expand Down Expand Up @@ -543,39 +543,26 @@ export function FilteredActionList({
}
}

const {className: textInputClassName, ...restTextInputProps} = textInputProps || {}

return (
<div
ref={inputAndListContainerRef}
className={clsx(className, classes.Root)}
data-testid="filtered-action-list"
data-component="FilteredActionList"
>
<div className={classes.Header} data-component="FilteredActionList.Header">
<TextInput
// @ts-expect-error it needs a non nullable ref
ref={inputRef}
block
width="auto"
color="fg.default"
value={filterValue}
onChange={onInputChange}
onKeyPress={onInputKeyPress}
onKeyDown={usingRovingTabindex ? onInputKeyDown : () => {}}
placeholder={placeholderText}
role="combobox"
aria-expanded="true"
aria-autocomplete="list"
aria-controls={listId}
aria-label={placeholderText}
aria-describedby={inputDescriptionTextId}
loaderPosition={'leading'}
loading={loading && !loadingType.appearsInBody}
className={clsx(textInputClassName, {[classes.FullScreenTextInput]: fullScreenOnNarrow})}
{...restTextInputProps}
/>
</div>
<FilteredActionListInput
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.

Do we envision splitting up more of FilteredActionList?

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.

We definitely could. I assume that'd come with the SelectPanel separation work if we ever get to it 🙏🏽. Just added what I needed for now

inputRef={inputRef}
value={filterValue}
onInputChange={onInputChange}
onInputKeyPress={onInputKeyPress}
onInputKeyDown={usingRovingTabindex ? onInputKeyDown : undefined}
placeholderText={placeholderText}
listId={listId}
inputDescriptionTextId={inputDescriptionTextId}
loading={loading && !loadingType.appearsInBody}
fullScreenOnNarrow={fullScreenOnNarrow}
{...textInputProps}
/>
Comment thread
francinelucca marked this conversation as resolved.
<VisuallyHidden id={inputDescriptionTextId}>Items will be filtered as you type</VisuallyHidden>
{onSelectAllChange !== undefined && (
<div className={classes.SelectAllContainer} data-component="FilteredActionList.SelectAll">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import type React from 'react'
import {clsx} from 'clsx'
import TextInput from '../TextInput'
import type {TextInputProps} from '../TextInput'
import classes from './FilteredActionList.module.css'

export interface FilteredActionListInputProps extends Partial<Omit<TextInputProps, 'onChange' | 'onKeyDown'>> {
inputRef: React.RefObject<HTMLInputElement | null>
onInputChange?: (e: React.ChangeEvent<HTMLInputElement>) => void
onInputKeyPress?: React.KeyboardEventHandler<HTMLInputElement>
onInputKeyDown?: React.KeyboardEventHandler<HTMLInputElement>
placeholderText?: string
listId: string
inputDescriptionTextId: string
loading: boolean
fullScreenOnNarrow?: boolean
}

export function FilteredActionListInput({
inputRef,
value,
onInputChange,
onInputKeyPress,
onInputKeyDown,
placeholderText,
listId,
inputDescriptionTextId,
loading,
fullScreenOnNarrow,
className,
...restTextInputProps
}: FilteredActionListInputProps): React.JSX.Element {
return (
<div className={classes.Header} data-component="FilteredActionList.Header">
<TextInput
// @ts-expect-error it needs a non nullable ref
ref={inputRef}
block
Comment thread
francinelucca marked this conversation as resolved.
width="auto"
color="fg.default"
value={value}
onChange={onInputChange}
onKeyPress={onInputKeyPress}
onKeyDown={onInputKeyDown}
placeholder={placeholderText}
role="combobox"
aria-expanded="true"
aria-autocomplete="list"
aria-controls={listId}
aria-label={placeholderText}
aria-describedby={inputDescriptionTextId}
loaderPosition={'leading'}
loading={loading}
className={clsx(className, {[classes.FullScreenTextInput]: fullScreenOnNarrow})}
{...restTextInputProps}
/>
Comment thread
francinelucca marked this conversation as resolved.
</div>
)
}
11 changes: 10 additions & 1 deletion packages/react/src/FilteredActionList/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
export {FilteredActionList} from './FilteredActionList'
import {FilteredActionList as FilteredList} from './FilteredActionList'
import {FilteredActionListInput} from './FilteredActionListInput'
import {FilteredActionListBodyLoader} from './FilteredActionListLoaders'

export type {FilteredActionListProps} from './FilteredActionList'
export type {FilteredActionListInputProps} from './FilteredActionListInput'
export {FilteredActionListLoadingTypes} from './FilteredActionListLoaders'

export type {
FilteredActionListItemProps as ItemProps,
Expand All @@ -9,3 +13,8 @@ export type {
ListPropsBase,
RenderItemFn,
} from './types'

export const FilteredActionList = Object.assign(FilteredList, {
BodyLoader: FilteredActionListBodyLoader,
Input: FilteredActionListInput,
})
1 change: 1 addition & 0 deletions packages/react/src/SelectPanel/SelectPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1053,4 +1053,5 @@ export const SelectPanel = Object.assign(Panel, {
__SLOT__: Symbol('SelectPanel'),
SecondaryActionButton: SecondaryButton,
SecondaryActionLink: SecondaryLink,
Message: SelectPanelMessage,
})
1 change: 1 addition & 0 deletions packages/react/src/SelectPanel/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export {SelectPanel} from './SelectPanel'
export {SelectPanelMessage} from './SelectPanelMessage'
export type {SelectPanelProps} from './SelectPanel'

export type {ItemProps, ItemInput, GroupedListProps, ListPropsBase} from '../FilteredActionList'
Comment thread
francinelucca marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ exports[`@primer/react > should not update exports without a semver change 1`] =
"ActionList",
"type ActionListDescriptionProps",
"type ActionListDividerProps",
"type ActionListGroupHeadingProps",
"type ActionListGroupProps",
"type ActionListItemProps",
"type ActionListLeadingVisualProps",
Expand Down Expand Up @@ -68,6 +69,7 @@ exports[`@primer/react > should not update exports without a semver change 1`] =
"type DialogWidth",
"Flash",
"type FlashProps",
"FocusKeys",
"type FocusTrapHookSettings",
"type FocusZoneHookSettings",
"FormControl",
Expand Down Expand Up @@ -308,6 +310,8 @@ exports[`@primer/react/experimental > should not update exports without a semver
"FeatureFlags",
"type FeatureFlagsProps",
"FilteredActionList",
"type FilteredActionListInputProps",
"FilteredActionListLoadingTypes",
Comment thread
francinelucca marked this conversation as resolved.
"type FilteredActionListProps",
"getAccessibleKeybindingHintString",
"Hidden",
Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/experimental/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ export type {SkeletonAvatarProps} from '../SkeletonAvatar'
export {FeatureFlags, DefaultFeatureFlags, useFeatureFlag} from '../FeatureFlags'
export type {FeatureFlagsProps} from '../FeatureFlags'

export {FilteredActionList} from '../FilteredActionList'
export type {FilteredActionListProps} from '../FilteredActionList'
export {FilteredActionList, FilteredActionListLoadingTypes} from '../FilteredActionList'
export type {FilteredActionListProps, FilteredActionListInputProps} from '../FilteredActionList'
export {IssueLabel} from './IssueLabel'
export type {IssueLabelProps} from './IssueLabel'

Expand Down
3 changes: 2 additions & 1 deletion packages/react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export {useOverlay} from './hooks/useOverlay'
export {useConfirm} from './ConfirmationDialog/ConfirmationDialog'
export {useFocusTrap} from './hooks/useFocusTrap'
export type {FocusTrapHookSettings} from './hooks/useFocusTrap'
export {useFocusZone} from './hooks/useFocusZone'
export {FocusKeys, useFocusZone} from './hooks/useFocusZone'
export type {FocusZoneHookSettings} from './hooks/useFocusZone'
export {useRefObjectAsForwardedRef} from './hooks/useRefObjectAsForwardedRef'
export {useMergedRefs} from './hooks/useMergedRefs'
Expand All @@ -59,6 +59,7 @@ export {ActionList} from './ActionList'
export type {
ActionListProps,
ActionListGroupProps,
ActionListGroupHeadingProps,
ActionListItemProps,
ActionListLinkItemProps,
ActionListDividerProps,
Expand Down
Loading