feat: RAC NavigationTree - #10404
Conversation
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
|
||
| 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! 🎉 |
There was a problem hiding this comment.
since i have scrollbar's on, when you expand a section, the scrollbar appears shifting the chevron to the left. we have the same issue on our current docs but it feels less noticeable bc the chevron is always stable (since it's positioned on the left). should we consider adding a scrollbar-gutter to sidenav?
There was a problem hiding this comment.
Good question, I'm going to see if design has an opinion. Tree sidesteps this issue because the expand button is on the left instead of where the scroll bar would appear
|
Build successful! 🎉 |
|
Build successful! 🎉 |
bed8ca5 to
44e1689
Compare
44e1689 to
39e6f9a
Compare
|
Build successful! 🎉 |
|
Build successful! 🎉 |
|
Build successful! 🎉 |
## API Changes
react-aria-components/react-aria-components:NavigationTree+NavigationTree <T> {
+ aria-describedby?: string
+ aria-details?: string
+ aria-label?: string
+ aria-labelledby?: string
+ autoFocus?: boolean | FocusStrategy
+ children?: ReactNode | (T) => ReactNode
+ className?: ClassNameOrFunction<NavigationTreeRenderProps> = 'react-aria-NavigationTree'
+ 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, NavigationTreeRenderProps>
+ selectedRoute?: string | null
+ slot?: string | null
+ style?: StyleOrFunction<NavigationTreeRenderProps>
+}/react-aria-components:NavigationTreeItem+NavigationTreeItem <T extends {}> {
+ aria-label?: string
+ children: ReactNode
+ className?: ClassNameOrFunction<NavigationTreeItemRenderProps> = 'react-aria-NavigationTreeItem'
+ 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, NavigationTreeItemRenderProps>
+ routerOptions?: RouterOptions
+ style?: StyleOrFunction<NavigationTreeItemRenderProps>
+ target?: HTMLAttributeAnchorTarget
+ textValue: string
+}/react-aria-components:NavigationTreeItemContent+NavigationTreeItemContent {
+ children: ChildrenOrFunction<NavigationTreeItemContentRenderProps>
+}/react-aria-components:NavigationTreeSection+NavigationTreeSection <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:NavigationTreeHeader+NavigationTreeHeader {
+ children?: ReactNode
+ className?: string
+ id?: string
+ render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
+ style?: CSSProperties
+}/react-aria-components:NavigationTreeContext+NavigationTreeContext {
+ UNTYPED
+}/react-aria-components:NavigationTreeProps+NavigationTreeProps <T> {
+ aria-describedby?: string
+ aria-details?: string
+ aria-label?: string
+ aria-labelledby?: string
+ autoFocus?: boolean | FocusStrategy
+ children?: ReactNode | (T) => ReactNode
+ className?: ClassNameOrFunction<NavigationTreeRenderProps> = 'react-aria-NavigationTree'
+ 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, NavigationTreeRenderProps>
+ selectedRoute?: string | null
+ slot?: string | null
+ style?: StyleOrFunction<NavigationTreeRenderProps>
+}/react-aria-components:NavigationTreeRenderProps+NavigationTreeRenderProps {
+ isEmpty: boolean
+ isFocusVisible: boolean
+ isFocused: boolean
+ state: TreeState<unknown>
+}/react-aria-components:NavigationTreeItemProps+NavigationTreeItemProps <T = {}> {
+ aria-label?: string
+ children: ReactNode
+ className?: ClassNameOrFunction<NavigationTreeItemRenderProps> = 'react-aria-NavigationTreeItem'
+ 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, NavigationTreeItemRenderProps>
+ routerOptions?: RouterOptions
+ style?: StyleOrFunction<NavigationTreeItemRenderProps>
+ target?: HTMLAttributeAnchorTarget
+ textValue: string
+}/react-aria-components:NavigationTreeItemRenderProps+NavigationTreeItemRenderProps {
+ 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:NavigationTreeItemContentProps+NavigationTreeItemContentProps {
+ children: ChildrenOrFunction<NavigationTreeItemContentRenderProps>
+}/react-aria-components:NavigationTreeItemContentRenderProps+NavigationTreeItemContentRenderProps {
+ 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:NavigationTreeSectionProps+NavigationTreeSectionProps <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:NavigationTreeHeaderProps+NavigationTreeHeaderProps {
+ children?: ReactNode
+ className?: string
+ id?: string
+ render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
+ style?: CSSProperties
+} |
Agent Skills ChangesAdded (2)
Modified (8)
InstallReact Spectrum S2: React Aria: |
| } | ||
| ``` | ||
|
|
||
| ## Sections |
There was a problem hiding this comment.
Nest the above sections under Content to match other pages
| <ExampleSwitcher> | ||
| ```tsx render docs={docs.exports.NavigationTree} links={docs.links} props={[]} type="vanilla" files={["starters/docs/src/NavigationTree.tsx", "starters/docs/src/NavigationTree.css", "./RoutedNavigationTree.tsx"]} | ||
| "use client"; | ||
| import {NavigationTree, NavigationTreeItem} from 'vanilla-starter/NavigationTree'; |
There was a problem hiding this comment.
IMO the style is a bit heavy for a sidenav. Maybe we can make it a bit closer to what we have in S2 with the selection line
|
|
||
| ## API | ||
|
|
||
| ```tsx links={{NavigationTree: '#NavigationTree', NavigationTreeItem: '#NavigationTreeitem', NavigationTreeItemContent: '#NavigationTreeitemcontent', NavigationTreeSection: '#NavigationTreesection', NavigationTreeHeader: '#NavigationTreeheader', Link: 'Link'}} |
There was a problem hiding this comment.
Would be nice to have an anatomy diagram...
| } | ||
| ``` | ||
|
|
||
| ## Current route |
There was a problem hiding this comment.
noticed that you can't see the focus ring on the selected item with the current styles
devongovett
left a comment
There was a problem hiding this comment.
Nothing blocking if we want to merge for testing.
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: