Repository navigation
FilteredActionList: only reference the list from the input while it is rendered - #8634
HadrielWonda wants to merge 2 commits into
Conversation
🦋 Changeset detectedLatest commit: 60a7e03 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Muguett-DBY
left a comment
There was a problem hiding this comment.
I found a callback-ref regression when the default primer_react_merged_forwarded_refs flag is off:
<FilteredActionList
items={[]}
onFilterChange={() => {}}
scrollContainerRef={() => {}}
loading
/>scrollContainerRef accepts a callback, but in this path useProvidedRefOrCreate returns that function and its .current is undefined. The new !== null check treats that as present, so reading .clientHeight throws. Current main doesn't throw here: its previous truthiness guard skips the body loader (although that also means the loader isn't shown for this ref).
Could the new guard treat both null and undefined as absent, or use the merged internal ref for this path? I compared the exact PR component and current main with React 18 server rendering and stubbed unrelated imports; I haven't run the full browser or project suite. I used OpenAI Codex for the analysis and focused reproduction.
With primer_react_merged_forwarded_refs off, a callback scrollContainerRef leaves current undefined, so the null check let the body loader read clientHeight from undefined. Read the height with optional chaining and only show the loader when it was read, matching main.
|
@Muguett-DBY thanks, good catch. I reproduced it: with the flag off, Why the types didn't catch it: with the flag off, Fix (60a7e03): I went with your first suggestion. The loader height is now read with optional chaining, and the body loader only shows when a height was actually read: const bodyLoaderHeight =
loading && loadingType.appearsInBody ? readScrollContainerRef.current?.clientHeight : undefined
const showBodyLoader = bodyLoaderHeight !== undefinedThis keeps Regression test: Checks: with the component change, the |
Closes #8633
The filter input in
FilteredActionListalways setaria-expanded="true"andaria-controls={listId}, even while the body shows a loader or a message and the list is not rendered. The combobox then referenced a missing element (axearia-valid-attr-value).FilteredActionListnow passeslistIdto the input only while the list is rendered. The input setsaria-expandedfrom that, so while the body shows a loader or a message the input hasaria-expanded="false"and noaria-controls. When items are shown, nothing changes.Changelog
New
Changed
FilteredActionList: the filter input only references the list while it is renderedFilteredActionListInput:listIdis optional, andaria-expandedreflects whether it is setRemoved
None
Rollout strategy
Patch changeset included.
Testing & Reviewing
main(message and body-loader cases) and pass with this change.FilteredActionList,SelectPanel,experimental/SelectPanel2,ActionListandFormControltests: 388 passed.tsc --noEmit, ESLint and Prettier are clean.loading-with-body-spinnerorwith-no-results-messagestory: the input now hasaria-expanded="false"and noaria-controls, and axe no longer reportsaria-valid-attr-value.