Skip to content

feat: S2 SideNav#10306

Open
snowystinger wants to merge 25 commits into
textfield_gridlistsfrom
s2-sidenav-rob
Open

feat: S2 SideNav#10306
snowystinger wants to merge 25 commits into
textfield_gridlistsfrom
s2-sidenav-rob

Conversation

@snowystinger

@snowystinger snowystinger commented Jul 7, 2026

Copy link
Copy Markdown
Member

Closes

Early draft of SideNav for S2.

api is this right now:

<SideNav selectedRoute="/home"> // no onSelectionChange, control through router
  <SideNavItem href="/home">
    <SideNavContent>
      <SideNavLink>

decisions to make still

  • what are "categories"?
    • They are just items that don't have a link in them, don't participate in selection and don't have the selection hover state. This will be problematic with our API as we don't know ahead of time if there will be a link or not.
    • They can be mixed in the same SideNav, if it has children, it can either be a category or an item with a link.
  • how to stop focus from ever going to the "row/cell"
    • Solved by forwarding events and re-firing them on the row from the link. This way you don't need to navigate to the row.
  • what happens to selection indicator if it's on an item inside a collapsed item/category?
    • Figma shows that the item gets bolded and a different text color
  • does the selection indicator animate like Tabs do? what happens if it needs to move between levels?
    • Design says no due to how far the indicator may need to move and how it indents

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

🧢 Your Project:

@snowystinger snowystinger marked this pull request as draft July 7, 2026 05:14
@rspbot

rspbot commented Jul 7, 2026

Copy link
Copy Markdown

@snowystinger snowystinger changed the title S2 sidenav rob feat: S2 SideNav Jul 7, 2026
@rspbot

rspbot commented Jul 9, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 10, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 10, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 13, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 13, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 13, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 13, 2026

Copy link
Copy Markdown

Comment on lines +203 to +206
// 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) => {

@LFDanLu LFDanLu Jul 13, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@snowystinger snowystinger Jul 14, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread packages/@react-spectrum/s2/src/SideNav.tsx
@snowystinger snowystinger marked this pull request as ready for review July 14, 2026 07:26
@rspbot

rspbot commented Jul 14, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 15, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 15, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 15, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 15, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 15, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 15, 2026

Copy link
Copy Markdown

Comment thread packages/@react-spectrum/s2/src/SideNav.tsx Outdated
Comment thread packages/@react-spectrum/s2/src/SideNav.tsx Outdated
Comment thread packages/@react-spectrum/s2/src/SideNav.tsx Outdated
@rspbot

rspbot commented Jul 15, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 15, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Jul 15, 2026

Copy link
Copy Markdown
## API Changes

react-aria-components

/react-aria-components:GridListItem

 GridListItem <T> {
+  allowsArrowNavigation?: boolean
   children?: ChildrenOrFunction<GridListItemRenderProps>
   className?: ClassNameOrFunction<GridListItemRenderProps> = 'react-aria-GridListItem'
   download?: boolean | string
+  focusMode?: 'child' | 'row'
   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, GridListItemRenderProps>
   routerOptions?: RouterOptions
   style?: StyleOrFunction<GridListItemRenderProps>
   target?: HTMLAttributeAnchorTarget
   textValue?: string
   value?: T
 }

/react-aria-components:Table

 Table {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode
   className?: ClassNameOrFunction<TableRenderProps> = 'react-aria-Table'
   defaultExpandedKeys?: Iterable<Key>
   defaultSelectedKeys?: 'all' | Iterable<Key>
   disabledBehavior?: DisabledBehavior = 'all'
   disabledKeys?: Iterable<Key>
   disallowEmptySelection?: boolean
   dragAndDropHooks?: DragAndDropHooks
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   expandedKeys?: Iterable<Key>
+  keyboardNavigationBehavior?: 'arrow' | 'tab' = 'arrow'
   onExpandedChange?: (Set<Key>) => any
   onRowAction?: (Key) => void
   onSelectionChange?: (Selection) => void
   onSortChange?: (SortDescriptor) => any
   selectedKeys?: 'all' | Iterable<Key>
   selectionBehavior?: SelectionBehavior = 'toggle'
   selectionMode?: SelectionMode
   shouldSelectOnPressUp?: boolean
   slot?: string | null
   sortDescriptor?: SortDescriptor
   style?: StyleOrFunction<TableRenderProps>
   treeColumn?: Key
 }

/react-aria-components:Cell

 Cell {
+  allowsArrowNavigation?: boolean
   children?: ChildrenOrFunction<CellRenderProps>
   className?: ClassNameOrFunction<CellRenderProps> = 'react-aria-Cell'
   colSpan?: number
+  focusMode?: 'child' | 'cell'
   id?: Key
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, CellRenderProps>
   style?: StyleOrFunction<CellRenderProps>
   textValue?: string

/react-aria-components:Column

 Column {
+  allowsArrowNavigation?: boolean
   allowsSorting?: boolean
   children?: ChildrenOrFunction<ColumnRenderProps>
   className?: ClassNameOrFunction<ColumnRenderProps> = 'react-aria-Column'
   defaultWidth?: ColumnSize | null
+  focusMode?: 'child' | 'cell'
   id?: Key
   isRowHeader?: boolean
   maxWidth?: ColumnStaticSize | null
   minWidth?: ColumnStaticSize | null
   style?: StyleOrFunction<ColumnRenderProps>
   textValue?: string
   width?: ColumnSize | null
 }

/react-aria-components:TreeItem

 TreeItem <T extends any> {
+  allowsArrowNavigation?: boolean
   aria-label?: string
   children: ReactNode
   className?: ClassNameOrFunction<TreeItemRenderProps> = 'react-aria-TreeItem'
   download?: boolean | string
+  focusMode?: 'child' | 'row' = 'row'
   hasChildItems?: boolean
   href?: Href
   hrefLang?: string
   id?: Key
   onAction?: () => void
   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, TreeItemRenderProps>
   routerOptions?: RouterOptions
   style?: StyleOrFunction<TreeItemRenderProps>
   target?: HTMLAttributeAnchorTarget
   textValue: string
   value?: any
 }

/react-aria-components:GridListItemProps

 GridListItemProps <T = {}> {
+  allowsArrowNavigation?: boolean
   children?: ChildrenOrFunction<GridListItemRenderProps>
   className?: ClassNameOrFunction<GridListItemRenderProps> = 'react-aria-GridListItem'
   download?: boolean | string
+  focusMode?: 'child' | 'row'
   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, GridListItemRenderProps>
   routerOptions?: RouterOptions
   style?: StyleOrFunction<GridListItemRenderProps>
   target?: HTMLAttributeAnchorTarget
   textValue?: string
   value?: T
 }

/react-aria-components:TableProps

 TableProps {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode
   className?: ClassNameOrFunction<TableRenderProps> = 'react-aria-Table'
   defaultExpandedKeys?: Iterable<Key>
   defaultSelectedKeys?: 'all' | Iterable<Key>
   disabledBehavior?: DisabledBehavior = 'all'
   disabledKeys?: Iterable<Key>
   disallowEmptySelection?: boolean
   dragAndDropHooks?: DragAndDropHooks
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   expandedKeys?: Iterable<Key>
+  keyboardNavigationBehavior?: 'arrow' | 'tab' = 'arrow'
   onExpandedChange?: (Set<Key>) => any
   onRowAction?: (Key) => void
   onSelectionChange?: (Selection) => void
   onSortChange?: (SortDescriptor) => any
   selectedKeys?: 'all' | Iterable<Key>
   selectionBehavior?: SelectionBehavior = 'toggle'
   selectionMode?: SelectionMode
   shouldSelectOnPressUp?: boolean
   slot?: string | null
   sortDescriptor?: SortDescriptor
   style?: StyleOrFunction<TableRenderProps>
   treeColumn?: Key
 }

/react-aria-components:ColumnProps

 ColumnProps {
+  allowsArrowNavigation?: boolean
   allowsSorting?: boolean
   children?: ChildrenOrFunction<ColumnRenderProps>
   className?: ClassNameOrFunction<ColumnRenderProps> = 'react-aria-Column'
   defaultWidth?: ColumnSize | null
+  focusMode?: 'child' | 'cell'
   id?: Key
   isRowHeader?: boolean
   maxWidth?: ColumnStaticSize | null
   minWidth?: ColumnStaticSize | null
   style?: StyleOrFunction<ColumnRenderProps>
   textValue?: string
   width?: ColumnSize | null
 }

/react-aria-components:CellProps

 CellProps {
+  allowsArrowNavigation?: boolean
   children?: ChildrenOrFunction<CellRenderProps>
   className?: ClassNameOrFunction<CellRenderProps> = 'react-aria-Cell'
   colSpan?: number
+  focusMode?: 'child' | 'cell'
   id?: Key
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, CellRenderProps>
   style?: StyleOrFunction<CellRenderProps>
   textValue?: string

/react-aria-components:TreeItemProps

 TreeItemProps <T = {}> {
+  allowsArrowNavigation?: boolean
   aria-label?: string
   children: ReactNode
   className?: ClassNameOrFunction<TreeItemRenderProps> = 'react-aria-TreeItem'
   download?: boolean | string
+  focusMode?: 'child' | 'row' = 'row'
   hasChildItems?: boolean
   href?: Href
   hrefLang?: string
   id?: Key
   onAction?: () => void
   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, TreeItemRenderProps>
   routerOptions?: RouterOptions
   style?: StyleOrFunction<TreeItemRenderProps>
   target?: HTMLAttributeAnchorTarget
   textValue: string
   value?: T
 }

/react-aria-components:GridListHeaderProps

+GridListHeaderProps {
+  children?: ReactNode
+  className?: string
+  id?: string
+  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
+  style?: CSSProperties
+}

@react-aria/grid

/@react-aria/grid:GridProps

 GridProps {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   disallowTypeAhead?: boolean = false
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   focusMode?: 'row' | 'cell' = 'row'
   getRowText?: (Key) => string = (key) => state.collection.getItem(key)?.textValue
   id?: string
   isVirtualized?: boolean
   keyboardDelegate?: KeyboardDelegate
+  keyboardNavigationBehavior?: 'arrow' | 'tab' = 'arrow'
   onCellAction?: (Key) => void
   onRowAction?: (Key) => void
   scrollRef?: RefObject<HTMLElement | null>
   shouldSelectOnPressUp?: boolean

/@react-aria/grid:GridCellProps

 GridCellProps {
+  allowsArrowNavigation?: boolean
   colSpan?: number
   focusMode?: 'child' | 'cell'
   isVirtualized?: boolean
   node: GridNode<unknown>
 }

@react-aria/gridlist

/@react-aria/gridlist:AriaGridListItemOptions

 AriaGridListItemOptions {
+  allowsArrowNavigation?: boolean
+  focusMode?: 'child' | 'row' = 'row'
   hasChildItems?: boolean
   isVirtualized?: boolean
   node: Node<unknown>
   shouldSelectOnPressUp?: boolean

@react-aria/table

/@react-aria/table:AriaTableProps

 AriaTableProps {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   disallowTypeAhead?: boolean = false
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   focusMode?: 'row' | 'cell' = 'row'
   getRowText?: (Key) => string = (key) => state.collection.getItem(key)?.textValue
   id?: string
   isVirtualized?: boolean
   keyboardDelegate?: KeyboardDelegate
+  keyboardNavigationBehavior?: 'arrow' | 'tab' = 'arrow'
   layoutDelegate?: LayoutDelegate
   onCellAction?: (Key) => void
   onRowAction?: (Key) => void
   scrollRef?: RefObject<HTMLElement | null>
 }

/@react-aria/table:AriaTableColumnHeaderProps

 AriaTableColumnHeaderProps <T> {
+  allowsArrowNavigation?: boolean
+  focusMode?: 'child' | 'cell'
   isVirtualized?: boolean
   node: GridNode<T>
 }

/@react-aria/table:AriaTableCellProps

 AriaTableCellProps {
+  allowsArrowNavigation?: boolean
+  focusMode?: 'child' | 'cell'
   isVirtualized?: boolean
   node: GridNode<unknown>
   shouldSelectOnPressUp?: boolean
 }

@react-aria/tree

/@react-aria/tree:AriaTreeItemOptions

 AriaTreeItemOptions {
+  allowsArrowNavigation?: boolean
+  focusMode?: 'child' | 'row' = 'row'
   hasChildItems?: boolean
   node: Node<unknown>
   shouldSelectOnPressUp?: boolean
 }

@react-spectrum/ai

/@react-spectrum/ai:Attachment

 Attachment {
+  allowsArrowNavigation?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children: ReactNode | (AttachmentRenderProps) => ReactNode
   density?: 'compact' | 'regular' | 'spacious' = 'regular'
   download?: boolean | string
+  focusMode?: 'child' | 'row'
   href?: Href
   hrefLang?: string
   id?: Key
   isDisabled?: boolean
   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, TagRenderProps>
   routerOptions?: RouterOptions
   size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
   styles?: StyleString
   target?: HTMLAttributeAnchorTarget
   textValue?: string
   uploadProgress?: number
   value?: T
   variant?: 'primary' | 'secondary' | 'tertiary' | 'quiet' = 'primary'
 }

/@react-spectrum/ai:ThreadItem

 ThreadItem {
+  allowsArrowNavigation?: boolean
   children?: ChildrenOrFunction<GridListItemRenderProps>
+  focusMode?: 'child' | 'row'
   isStreaming?: boolean
   shouldAnnounceOnMount?: boolean
   styles?: StyleString
   textValue?: string

/@react-spectrum/ai:AttachmentProps

 AttachmentProps {
+  allowsArrowNavigation?: boolean
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children: ReactNode | (AttachmentRenderProps) => ReactNode
   density?: 'compact' | 'regular' | 'spacious' = 'regular'
   download?: boolean | string
+  focusMode?: 'child' | 'row'
   href?: Href
   hrefLang?: string
   id?: Key
   isDisabled?: boolean
   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, TagRenderProps>
   routerOptions?: RouterOptions
   size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
   styles?: StyleString
   target?: HTMLAttributeAnchorTarget
   textValue?: string
   uploadProgress?: number
   value?: T
   variant?: 'primary' | 'secondary' | 'tertiary' | 'quiet' = 'primary'
 }

/@react-spectrum/ai:ThreadItemProps

 ThreadItemProps {
+  allowsArrowNavigation?: boolean
   children?: ChildrenOrFunction<GridListItemRenderProps>
+  focusMode?: 'child' | 'row'
   isStreaming?: boolean
   shouldAnnounceOnMount?: boolean
   styles?: StyleString
   textValue?: string

@react-spectrum/s2

/@react-spectrum/s2:Card

 Card {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
+  allowsArrowNavigation?: boolean
   children: ReactNode | (CardRenderProps) => ReactNode
   density?: 'compact' | 'regular' | 'spacious' = 'regular'
   download?: boolean | string
+  focusMode?: 'child' | 'row'
   href?: Href
   hrefLang?: string
   id?: Key
   isDisabled?: boolean
   onPress?: (PressEvent) => void
   onPressChange?: (boolean) => void
   onPressEnd?: (PressEvent) => void
   onPressStart?: (PressEvent) => void
   onPressUp?: (PressEvent) => void
   ping?: string
   referrerPolicy?: HTMLAttributeReferrerPolicy
   rel?: string
   routerOptions?: RouterOptions
   size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
   styles?: StylesProp
   target?: HTMLAttributeAnchorTarget
   textValue?: string
   value?: T
   variant?: 'primary' | 'secondary' | 'tertiary' | 'quiet' = 'primary'
 }

/@react-spectrum/s2:AssetCard

 AssetCard {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
+  allowsArrowNavigation?: boolean
   children: ReactNode | (CardRenderProps) => ReactNode
   download?: boolean | string
+  focusMode?: 'child' | 'row'
   href?: Href
   hrefLang?: string
   id?: Key
   isDisabled?: boolean
   onPress?: (PressEvent) => void
   onPressChange?: (boolean) => void
   onPressEnd?: (PressEvent) => void
   onPressStart?: (PressEvent) => void
   onPressUp?: (PressEvent) => void
   ping?: string
   referrerPolicy?: HTMLAttributeReferrerPolicy
   rel?: string
   routerOptions?: RouterOptions
   size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
   styles?: StylesProp
   target?: HTMLAttributeAnchorTarget
   textValue?: string
   value?: T
   variant?: 'primary' | 'secondary' | 'tertiary' | 'quiet' = 'primary'
 }

/@react-spectrum/s2:UserCard

 UserCard {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
+  allowsArrowNavigation?: boolean
   children: ReactNode | (CardRenderProps) => ReactNode
   download?: boolean | string
+  focusMode?: 'child' | 'row'
   href?: Href
   hrefLang?: string
   id?: Key
   isDisabled?: boolean
   onPress?: (PressEvent) => void
   onPressChange?: (boolean) => void
   onPressEnd?: (PressEvent) => void
   onPressStart?: (PressEvent) => void
   onPressUp?: (PressEvent) => void
   ping?: string
   referrerPolicy?: HTMLAttributeReferrerPolicy
   rel?: string
   routerOptions?: RouterOptions
   size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
   styles?: StylesProp
   target?: HTMLAttributeAnchorTarget
   textValue?: string
   value?: T
   variant?: 'primary' | 'secondary' | 'tertiary'
 }

/@react-spectrum/s2:ProductCard

 ProductCard {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
+  allowsArrowNavigation?: boolean
   children: ReactNode | (CardRenderProps) => ReactNode
   download?: boolean | string
+  focusMode?: 'child' | 'row'
   href?: Href
   hrefLang?: string
   id?: Key
   isDisabled?: boolean
   onPress?: (PressEvent) => void
   onPressChange?: (boolean) => void
   onPressEnd?: (PressEvent) => void
   onPressStart?: (PressEvent) => void
   onPressUp?: (PressEvent) => void
   ping?: string
   referrerPolicy?: HTMLAttributeReferrerPolicy
   rel?: string
   routerOptions?: RouterOptions
   size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
   styles?: StylesProp
   target?: HTMLAttributeAnchorTarget
   textValue?: string
   value?: T
   variant?: 'primary' | 'secondary' | 'tertiary'
 }

/@react-spectrum/s2:ListViewItem

 ListViewItem {
+  allowsArrowNavigation?: boolean
   children: ReactNode
   download?: boolean | string
+  focusMode?: 'child' | 'row'
   hasChildItems?: boolean
   href?: Href
   hrefLang?: string
   id?: Key
   onAction?: () => 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
   routerOptions?: RouterOptions
   target?: HTMLAttributeAnchorTarget
   textValue?: string
   value?: T
 }

/@react-spectrum/s2:TableView

 TableView {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode
   defaultExpandedKeys?: Iterable<Key>
   defaultSelectedKeys?: 'all' | Iterable<Key>
   density?: 'compact' | 'spacious' | 'regular' = 'regular'
   disabledBehavior?: DisabledBehavior = 'all'
   disabledKeys?: Iterable<Key>
   disallowEmptySelection?: boolean
   dragAndDropHooks?: DragAndDropHooks
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   expandedKeys?: Iterable<Key>
   id?: string
   isQuiet?: boolean
+  keyboardNavigationBehavior?: 'arrow' | 'tab' = 'arrow'
   loadingState?: LoadingState
   onAction?: (Key) => void
   onExpandedChange?: (Set<Key>) => any
   onLoadMore?: () => any
   onResizeEnd?: (Map<Key, ColumnSize>) => void
   onResizeStart?: (Map<Key, ColumnSize>) => void
   onSelectionChange?: (Selection) => void
   onSortChange?: (SortDescriptor) => any
   overflowMode?: 'wrap' | 'truncate' = 'truncate'
   renderActionBar?: ('all' | Set<Key>) => ReactElement
   selectedKeys?: 'all' | Iterable<Key>
   selectionMode?: SelectionMode
   selectionStyle?: 'checkbox' | 'highlight' = 'checkbox'
   shouldSelectOnPressUp?: boolean
   slot?: string | null
   sortDescriptor?: SortDescriptor
   styles?: StylesPropWithHeight
   treeColumn?: Key
 }

/@react-spectrum/s2:Cell

 Cell {
   align?: 'start' | 'center' | 'end' = 'start'
+  allowsArrowNavigation?: boolean
   children: ReactNode
   colSpan?: number
+  focusMode?: 'child' | 'cell'
   id?: Key
   showDivider?: boolean
   textValue?: string
 }

/@react-spectrum/s2:Column

 Column {
   align?: 'start' | 'center' | 'end' = 'start'
+  allowsArrowNavigation?: boolean
   allowsResizing?: boolean
   allowsSorting?: boolean
   children: ReactNode
   defaultWidth?: ColumnSize | null
+  focusMode?: 'child' | 'cell'
   id?: Key
   isRowHeader?: boolean
   maxWidth?: ColumnStaticSize | null
   menuItems?: ReactNode
   showDivider?: boolean
   textValue?: string
   width?: ColumnSize | null
 }

/@react-spectrum/s2:EditableCell

 EditableCell {
   action?: string | FormHTMLAttributes<HTMLFormElement>['action']
   align?: 'start' | 'center' | 'end' = 'start'
+  allowsArrowNavigation?: boolean
   children: ReactNode
   colSpan?: number
+  focusMode?: 'child' | 'cell'
   id?: Key
   isSaving?: boolean
   onCancel?: () => void
   onSubmit?: (FormEvent<HTMLFormElement>) => void
   showDivider?: boolean
   textValue?: string
 }

/@react-spectrum/s2:TreeViewItem

 TreeViewItem {
+  allowsArrowNavigation?: boolean
   aria-label?: string
   children: ReactNode
   download?: boolean | string
+  focusMode?: 'child' | 'row' = 'row'
   hasChildItems?: boolean
   href?: Href
   hrefLang?: string
   id?: Key
   onAction?: () => 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
   routerOptions?: RouterOptions
   target?: HTMLAttributeAnchorTarget
   textValue: string
   value?: T
 }

/@react-spectrum/s2:CardProps

 CardProps {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
+  allowsArrowNavigation?: boolean
   children: ReactNode | (CardRenderProps) => ReactNode
   density?: 'compact' | 'regular' | 'spacious' = 'regular'
   download?: boolean | string
+  focusMode?: 'child' | 'row'
   href?: Href
   hrefLang?: string
   id?: Key
   isDisabled?: boolean
   onPress?: (PressEvent) => void
   onPressChange?: (boolean) => void
   onPressEnd?: (PressEvent) => void
   onPressStart?: (PressEvent) => void
   onPressUp?: (PressEvent) => void
   ping?: string
   referrerPolicy?: HTMLAttributeReferrerPolicy
   rel?: string
   routerOptions?: RouterOptions
   size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
   styles?: StylesProp
   target?: HTMLAttributeAnchorTarget
   textValue?: string
   value?: T
   variant?: 'primary' | 'secondary' | 'tertiary' | 'quiet' = 'primary'
 }

/@react-spectrum/s2:AssetCardProps

 AssetCardProps {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
+  allowsArrowNavigation?: boolean
   children: ReactNode | (CardRenderProps) => ReactNode
   download?: boolean | string
+  focusMode?: 'child' | 'row'
   href?: Href
   hrefLang?: string
   id?: Key
   isDisabled?: boolean
   onPress?: (PressEvent) => void
   onPressChange?: (boolean) => void
   onPressEnd?: (PressEvent) => void
   onPressStart?: (PressEvent) => void
   onPressUp?: (PressEvent) => void
   ping?: string
   referrerPolicy?: HTMLAttributeReferrerPolicy
   rel?: string
   routerOptions?: RouterOptions
   size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
   styles?: StylesProp
   target?: HTMLAttributeAnchorTarget
   textValue?: string
   value?: T
   variant?: 'primary' | 'secondary' | 'tertiary' | 'quiet' = 'primary'
 }

/@react-spectrum/s2:ProductCardProps

 ProductCardProps {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
+  allowsArrowNavigation?: boolean
   children: ReactNode | (CardRenderProps) => ReactNode
   download?: boolean | string
+  focusMode?: 'child' | 'row'
   href?: Href
   hrefLang?: string
   id?: Key
   isDisabled?: boolean
   onPress?: (PressEvent) => void
   onPressChange?: (boolean) => void
   onPressEnd?: (PressEvent) => void
   onPressStart?: (PressEvent) => void
   onPressUp?: (PressEvent) => void
   ping?: string
   referrerPolicy?: HTMLAttributeReferrerPolicy
   rel?: string
   routerOptions?: RouterOptions
   size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
   styles?: StylesProp
   target?: HTMLAttributeAnchorTarget
   textValue?: string
   value?: T
   variant?: 'primary' | 'secondary' | 'tertiary'
 }

/@react-spectrum/s2:UserCardProps

 UserCardProps {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
+  allowsArrowNavigation?: boolean
   children: ReactNode | (CardRenderProps) => ReactNode
   download?: boolean | string
+  focusMode?: 'child' | 'row'
   href?: Href
   hrefLang?: string
   id?: Key
   isDisabled?: boolean
   onPress?: (PressEvent) => void
   onPressChange?: (boolean) => void
   onPressEnd?: (PressEvent) => void
   onPressStart?: (PressEvent) => void
   onPressUp?: (PressEvent) => void
   ping?: string
   referrerPolicy?: HTMLAttributeReferrerPolicy
   rel?: string
   routerOptions?: RouterOptions
   size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
   styles?: StylesProp
   target?: HTMLAttributeAnchorTarget
   textValue?: string
   value?: T
   variant?: 'primary' | 'secondary' | 'tertiary'
 }

/@react-spectrum/s2:ListViewItemProps

 ListViewItemProps {
+  allowsArrowNavigation?: boolean
   children: ReactNode
   download?: boolean | string
+  focusMode?: 'child' | 'row'
   hasChildItems?: boolean
   href?: Href
   hrefLang?: string
   id?: Key
   onAction?: () => 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
   routerOptions?: RouterOptions
   target?: HTMLAttributeAnchorTarget
   textValue?: string
   value?: T
 }

/@react-spectrum/s2:TableViewProps

 TableViewProps {
   UNSAFE_className?: UnsafeClassName
   UNSAFE_style?: CSSProperties
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   children?: ReactNode
   defaultExpandedKeys?: Iterable<Key>
   defaultSelectedKeys?: 'all' | Iterable<Key>
   density?: 'compact' | 'spacious' | 'regular' = 'regular'
   disabledBehavior?: DisabledBehavior = 'all'
   disabledKeys?: Iterable<Key>
   disallowEmptySelection?: boolean
   dragAndDropHooks?: DragAndDropHooks
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   expandedKeys?: Iterable<Key>
   id?: string
   isQuiet?: boolean
+  keyboardNavigationBehavior?: 'arrow' | 'tab' = 'arrow'
   loadingState?: LoadingState
   onAction?: (Key) => void
   onExpandedChange?: (Set<Key>) => any
   onLoadMore?: () => any
   onResizeEnd?: (Map<Key, ColumnSize>) => void
   onResizeStart?: (Map<Key, ColumnSize>) => void
   onSelectionChange?: (Selection) => void
   onSortChange?: (SortDescriptor) => any
   overflowMode?: 'wrap' | 'truncate' = 'truncate'
   renderActionBar?: ('all' | Set<Key>) => ReactElement
   selectedKeys?: 'all' | Iterable<Key>
   selectionMode?: SelectionMode
   selectionStyle?: 'checkbox' | 'highlight' = 'checkbox'
   shouldSelectOnPressUp?: boolean
   slot?: string | null
   sortDescriptor?: SortDescriptor
   styles?: StylesPropWithHeight
   treeColumn?: Key
 }

/@react-spectrum/s2:CellProps

 CellProps {
   align?: 'start' | 'center' | 'end' = 'start'
+  allowsArrowNavigation?: boolean
   children: ReactNode
   colSpan?: number
+  focusMode?: 'child' | 'cell'
   id?: Key
   showDivider?: boolean
   textValue?: string
 }

/@react-spectrum/s2:ColumnProps

 ColumnProps {
   align?: 'start' | 'center' | 'end' = 'start'
+  allowsArrowNavigation?: boolean
   allowsResizing?: boolean
   allowsSorting?: boolean
   children: ReactNode
   defaultWidth?: ColumnSize | null
+  focusMode?: 'child' | 'cell'
   id?: Key
   isRowHeader?: boolean
   maxWidth?: ColumnStaticSize | null
   menuItems?: ReactNode
   showDivider?: boolean
   textValue?: string
   width?: ColumnSize | null
 }

/@react-spectrum/s2:TreeViewItemProps

 TreeViewItemProps {
+  allowsArrowNavigation?: boolean
   aria-label?: string
   children: ReactNode
   download?: boolean | string
+  focusMode?: 'child' | 'row' = 'row'
   hasChildItems?: boolean
   href?: Href
   hrefLang?: string
   id?: Key
   onAction?: () => 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
   routerOptions?: RouterOptions
   target?: HTMLAttributeAnchorTarget
   textValue: string
   value?: T
 }

/@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
+}

@react-spectrum/table

/@react-spectrum/table:TableView

 TableView <T extends {}> {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'>
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   bottom?: Responsive<DimensionValue>
   children: [ReactElement<TableHeaderProps<T>>, ReactElement<TableBodyProps<T>>]
   defaultSelectedKeys?: 'all' | Iterable<Key>
   density?: 'compact' | 'regular' | 'spacious' = 'regular'
   disabledBehavior?: DisabledBehavior = 'selection'
   disabledKeys?: Iterable<Key>
   disallowEmptySelection?: boolean
   dragAndDropHooks?: DragAndDropHooks<NoInfer<{}>>['dragAndDropHooks']
   end?: Responsive<DimensionValue>
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: Responsive<number>
   flexShrink?: Responsive<number>
   gridArea?: Responsive<string>
   gridColumn?: Responsive<string>
   gridColumnEnd?: Responsive<string>
   gridColumnStart?: Responsive<string>
   gridRow?: Responsive<string>
   gridRowEnd?: Responsive<string>
   gridRowStart?: Responsive<string>
   height?: Responsive<DimensionValue>
   id?: string
   isHidden?: Responsive<boolean>
   isQuiet?: boolean
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
+  keyboardNavigationBehavior?: 'arrow' | 'tab' = 'arrow'
   left?: Responsive<DimensionValue>
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginTop?: Responsive<DimensionValue>
   marginX?: Responsive<DimensionValue>
   marginY?: Responsive<DimensionValue>
   maxHeight?: Responsive<DimensionValue>
   maxWidth?: Responsive<DimensionValue>
   minHeight?: Responsive<DimensionValue>
   minWidth?: Responsive<DimensionValue>
   onAction?: (Key) => void
   onResize?: (Map<Key, ColumnSize>) => void
   onResizeEnd?: (Map<Key, ColumnSize>) => void
   onResizeStart?: (Map<Key, ColumnSize>) => void
   onSelectionChange?: (Selection) => void
   onSortChange?: (SortDescriptor) => any
   order?: Responsive<number>
   overflowMode?: 'wrap' | 'truncate' = 'truncate'
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   renderEmptyState?: () => JSX.Element
   right?: Responsive<DimensionValue>
   selectedKeys?: 'all' | Iterable<Key>
   selectionMode?: SelectionMode
   selectionStyle?: 'checkbox' | 'highlight'
   shouldSelectOnPressUp?: boolean
   sortDescriptor?: SortDescriptor
   start?: Responsive<DimensionValue>
   top?: Responsive<DimensionValue>
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

/@react-spectrum/table:SpectrumTableProps

 SpectrumTableProps <T> {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'>
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   bottom?: Responsive<DimensionValue>
   children: [ReactElement<TableHeaderProps<T>>, ReactElement<TableBodyProps<T>>]
   defaultSelectedKeys?: 'all' | Iterable<Key>
   density?: 'compact' | 'regular' | 'spacious' = 'regular'
   disabledBehavior?: DisabledBehavior = 'selection'
   disabledKeys?: Iterable<Key>
   disallowEmptySelection?: boolean
   dragAndDropHooks?: DragAndDropHooks<NoInfer<T>>['dragAndDropHooks']
   end?: Responsive<DimensionValue>
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: Responsive<number>
   flexShrink?: Responsive<number>
   gridArea?: Responsive<string>
   gridColumn?: Responsive<string>
   gridColumnEnd?: Responsive<string>
   gridColumnStart?: Responsive<string>
   gridRow?: Responsive<string>
   gridRowEnd?: Responsive<string>
   gridRowStart?: Responsive<string>
   height?: Responsive<DimensionValue>
   id?: string
   isHidden?: Responsive<boolean>
   isQuiet?: boolean
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
+  keyboardNavigationBehavior?: 'arrow' | 'tab' = 'arrow'
   left?: Responsive<DimensionValue>
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginTop?: Responsive<DimensionValue>
   marginX?: Responsive<DimensionValue>
   marginY?: Responsive<DimensionValue>
   maxHeight?: Responsive<DimensionValue>
   maxWidth?: Responsive<DimensionValue>
   minHeight?: Responsive<DimensionValue>
   minWidth?: Responsive<DimensionValue>
   onAction?: (Key) => void
   onResize?: (Map<Key, ColumnSize>) => void
   onResizeEnd?: (Map<Key, ColumnSize>) => void
   onResizeStart?: (Map<Key, ColumnSize>) => void
   onSelectionChange?: (Selection) => void
   onSortChange?: (SortDescriptor) => any
   order?: Responsive<number>
   overflowMode?: 'wrap' | 'truncate' = 'truncate'
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   renderEmptyState?: () => JSX.Element
   right?: Responsive<DimensionValue>
   selectedKeys?: 'all' | Iterable<Key>
   selectionMode?: SelectionMode
   selectionStyle?: 'checkbox' | 'highlight'
   shouldSelectOnPressUp?: boolean
   sortDescriptor?: SortDescriptor
   start?: Responsive<DimensionValue>
   top?: Responsive<DimensionValue>
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

@react-spectrum/tree

/@react-spectrum/tree:TreeViewItem

 TreeViewItem {
+  allowsArrowNavigation?: boolean
   aria-label?: string
   children: ReactNode
   download?: boolean | string
+  focusMode?: 'child' | 'row' = 'row'
   hasChildItems?: boolean
   href?: Href
   hrefLang?: string
   id?: Key
   onAction?: () => 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/tree:SpectrumTreeViewItemProps

 SpectrumTreeViewItemProps {
+  allowsArrowNavigation?: boolean
   aria-label?: string
   children: ReactNode
   download?: boolean | string
+  focusMode?: 'child' | 'row' = 'row'
   hasChildItems?: boolean
   href?: Href
   hrefLang?: string
   id?: Key
   onAction?: () => 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-stately/table

/@react-stately/table:TableProps

 TableProps <T> {
   children: [ReactElement<TableHeaderProps<T>>, ReactElement<TableBodyProps<T>>]
   defaultExpandedKeys?: Iterable<Key>
   defaultSelectedKeys?: 'all' | Iterable<Key>
   disabledKeys?: Iterable<Key>
   disallowEmptySelection?: boolean
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   expandedKeys?: Iterable<Key>
+  keyboardNavigationBehavior?: 'arrow' | 'tab' = 'arrow'
   onExpandedChange?: (Set<Key>) => any
   onSelectionChange?: (Selection) => void
   onSortChange?: (SortDescriptor) => any
   selectedKeys?: 'all' | Iterable<Key>
   shouldSelectOnPressUp?: boolean
   sortDescriptor?: SortDescriptor
   treeColumn?: Key
 }

@rspbot

rspbot commented Jul 15, 2026

Copy link
Copy Markdown

Agent Skills Changes

Added (1)
Modified (10)
Install

React Spectrum S2:

npx skills add https://d1pzu54gtk2aed.cloudfront.net/pr/05b4bcb73e84444e4ba733b264014364ccd7f040/

React Aria:

npx skills add https://d5iwopk28bdhl.cloudfront.net/pr/05b4bcb73e84444e4ba733b264014364ccd7f040/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants