feat: RAC SideNav - #10404
Conversation
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
| if (key != null) { | ||
| key = closestVisibleKey(collection, expandedKeys, key); | ||
| syncedRouteRef.current = selectedRoute; | ||
| selectionManager.setFocusedKey(key); |
There was a problem hiding this comment.
Hm, I'm kind of wondering whether we may want to force a scrollIntoView here, even without the collection having focus. I think in principle, it would be nice if a SideNav could be re-used for the navigation markers of a "Table of Contents" component, in which the active marker would follow along while scrolling.
In that regard, I was also questioning whether "SideNav" might be too restraining for a use-case which may later expand. Maybe something like "NavigationTargetGroup", "NavTargetList" or something of those sorts would leave some more room to play with later.
There was a problem hiding this comment.
Yeah, naming definitely up for discussion :)
Interesting idea with the scrolling, right now I'm handling it outside and it's a little hack-y.
Thanks for the feedback!
|
|
||
| let defaultRef = useRef<HTMLDivElement>(null); | ||
| let mergedRef = mergeRefs(ref, defaultRef); | ||
| useEffect(() => { |
There was a problem hiding this comment.
Should we always try to scroll the current item into view whenever it changes? Should we have a prop to disable this behaviour entirely? should there be an option to only do it on mount and no other time?
There was a problem hiding this comment.
Fyi, I believe scroll-on-mount should be handled more holistically with an integration of the upcoming scroll-initial-target CSS attribute. Ideally that would be a mechanic for all collections, and also integrate with virtualizer to push the item into persisted keys.
Related to this, Im also not quite sure whether the current key here is being persisted? How does Tree learn of the Items quasi selection state? Is it just through “current” always being kept in-sync with the focusedKey?
|
Build successful! 🎉 |
|
Build successful! 🎉 |
## API Changes
react-aria-components/react-aria-components:SideNav+SideNav <T> {
+ aria-describedby?: string
+ aria-details?: string
+ aria-label?: string
+ aria-labelledby?: string
+ autoFocus?: boolean | FocusStrategy
+ children?: ReactNode | (T) => ReactNode
+ className?: ClassNameOrFunction<SideNavRenderProps> = 'react-aria-SideNav'
+ defaultExpandedKeys?: Iterable<Key>
+ dependencies?: ReadonlyArray<any>
+ disabledKeys?: Iterable<Key>
+ expandedKeys?: Iterable<Key>
+ id?: string
+ items?: Iterable<T>
+ onExpandedChange?: (Set<Key>) => any
+ render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, SideNavRenderProps>
+ selectedRoute?: string | null
+ slot?: string | null
+ style?: StyleOrFunction<SideNavRenderProps>
+}/react-aria-components:SideNavItem+SideNavItem <T extends {}> {
+ aria-label?: string
+ children: ReactNode
+ className?: ClassNameOrFunction<SideNavItemRenderProps> = 'react-aria-SideNavItem'
+ download?: boolean | string
+ hasChildItems?: boolean
+ href?: Href
+ hrefLang?: string
+ id?: Key
+ isDisabled?: boolean
+ onClick?: (MouseEvent<FocusableElement>) => void
+ 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
+ render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, SideNavItemRenderProps>
+ routerOptions?: RouterOptions
+ style?: StyleOrFunction<SideNavItemRenderProps>
+ target?: HTMLAttributeAnchorTarget
+ textValue: string
+}/react-aria-components:SideNavItemContent+SideNavItemContent {
+ children: ChildrenOrFunction<SideNavItemContentRenderProps>
+}/react-aria-components:SideNavSection+SideNavSection <T extends {}> {
+ aria-label?: string
+ children?: ReactNode | (T) => ReactElement
+ className?: string
+ dependencies?: ReadonlyArray<any>
+ id?: Key
+ items?: Iterable<T>
+ render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
+ style?: CSSProperties
+}/react-aria-components:SideNavHeader+SideNavHeader {
+ children?: ReactNode
+ className?: string
+ id?: string
+ render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
+ style?: CSSProperties
+}/react-aria-components:SideNavContext+SideNavContext {
+ UNTYPED
+}/react-aria-components:SideNavProps+SideNavProps <T> {
+ aria-describedby?: string
+ aria-details?: string
+ aria-label?: string
+ aria-labelledby?: string
+ autoFocus?: boolean | FocusStrategy
+ children?: ReactNode | (T) => ReactNode
+ className?: ClassNameOrFunction<SideNavRenderProps> = 'react-aria-SideNav'
+ defaultExpandedKeys?: Iterable<Key>
+ dependencies?: ReadonlyArray<any>
+ disabledKeys?: Iterable<Key>
+ expandedKeys?: Iterable<Key>
+ id?: string
+ items?: Iterable<T>
+ onExpandedChange?: (Set<Key>) => any
+ render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, SideNavRenderProps>
+ selectedRoute?: string | null
+ slot?: string | null
+ style?: StyleOrFunction<SideNavRenderProps>
+}/react-aria-components:SideNavRenderProps+SideNavRenderProps {
+ isEmpty: boolean
+ isFocusVisible: boolean
+ isFocused: boolean
+ state: TreeState<unknown>
+}/react-aria-components:SideNavItemProps+SideNavItemProps <T = {}> {
+ aria-label?: string
+ children: ReactNode
+ className?: ClassNameOrFunction<SideNavItemRenderProps> = 'react-aria-SideNavItem'
+ download?: boolean | string
+ hasChildItems?: boolean
+ href?: Href
+ hrefLang?: string
+ id?: Key
+ isDisabled?: boolean
+ onClick?: (MouseEvent<FocusableElement>) => void
+ 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
+ render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, SideNavItemRenderProps>
+ routerOptions?: RouterOptions
+ style?: StyleOrFunction<SideNavItemRenderProps>
+ target?: HTMLAttributeAnchorTarget
+ textValue: string
+}/react-aria-components:SideNavItemRenderProps+SideNavItemRenderProps {
+ allowsDragging?: boolean
+ hasChildItems: boolean
+ id: Key
+ isCurrent: boolean
+ isCurrentAncestor: boolean
+ isDisabled: boolean
+ isDragging?: boolean
+ isDropTarget?: boolean
+ isExpanded: boolean
+ isFocusVisible: boolean
+ isFocusVisibleWithin: boolean
+ isFocused: boolean
+ isHovered: boolean
+ isPressed: boolean
+ isSelected: boolean
+ level: number
+ selectionBehavior: SelectionBehavior
+ selectionMode: SelectionMode
+ state: TreeState<unknown>
+}/react-aria-components:SideNavItemContentProps+SideNavItemContentProps {
+ children: ChildrenOrFunction<SideNavItemContentRenderProps>
+}/react-aria-components:SideNavItemContentRenderProps+SideNavItemContentRenderProps {
+ allowsDragging?: boolean
+ hasChildItems: boolean
+ id: Key
+ isCurrent: boolean
+ isCurrentAncestor: boolean
+ isDisabled: boolean
+ isDragging?: boolean
+ isDropTarget?: boolean
+ isExpanded: boolean
+ isFocusVisible: boolean
+ isFocusVisibleWithin: boolean
+ isFocused: boolean
+ isHovered: boolean
+ isPressed: boolean
+ isSelected: boolean
+ level: number
+ selectionBehavior: SelectionBehavior
+ selectionMode: SelectionMode
+ state: TreeState<unknown>
+}/react-aria-components:SideNavSectionProps+SideNavSectionProps <T> {
+ aria-label?: string
+ children?: ReactNode | (T) => ReactElement
+ className?: string
+ dependencies?: ReadonlyArray<any>
+ id?: Key
+ items?: Iterable<T>
+ render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
+ style?: CSSProperties
+}/react-aria-components:SideNavHeaderProps+SideNavHeaderProps {
+ children?: ReactNode
+ className?: string
+ id?: string
+ render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
+ style?: CSSProperties
+} |
Agent Skills ChangesAdded (2)
Modified (9)
InstallReact Spectrum S2: React Aria: |
Closes
Adds the RAC implementation of SideNav. Rewrites S2 to use that. Adds starter examples and docs page for new RAC.
Switches Docs SideNav over to our S2 SideNav.
✅ Pull Request Checklist:
📝 Test Instructions:
🧢 Your Project: