feat: S2 SideNav#10306
Conversation
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
| // RAC swallows arrow keys at the collection level (stopPropagation during capture), so a handler | ||
| // on the link never sees them. Intercept here on an ancestor, before RAC's row handler runs, and | ||
| // expand a collapsed row when the expand arrow is pressed while focus is on its link. | ||
| let onKeyDownCapture = (e: ReactKeyboardEvent) => { |
There was a problem hiding this comment.
I haven't pulled this down to try it myself, but perhaps you could make SideNav a keyboardNavigationBehavior = tab tree and have focusMode="child" and allowsArrowNavigation=true so that arrow up/down navigation still work but focus lands on the link by default. useGridList's handleTreeExpansionKeys will have to be updated to also check allowsArrowNavigation so that it can skip the
activeElement check below, but that might allow you to get rid of all this extra handling at this level
if (!('expandedKeys' in state) || activeElement !== rowRef) {
return false;
}
note that the extra props mentioned above are in #10159, so will require you to rebase/pull in that PR
There was a problem hiding this comment.
Good news, textfield_gridlists is already my base :)
I attempted an implementation of the above and it appears to mostly work, so that's pretty awesome. I was missing that allowsArrowNavigation update when I tried those all together previously. Good thinking.
Just for posterity, there's a couple cases here:
Left/Right arrow to expand/collapse/traverse up that should still be accessible from the link.
In addition, focusMode="child" should only be the case for items with links (not categories) because then it might accidentally focus something like an ActionMenu that may be in the row regardless of if there is a Link.
Shift+Tab from a link should leave the SideNav.
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
## API Changes
react-aria-components/react-aria-components:GridListHeaderProps+GridListHeaderProps {
+ children?: ReactNode
+ className?: string
+ id?: string
+ render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
+ style?: CSSProperties
+}@react-spectrum/s2/@react-spectrum/s2:SideNav+SideNav <T> {
+ UNSAFE_className?: UnsafeClassName
+ UNSAFE_style?: CSSProperties
+ aria-describedby?: string
+ aria-details?: string
+ aria-label?: string
+ aria-labelledby?: string
+ autoFocus?: boolean | FocusStrategy
+ children?: ReactNode | (T) => ReactNode
+ defaultExpandedKeys?: Iterable<Key>
+ dependencies?: ReadonlyArray<any>
+ disabledKeys?: Iterable<Key>
+ expandedKeys?: Iterable<Key>
+ id?: string
+ items?: Iterable<T>
+ onAction?: (Key) => void
+ onExpandedChange?: (Set<Key>) => any
+ selectedRoute: string
+ slot?: string | null
+ styles?: StylesPropWithHeight
+}/@react-spectrum/s2:SideNavItem+SideNavItem {
+ aria-label?: string
+ children: ReactNode
+ download?: boolean | string
+ hasChildItems?: boolean
+ href?: Href
+ hrefLang?: string
+ id?: Key
+ isDisabled?: boolean
+ onHoverChange?: (boolean) => void
+ onHoverEnd?: (HoverEvent) => void
+ onHoverStart?: (HoverEvent) => void
+ onPress?: (PressEvent) => void
+ onPressChange?: (boolean) => void
+ onPressEnd?: (PressEvent) => void
+ onPressStart?: (PressEvent) => void
+ onPressUp?: (PressEvent) => void
+ ping?: string
+ referrerPolicy?: HTMLAttributeReferrerPolicy
+ rel?: string
+ routerOptions?: RouterOptions
+ target?: HTMLAttributeAnchorTarget
+ textValue: string
+}/@react-spectrum/s2:SideNavItemContent+SideNavItemContent {
+ children: ReactNode
+}/@react-spectrum/s2:SideNavItemLink+SideNavItemLink {
+ children?: ReactNode
+}/@react-spectrum/s2:SideNavSection+SideNavSection <T extends {}> {
+ aria-label?: string
+ children?: ReactNode | (T) => ReactElement
+ dependencies?: ReadonlyArray<any>
+ id?: Key
+ items?: Iterable<T>
+}/@react-spectrum/s2:SideNavHeader+SideNavHeader {
+ children?: ReactNode
+ id?: string
+}/@react-spectrum/s2:SideNavProps+SideNavProps <T> {
+ UNSAFE_className?: UnsafeClassName
+ UNSAFE_style?: CSSProperties
+ aria-describedby?: string
+ aria-details?: string
+ aria-label?: string
+ aria-labelledby?: string
+ autoFocus?: boolean | FocusStrategy
+ children?: ReactNode | (T) => ReactNode
+ defaultExpandedKeys?: Iterable<Key>
+ dependencies?: ReadonlyArray<any>
+ disabledKeys?: Iterable<Key>
+ expandedKeys?: Iterable<Key>
+ id?: string
+ items?: Iterable<T>
+ onAction?: (Key) => void
+ onExpandedChange?: (Set<Key>) => any
+ selectedRoute: string
+ slot?: string | null
+ styles?: StylesPropWithHeight
+}/@react-spectrum/s2:SideNavItemProps+SideNavItemProps {
+ aria-label?: string
+ children: ReactNode
+ download?: boolean | string
+ hasChildItems?: boolean
+ href?: Href
+ hrefLang?: string
+ id?: Key
+ isDisabled?: boolean
+ onHoverChange?: (boolean) => void
+ onHoverEnd?: (HoverEvent) => void
+ onHoverStart?: (HoverEvent) => void
+ onPress?: (PressEvent) => void
+ onPressChange?: (boolean) => void
+ onPressEnd?: (PressEvent) => void
+ onPressStart?: (PressEvent) => void
+ onPressUp?: (PressEvent) => void
+ ping?: string
+ referrerPolicy?: HTMLAttributeReferrerPolicy
+ rel?: string
+ routerOptions?: RouterOptions
+ target?: HTMLAttributeAnchorTarget
+ textValue: string
+}/@react-spectrum/s2:SideNavItemContentProps+SideNavItemContentProps {
+ children: ReactNode
+}/@react-spectrum/s2:SideNavItemLinkProps+SideNavItemLinkProps {
+ children?: ReactNode
+}/@react-spectrum/s2:SideNavSectionProps+SideNavSectionProps <T> {
+ aria-label?: string
+ children?: ReactNode | (T) => ReactElement
+ dependencies?: ReadonlyArray<any>
+ id?: Key
+ items?: Iterable<T>
+}/@react-spectrum/s2:SideNavHeaderProps+SideNavHeaderProps {
+ children?: ReactNode
+ id?: string
+} |
Agent Skills ChangesAdded (1)
Modified (7)
InstallReact Spectrum S2: React Aria: |
Closes
Early draft of SideNav for S2.
api is this right now:
decisions to make still
✅ Pull Request Checklist:
📝 Test Instructions:
🧢 Your Project: