Skip to content

feat: (WIP) Async Menu support - #10494

Draft
LFDanLu wants to merge 2 commits into
mainfrom
async_menu_rac
Draft

feat: (WIP) Async Menu support#10494
LFDanLu wants to merge 2 commits into
mainfrom
async_menu_rac

Conversation

@LFDanLu

@LFDanLu LFDanLu commented Aug 21, 2026

Copy link
Copy Markdown
Member

For coworker use case

✅ 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
  • I understand every change in this PR and can explain why it's there.
  • If AI-assisted, I followed our AI contribution guidance and pointed my assistant at CLAUDE.md.

📝 Test Instructions:

🧢 Your Project:

RSP

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.

basically ListBox's implementation

@rspbot

rspbot commented Aug 21, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Aug 21, 2026

Copy link
Copy Markdown
## API Changes

react-aria-components

/react-aria-components:GridListLoadMoreItem

 GridListLoadMoreItem {
   children?: ReactNode
-  className?: string = 'react-aria-GridListLoadMoreItem'
+  className?: string = 'react-aria-GridListLoadingIndicator'
   isLoading?: boolean
   onLoadMore?: () => any
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
   scrollOffset?: number = 1
 }

/react-aria-components:ListBoxLoadMoreItem

 ListBoxLoadMoreItem {
   children?: ReactNode
-  className?: string = 'react-aria-ListBoxLoadMoreItem'
+  className?: string = 'react-aria-ListBoxLoadingIndicator'
   isLoading?: boolean
   onLoadMore?: () => any
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
   scrollOffset?: number = 1
 }

/react-aria-components:TableLoadMoreItem

 TableLoadMoreItem {
   children?: ReactNode
-  className?: string = 'react-aria-TableLoadMoreItem'
+  className?: string = 'react-aria-TableLoadingIndicator'
   direction?: 'start' | 'end' = 'end'
   isLoading?: boolean
   onLoadMore?: () => any
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
   style?: CSSProperties
 }

/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:TreeLoadMoreItem

 TreeLoadMoreItem <T> {
   children?: ChildrenOrFunction<TreeLoadMoreItemRenderProps>
-  className?: ClassNameOrFunction<TreeLoadMoreItemRenderProps> = 'react-aria-TreeLoadMoreItem'
+  className?: ClassNameOrFunction<TreeLoadMoreItemRenderProps> = 'react-aria-TreeLoader'
   isLoading?: boolean
   onLoadMore?: () => any
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, TreeLoadMoreItemRenderProps>
   scrollOffset?: number = 1
 }

/react-aria-components:GridListLoadMoreItemProps

 GridListLoadMoreItemProps {
   children?: ReactNode
-  className?: string = 'react-aria-GridListLoadMoreItem'
+  className?: string = 'react-aria-GridListLoadingIndicator'
   isLoading?: boolean
   onLoadMore?: () => any
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
   scrollOffset?: number = 1
 }

/react-aria-components:ListBoxLoadMoreItemProps

 ListBoxLoadMoreItemProps {
   children?: ReactNode
-  className?: string = 'react-aria-ListBoxLoadMoreItem'
+  className?: string = 'react-aria-ListBoxLoadingIndicator'
   isLoading?: boolean
   onLoadMore?: () => any
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
   scrollOffset?: number = 1
 }

/react-aria-components:TableLoadMoreItemProps

 TableLoadMoreItemProps {
   children?: ReactNode
-  className?: string = 'react-aria-TableLoadMoreItem'
+  className?: string = 'react-aria-TableLoadingIndicator'
   direction?: 'start' | 'end' = 'end'
   isLoading?: boolean
   onLoadMore?: () => any
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
   style?: CSSProperties
 }

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

/react-aria-components:TreeLoadMoreItemProps

 TreeLoadMoreItemProps {
   children?: ChildrenOrFunction<TreeLoadMoreItemRenderProps>
-  className?: ClassNameOrFunction<TreeLoadMoreItemRenderProps> = 'react-aria-TreeLoadMoreItem'
+  className?: ClassNameOrFunction<TreeLoadMoreItemRenderProps> = 'react-aria-TreeLoader'
   isLoading?: boolean
   onLoadMore?: () => any
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, TreeLoadMoreItemRenderProps>
   scrollOffset?: number = 1
 }

/react-aria-components:MenuLoadMoreItem

+MenuLoadMoreItem {
+  children?: ReactNode
+  className?: string = 'react-aria-MenuLoadingIndicator'
+  isLoading?: boolean
+  onLoadMore?: () => any
+  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
+  scrollOffset?: number = 1
+  style?: CSSProperties
+}

/react-aria-components:MenuLoadMoreItemProps

+MenuLoadMoreItemProps {
+  children?: ReactNode
+  className?: string = 'react-aria-MenuLoadingIndicator'
+  isLoading?: boolean
+  onLoadMore?: () => any
+  render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
+  scrollOffset?: number = 1
+  style?: CSSProperties
+}

@react-spectrum/ai

/@react-spectrum/ai:ThreadLoadMoreItem

 ThreadLoadMoreItem {
   children?: ReactNode
-  className?: string = 'react-aria-GridListLoadMoreItem'
+  className?: string = 'react-aria-GridListLoadingIndicator'
   isLoading?: boolean
   onLoadMore?: () => any
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
   scrollOffset?: number = 1
 }

/@react-spectrum/ai:ThreadLoadMoreItemProps

 ThreadLoadMoreItemProps {
   children?: ReactNode
-  className?: string = 'react-aria-GridListLoadMoreItem'
+  className?: string = 'react-aria-GridListLoadingIndicator'
   isLoading?: boolean
   onLoadMore?: () => any
   render?: DOMRenderFunction<keyof React.JSX.IntrinsicElements, undefined>
   scrollOffset?: number = 1
 }

@rspbot

rspbot commented Aug 21, 2026

Copy link
Copy Markdown

Agent Skills Changes

Added (450)

… output truncated to fit GitHub comment size limit.

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.

2 participants