-
Notifications
You must be signed in to change notification settings - Fork 599
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove activedescendant focus pattern from SelectPanel #5688
base: main
Are you sure you want to change the base?
Conversation
🦋 Changeset detectedLatest commit: df77160 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 |
👋 Hi, this pull request contains changes to the source code that github/github depends on. If you are GitHub staff, we recommend testing these changes with github/github using the integration workflow. Thanks! |
@@ -243,7 +205,6 @@ function MappedActionListItem(item: ItemInput & {renderItem?: RenderItemFn}) { | |||
|
|||
return ( | |||
<ActionList.Item | |||
role="option" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The role is automatically inferred by ActionList
.
className={enabled ? clsx(className, classes.FilteredActionList) : className} | ||
announcementsEnabled={false} | ||
/> | ||
<ActionListContainerContext.Provider value={{container: 'SelectPanel', focusZoneFocusOutBehavior: 'wrap'}}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only for the modern ActionList
and shouldn't affect the deprecated one.
@@ -253,7 +253,6 @@ const StyledItem = styled.div< | |||
|
|||
&:focus { | |||
background: ${({variant, item}) => getItemVariant(variant, item?.disabled).focusBg}; | |||
outline: none; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Allows items to appear visually focused.
size-limit report 📦
|
👋 Hi from github/github! Your integration PR is ready: https://github.com/github/github/pull/362191 |
🟢 golden-jobs completed with status |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking great! just a question on the new FilterActionList custom attribute
packages/react/src/FilteredActionList/FilteredActionListWithModernActionList.tsx
Outdated
Show resolved
Hide resolved
packages/react/src/FilteredActionList/FilteredActionListWithModernActionList.tsx
Outdated
Show resolved
Hide resolved
packages/react/src/FilteredActionList/FilteredActionListWithModernActionList.tsx
Show resolved
Hide resolved
…mer/react into select_panel_remove_activedescendant
👋 Hi, there are new commits since the last successful integration test. We recommend running the integration workflow once more, unless you are sure the new changes do not affect github/github. Thanks! |
👋 Hi, there are new commits since the last successful integration test. We recommend running the integration workflow once more, unless you are sure the new changes do not affect github/github. Thanks! |
👋 Hi, there are new commits since the last successful integration test. We recommend running the integration workflow once more, unless you are sure the new changes do not affect github/github. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Took a look and everything's looking good! Will follow up in my next review to test with a screen reader!
items={items.map(item => { | ||
return { | ||
...item, | ||
'data-select-panel-item': container === 'SelectPanel', | ||
role: 'option', | ||
} | ||
})} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we utilize useMemo
here? I noticed that this was being called a few times on the initial render. I think if we utilize useMemo
we could reduce it to one since we'll memorize the array.
const filteredItems: ItemInput[] = React.useMemo(() => {
return items.map(item => {
return {
...item,
'data-select-panel-item': container === 'SelectPanel',
role: 'option',
}
})
}, [items, container])
Not a big concern though, so up to you! I believe this will still be called upon filtering existing options, so this only helps us when it comes to the initial render.
@@ -0,0 +1,5 @@ | |||
--- | |||
"@primer/react": patch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I'm wondering if this should be minor
instead of patch
. Entirely up to you though! 😁
function MappedActionListItem(item: ItemInput & {renderItem?: RenderItemFn}) { | ||
const {container} = useContext(ActionListContainerContext) | ||
|
||
// keep backward compatibility for renderItem | ||
// escape hatch for custom Item rendering | ||
if (typeof item.renderItem === 'function') return item.renderItem(item) | ||
if (typeof item.renderItem === 'function') { | ||
if (container === 'SelectPanel') { | ||
return React.cloneElement(item.renderItem(item), { | ||
'data-select-panel-item': true, | ||
}) | ||
} | ||
|
||
return item.renderItem(item) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have an example that utilizes this? Not a blocker, but just curious 🤔
const getItemWithActiveDescendant = ( | ||
listRef: React.RefObject<HTMLElement>, | ||
items: FilteredActionListProps['items'], | ||
) => { | ||
const listElement = listRef.current | ||
const activeItemElement = listElement?.querySelector('[data-is-active-descendant]') | ||
|
||
if (!listElement || !activeItemElement?.textContent) return | ||
|
||
const optionElements = listElement.querySelectorAll('[role="option"]') | ||
|
||
const index = Array.from(optionElements).indexOf(activeItemElement) | ||
const activeItem = items[index] as ItemInput | undefined | ||
|
||
const text = activeItem?.text | ||
const selected = activeItem?.selected | ||
|
||
return {index, text, selected} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, active descendant used a lot of code! It's great that we're able to clean it all up 🥹
useEffect(() => { | ||
if (open && inputRef) { | ||
inputRef.current?.focus() | ||
} | ||
}, [inputRef, open]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could potentially add the .focus()
inside of onInputRefChanged
, as this appears to be where we get the input ref initially, and avoids using useEffect
.
Though I'm not 100% on when onInputRefChanged
is called. It seems like only when the ref is set, so should be initial render? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like we already focus it even without the .focus()
we provide here. I'm wondering if this is because the container (AnchoredOverlay
) automatically focuses the first focusable element?
I think this is set via the following on (currently) line 357:
const focusTrapSettings = {
initialFocusRef: inputRef || undefined,
}
We might be able to omit the useEffect
entirely, (and my previous comment 😅)
Closes https://github.com/github/primer/issues/4740
Changelog
New
Changed
SelectPanel
in favor of regular 'ol focus behavior with a roving tab index.Removed
Rollout strategy
Testing & Reviewing
Merge checklist
- [ ] Added/updated documentation- [ ] Added/updated previews (Storybook)