Skip to content

(DNM) Feat: Add support for horizontal orientation to GridList & ListBox test build #8544

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from

Conversation

LFDanLu
Copy link
Member

@LFDanLu LFDanLu commented Jul 14, 2025

Closes

✅ 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:

@rspbot
Copy link

rspbot commented Jul 14, 2025

@rspbot
Copy link

rspbot commented Jul 14, 2025

## API Changes

react-aria-components

/react-aria-components:GridListLoadMoreItem

-GridListLoadMoreItem {
+GridListLoadMoreItem <T extends {}> {
   children?: ReactNode
   className?: string
   isLoading?: boolean
   scrollOffset?: number = 1
   style?: CSSProperties
 }

/react-aria-components:GridList

 GridList <T extends {}> {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean | FocusStrategy
   children?: ReactNode | ({}) => ReactNode
   className?: ClassNameOrFunction<GridListRenderProps>
   defaultSelectedKeys?: 'all' | Iterable<Key>
   dependencies?: ReadonlyArray<any>
   disabledBehavior?: DisabledBehavior = "all"
   disabledKeys?: Iterable<Key>
   disallowEmptySelection?: boolean
   disallowTypeAhead?: boolean = false
   dragAndDropHooks?: DragAndDropHooks
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   id?: string
   items?: Iterable<T>
   keyboardNavigationBehavior?: 'arrow' | 'tab' = 'arrow'
   layout?: 'stack' | 'grid' = 'stack'
   onAction?: (Key) => void
   onSelectionChange?: (Selection) => void
+  orientation?: Orientation = 'vertical'
   renderEmptyState?: (GridListRenderProps) => ReactNode
   selectedKeys?: 'all' | Iterable<Key>
   selectionBehavior?: SelectionBehavior = "toggle"
   selectionMode?: SelectionMode
   slot?: string | null
   style?: StyleOrFunction<GridListRenderProps>
 }

/react-aria-components:ListBoxLoadMoreItem

-ListBoxLoadMoreItem {
+ListBoxLoadMoreItem <T extends {}> {
   children?: ReactNode
   className?: string
   isLoading?: boolean
   scrollOffset?: number = 1
   style?: CSSProperties
 }

/react-aria-components:TableLoadMoreItem

-TableLoadMoreItem {
+TableLoadMoreItem <T extends {}> {
   children?: ReactNode
   className?: string
   isLoading?: boolean
   scrollOffset?: number = 1
   style?: CSSProperties
 }

/react-aria-components:TableLayout

 TableLayout <O extends TableLayoutProps = TableLayoutProps, T> {
   constructor: (ListLayoutOptions) => void
   getContentSize: () => Size
   getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget | null
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getLayoutInfo: (Key) => LayoutInfo | null
+  getOrientation: () => Orientation | null
   getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (TableLayoutProps, TableLayoutProps) => boolean
   update: (InvalidationContext<TableLayoutProps>) => void
   useLayoutOptions: () => TableLayoutProps
   virtualizer: Virtualizer<{}, any> | null
 }

/react-aria-components:ListLayout

 ListLayout <O extends ListLayoutOptions = ListLayoutOptions, T> {
   constructor: (ListLayoutOptions) => void
   getContentSize: () => Size
   getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget | null
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getLayoutInfo: (Key) => LayoutInfo | null
+  getOrientation: () => Orientation | null
   getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (ListLayoutOptions, ListLayoutOptions) => boolean
   update: (InvalidationContext<ListLayoutOptions>) => void
   virtualizer: Virtualizer<{}, any> | null
 }

/react-aria-components:GridLayout

 GridLayout <O extends GridLayoutOptions = GridLayoutOptions, T> {
+  constructor: (LayoutOptions) => void
   getContentSize: () => Size
   getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getLayoutInfo: (Key) => LayoutInfo | null
+  getOrientation: () => Orientation | null
   getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (GridLayoutOptions, GridLayoutOptions) => boolean
   update: (InvalidationContext<GridLayoutOptions>) => void
   virtualizer: Virtualizer<{}, any> | null
 }

/react-aria-components:WaterfallLayout

 WaterfallLayout <O extends WaterfallLayoutOptions = WaterfallLayoutOptions, T extends {}> {
+  constructor: (LayoutOptions) => void
   getContentSize: () => Size
   getDropTargetFromPoint: (number, number) => DropTarget
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getKeyLeftOf: (Key) => Key | null
   getKeyRange: (Key, Key) => Array<Key>
   getKeyRightOf: (Key) => Key | null
   getLayoutInfo: (Key) => LayoutInfo
+  getOrientation: () => Orientation | null
   getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (WaterfallLayoutOptions, WaterfallLayoutOptions) => boolean
   update: (InvalidationContext<WaterfallLayoutOptions>) => void
   virtualizer: Virtualizer<{}, any> | null
 }

/react-aria-components:Layout

 Layout <O = any, T extends {} = Node<any>> {
+  constructor: (LayoutOptions) => void
   getContentSize: () => Size
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getLayoutInfo: (Key) => LayoutInfo | null
+  getOrientation: () => Orientation | null
   getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (O, O) => boolean
   update: (InvalidationContext<O>) => void
   virtualizer: Virtualizer<{}, any> | null
 }

/react-aria-components:ColorSwatchPickerRenderProps

 ColorSwatchPickerRenderProps {
   isEmpty: boolean
   isFocusVisible: boolean
   isFocused: boolean
   layout: 'stack' | 'grid'
+  orientation: Orientation
   state: ListState<unknown>
 }

/react-aria-components:GridListProps

 GridListProps <T> {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean | FocusStrategy
   children?: ReactNode | (T) => ReactNode
   className?: ClassNameOrFunction<GridListRenderProps>
   defaultSelectedKeys?: 'all' | Iterable<Key>
   dependencies?: ReadonlyArray<any>
   disabledBehavior?: DisabledBehavior = "all"
   disabledKeys?: Iterable<Key>
   disallowEmptySelection?: boolean
   disallowTypeAhead?: boolean = false
   dragAndDropHooks?: DragAndDropHooks
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   id?: string
   items?: Iterable<T>
   keyboardNavigationBehavior?: 'arrow' | 'tab' = 'arrow'
   layout?: 'stack' | 'grid' = 'stack'
   onAction?: (Key) => void
   onSelectionChange?: (Selection) => void
+  orientation?: Orientation = 'vertical'
   renderEmptyState?: (GridListRenderProps) => ReactNode
   selectedKeys?: 'all' | Iterable<Key>
   selectionBehavior?: SelectionBehavior = "toggle"
   selectionMode?: SelectionMode
   slot?: string | null
   style?: StyleOrFunction<GridListRenderProps>
 }

/react-aria-components:GridListRenderProps

 GridListRenderProps {
   isDropTarget: boolean
   isEmpty: boolean
   isFocusVisible: boolean
   isFocused: boolean
   layout: 'stack' | 'grid'
+  orientation: Orientation
   state: ListState<unknown>
 }

/react-aria-components:ListBoxRenderProps

 ListBoxRenderProps {
   isDropTarget: boolean
   isEmpty: boolean
   isFocusVisible: boolean
   isFocused: boolean
   layout: 'stack' | 'grid'
+  orientation: Orientation
   state: ListState<unknown>
 }

/react-aria-components:ListLayoutOptions

 ListLayoutOptions {
   dropIndicatorThickness?: number = 2
   estimatedHeadingHeight?: number
   estimatedRowHeight?: number
   gap?: number = 0
   headingHeight?: number = 48
   loaderHeight?: number = 48
+  orientation?: Orientation = 'vertical'
   padding?: number = 0
   rowHeight?: number = 48
 }

@react-aria/grid

/@react-aria/grid:GridKeyboardDelegate

 GridKeyboardDelegate <C extends GridCollection<T>, T> {
   collection: GridCollection<T>
   constructor: (GridKeyboardDelegateOptions<GridCollection<T>>) => void
   getFirstKey: (Key, boolean) => Key | null
   getKeyAbove: (Key) => Key | null
   getKeyBelow: (Key) => Key | null
   getKeyForSearch: (string, Key) => Key | null
   getKeyLeftOf: (Key) => Key | null
   getKeyPageAbove: (Key) => Key | null
   getKeyPageBelow: (Key) => Key | null
   getKeyRightOf: (Key) => Key | null
   getLastKey: (Key, boolean) => Key | null
+  getOrientation: () => Orientation | null
 }

@react-aria/listbox

/@react-aria/listbox:AriaListBoxOptions

 AriaListBoxOptions <T> {
   aria-describedby?: string
   aria-details?: string
   aria-label?: string
   aria-labelledby?: string
   autoFocus?: boolean | FocusStrategy
   defaultSelectedKeys?: 'all' | Iterable<Key>
   disabledKeys?: Iterable<Key>
   disallowEmptySelection?: boolean
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   id?: string
   isVirtualized?: boolean
   items?: Iterable<T>
   keyboardDelegate?: KeyboardDelegate
   label?: ReactNode
   layoutDelegate?: LayoutDelegate
   linkBehavior?: 'action' | 'selection' | 'override' = 'override'
   onAction?: (Key) => void
   onBlur?: (FocusEvent<Target>) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onSelectionChange?: (Selection) => void
+  orientation?: Orientation
   selectedKeys?: 'all' | Iterable<Key>
   selectionBehavior?: SelectionBehavior
   selectionMode?: SelectionMode
   shouldFocusOnHover?: boolean
   shouldSelectOnPressUp?: boolean
   shouldUseVirtualFocus?: boolean
 }

@react-aria/selection

/@react-aria/selection:ListKeyboardDelegate

 ListKeyboardDelegate <T> {
   constructor: (Array<any>) => void
   getFirstKey: () => Key | null
   getKeyAbove: (Key) => Key | null
   getKeyBelow: (Key) => Key | null
   getKeyForSearch: (string, Key) => Key | null
   getKeyLeftOf: (Key) => Key | null
   getKeyPageAbove: (Key) => Key | null
   getKeyPageBelow: (Key) => Key | null
   getKeyRightOf: (Key) => Key | null
   getLastKey: () => Key | null
   getNextKey: (Key) => Key | null
+  getOrientation: () => Orientation
   getPreviousKey: (Key) => Key | null
 }

/@react-aria/selection:DOMLayoutDelegate

 DOMLayoutDelegate {
-  constructor: (RefObject<HTMLElement | null>) => void
+  constructor: (RefObject<HTMLElement | null>, Orientation) => void
   getContentSize: () => Size
   getItemRect: (Key) => Rect | null
+  getOrientation: () => Orientation | null
   getVisibleRect: () => Rect
 }

/@react-aria/selection:AriaSelectableListOptions

 AriaSelectableListOptions {
   allowsTabNavigation?: boolean
   autoFocus?: boolean | FocusStrategy = false
   collection: Collection<Node<unknown>>
   disabledKeys: Set<Key>
   disallowEmptySelection?: boolean = false
   disallowSelectAll?: boolean = false
   disallowTypeAhead?: boolean = false
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   isVirtualized?: boolean
   keyboardDelegate?: KeyboardDelegate
   layoutDelegate?: LayoutDelegate
   linkBehavior?: 'action' | 'selection' | 'override' = 'action'
+  orientation?: Orientation
   ref: RefObject<HTMLElement | null>
   scrollRef?: RefObject<HTMLElement | null>
   selectOnFocus?: boolean = false
   selectionManager: MultipleSelectionManager
   shouldUseVirtualFocus?: boolean
 }

@react-spectrum/card

/@react-spectrum/card:GalleryLayout

 GalleryLayout <T> {
   _distributeWidths: (Array<number>) => boolean
   _findClosest: (Rect, Rect) => LayoutInfo | null
   _findClosestLayoutInfo: (Rect, Rect) => LayoutInfo | null
   buildCollection: () => void
   collection: GridCollection<T>
   constructor: (GalleryLayoutOptions) => void
   direction: Direction
   disabledKeys: Set<Key>
   getContentSize: () => number
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getFirstKey: () => Node<T> | undefined
   getKeyAbove: (Key) => Node<T> | undefined
   getKeyBelow: (Key) => Node<T> | undefined
   getKeyForSearch: (string, Key) => Node<T> | undefined | null
   getKeyLeftOf: (Key) => Node<T> | undefined
   getKeyPageAbove: (Key) => Node<T> | undefined
   getKeyPageBelow: (Key) => Node<T> | undefined
   getKeyRightOf: (Key) => Node<T> | undefined
   getLastKey: () => Node<T> | undefined
   getLayoutInfo: (Key) => LayoutInfo
+  getOrientation: () => Orientation | null
   getVisibleLayoutInfos: (Rect, any) => Array<LayoutInfo>
   isLoading: boolean
   isVisible: (LayoutInfo, Rect, boolean) => boolean
   itemPadding: number
   margin: number
   scale: Scale
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (O, O) => boolean
   update: (InvalidationContext<CardViewLayoutOptions>) => void
   updateItemSize: (Key, Size) => boolean
   virtualizer: Virtualizer<{}, any> | null
 }

/@react-spectrum/card:GridLayout

 GridLayout <T> {
   _findClosest: (Rect, Rect) => LayoutInfo | null
   _findClosestLayoutInfo: (Rect, Rect) => LayoutInfo | null
   buildChild: (Node<T>, number, number) => LayoutInfo
   buildCollection: () => void
   cardOrientation: Orientation
   collection: GridCollection<T>
   constructor: (GridLayoutOptions) => void
   direction: Direction
   disabledKeys: Set<Key>
   getContentSize: () => number
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getFirstKey: () => Node<T> | undefined
   getIndexAtPoint: (number, number, any) => number
   getKeyAbove: (Key) => Node<T> | undefined | null
   getKeyBelow: (Key) => Node<T> | undefined | null
   getKeyForSearch: (string, Key) => Node<T> | undefined | null
   getKeyLeftOf: (Key) => Node<T> | undefined
   getKeyPageAbove: (Key) => Node<T> | undefined
   getKeyPageBelow: (Key) => Node<T> | undefined
   getKeyRightOf: (Key) => Node<T> | undefined
   getLastKey: () => Node<T> | undefined
   getLayoutInfo: (Key) => LayoutInfo
+  getOrientation: () => Orientation | null
   getVisibleLayoutInfos: (Rect, any) => Array<LayoutInfo>
   isLoading: boolean
   isVisible: (LayoutInfo, Rect, boolean) => boolean
   itemPadding: number
   margin: number
   scale: Scale
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (O, O) => boolean
   update: (InvalidationContext<CardViewLayoutOptions>) => void
   updateItemSize: (Key, Size) => boolean
   virtualizer: Virtualizer<{}, any> | null
 }

/@react-spectrum/card:WaterfallLayout

 WaterfallLayout <T> {
   _findClosest: (Rect, Rect) => LayoutInfo | null
   _findClosestLayoutInfo: (Rect, Rect) => LayoutInfo | null
   buildCollection: (InvalidationContext) => void
   collection: GridCollection<T>
   constructor: (WaterfallLayoutOptions) => void
   direction: Direction
   disabledKeys: Set<Key>
   getClosestLeft: (Key) => Node<T> | undefined
   getClosestRight: (Key) => Node<T> | undefined
   getContentSize: () => number
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getFirstKey: () => Node<T> | undefined
   getKeyAbove: (Key) => Node<T> | undefined
   getKeyBelow: (Key) => Node<T> | undefined
   getKeyForSearch: (string, Key) => Node<T> | undefined | null
   getKeyLeftOf: (Key) => Node<T> | undefined
   getKeyPageAbove: (Key) => Node<T> | undefined
   getKeyPageBelow: (Key) => Node<T> | undefined
   getKeyRightOf: (Key) => Node<T> | undefined
   getLastKey: () => Node<T> | undefined
   getLayoutInfo: (Key) => LayoutInfo
   getNextColumnIndex: (Array<number>) => number
+  getOrientation: () => Orientation | null
   getVisibleLayoutInfos: (Rect, any) => Array<LayoutInfo>
   isLoading: boolean
   isVisible: (LayoutInfo, Rect, boolean) => boolean
   layoutType: string
   scale: Scale
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (O, O) => boolean
   update: (InvalidationContext<CardViewLayoutOptions>) => void
   updateItemSize: (Key, Size) => number
   virtualizer: Virtualizer<{}, any> | null
 }

@react-spectrum/image

/@react-spectrum/image:Image

 Image {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'>
   alt?: string
   bottom?: Responsive<DimensionValue>
-  crossOrigin?: 'anonymous' | 'use-credentials'
   end?: Responsive<DimensionValue>
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: 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>
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
   left?: Responsive<DimensionValue>
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginStart?: Responsive<DimensionValue>
   marginTop?: Responsive<DimensionValue>
   marginX?: Responsive<DimensionValue>
   marginY?: Responsive<DimensionValue>
   maxHeight?: Responsive<DimensionValue>
   maxWidth?: Responsive<DimensionValue>
   minHeight?: Responsive<DimensionValue>
   minWidth?: Responsive<DimensionValue>
   objectFit?: any
   onError?: ReactEventHandler<HTMLImageElement>
   onLoad?: ReactEventHandler<HTMLImageElement>
   order?: Responsive<number>
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   right?: Responsive<DimensionValue>
   slot?: string = 'image'
   src: string
   start?: Responsive<DimensionValue>
   top?: Responsive<DimensionValue>
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

/@react-spectrum/image:SpectrumImageProps

 SpectrumImageProps {
   UNSAFE_className?: string
   UNSAFE_style?: CSSProperties
   alignSelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'center' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'stretch'>
   alt?: string
   bottom?: Responsive<DimensionValue>
-  crossOrigin?: 'anonymous' | 'use-credentials'
   end?: Responsive<DimensionValue>
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: 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>
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
   left?: Responsive<DimensionValue>
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginStart?: Responsive<DimensionValue>
   marginTop?: Responsive<DimensionValue>
   marginX?: Responsive<DimensionValue>
   marginY?: Responsive<DimensionValue>
   maxHeight?: Responsive<DimensionValue>
   maxWidth?: Responsive<DimensionValue>
   minHeight?: Responsive<DimensionValue>
   minWidth?: Responsive<DimensionValue>
   objectFit?: any
   onError?: ReactEventHandler<HTMLImageElement>
   onLoad?: ReactEventHandler<HTMLImageElement>
   order?: Responsive<number>
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   right?: Responsive<DimensionValue>
   slot?: string = 'image'
   src: string
   start?: Responsive<DimensionValue>
   top?: Responsive<DimensionValue>
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

@react-spectrum/listbox

/@react-spectrum/listbox:ListBoxBase

 ListBoxBase <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
   autoFocus?: boolean | FocusStrategy
   bottom?: Responsive<DimensionValue>
   defaultSelectedKeys?: 'all' | Iterable<Key>
   disabledKeys?: Iterable<Key>
   disallowEmptySelection?: boolean
   domProps?: HTMLAttributes<HTMLElement>
   end?: Responsive<DimensionValue>
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   flex?: Responsive<string | number | boolean>
   flexBasis?: Responsive<number | string>
   flexGrow?: Responsive<number>
   flexShrink?: Responsive<number>
   focusOnPointerEnter?: boolean
   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>
   isLoading?: boolean
   isVirtualized?: boolean
   items?: Iterable<{}>
   justifySelf?: Responsive<'auto' | 'normal' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'self-start' | 'self-end' | 'center' | 'left' | 'right' | 'stretch'>
   keyboardDelegate?: KeyboardDelegate
   label?: ReactNode
   layout: ListBoxLayout<{}>
   layoutDelegate?: LayoutDelegate
   left?: Responsive<DimensionValue>
   linkBehavior?: 'action' | 'selection' | 'override' = 'override'
   margin?: Responsive<DimensionValue>
   marginBottom?: Responsive<DimensionValue>
   marginEnd?: Responsive<DimensionValue>
   marginStart?: 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
   onBlur?: (FocusEvent<Target>) => void
   onFocus?: (FocusEvent<Target>) => void
   onFocusChange?: (boolean) => void
   onLoadMore?: () => void
   onScroll?: () => void
   onSelectionChange?: (Selection) => void
   order?: Responsive<number>
+  orientation?: Orientation
   position?: Responsive<'static' | 'relative' | 'absolute' | 'fixed' | 'sticky'>
   renderEmptyState?: () => ReactNode
   right?: Responsive<DimensionValue>
   selectedKeys?: 'all' | Iterable<Key>
   selectionMode?: SelectionMode
   shouldFocusOnHover?: boolean
   shouldFocusWrap?: boolean
   shouldSelectOnPressUp?: boolean
   shouldUseVirtualFocus?: boolean
   showLoadingSpinner?: boolean
   start?: Responsive<DimensionValue>
   state: ListState<{}>
   top?: Responsive<DimensionValue>
   width?: Responsive<DimensionValue>
   zIndex?: Responsive<number>
 }

@react-spectrum/s2

/@react-spectrum/s2:CardView

 CardView <T extends {}> {
   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
   defaultSelectedKeys?: 'all' | Iterable<Key>
   density?: 'compact' | 'regular' | 'spacious' = 'regular'
   dependencies?: ReadonlyArray<any>
   disabledBehavior?: DisabledBehavior = "all"
   disabledKeys?: Iterable<Key>
   disallowEmptySelection?: boolean
   disallowTypeAhead?: boolean = false
   dragAndDropHooks?: DragAndDropHooks
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   id?: string
   items?: Iterable<T>
   layout?: 'grid' | 'waterfall' = 'grid'
   loadingState?: LoadingState
   onAction?: (Key) => void
   onLoadMore?: () => void
   onSelectionChange?: (Selection) => void
+  orientation?: Orientation = 'vertical'
   renderActionBar?: ('all' | Set<Key>) => ReactElement
   renderEmptyState?: (GridListRenderProps) => ReactNode
   selectedKeys?: 'all' | Iterable<Key>
   selectionMode?: SelectionMode
   shouldSelectOnPressUp?: boolean
   size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
   slot?: string | null
   styles?: StylesPropWithHeight
   variant?: 'primary' | 'secondary' | 'tertiary' | 'quiet' = 'primary'
 }

/@react-spectrum/s2:CardViewProps

 CardViewProps <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
   defaultSelectedKeys?: 'all' | Iterable<Key>
   density?: 'compact' | 'regular' | 'spacious' = 'regular'
   dependencies?: ReadonlyArray<any>
   disabledBehavior?: DisabledBehavior = "all"
   disabledKeys?: Iterable<Key>
   disallowEmptySelection?: boolean
   disallowTypeAhead?: boolean = false
   dragAndDropHooks?: DragAndDropHooks
   escapeKeyBehavior?: 'clearSelection' | 'none' = 'clearSelection'
   id?: string
   items?: Iterable<T>
   layout?: 'grid' | 'waterfall' = 'grid'
   loadingState?: LoadingState
   onAction?: (Key) => void
   onLoadMore?: () => void
   onSelectionChange?: (Selection) => void
+  orientation?: Orientation = 'vertical'
   renderActionBar?: ('all' | Set<Key>) => ReactElement
   renderEmptyState?: (GridListRenderProps) => ReactNode
   selectedKeys?: 'all' | Iterable<Key>
   selectionMode?: SelectionMode
   shouldSelectOnPressUp?: boolean
   size?: 'XS' | 'S' | 'M' | 'L' | 'XL' = 'M'
   slot?: string | null
   styles?: StylesPropWithHeight
   variant?: 'primary' | 'secondary' | 'tertiary' | 'quiet' = 'primary'
 }

@react-stately/layout

/@react-stately/layout:ListLayoutOptions

 ListLayoutOptions {
   dropIndicatorThickness?: number = 2
   estimatedHeadingHeight?: number
   estimatedRowHeight?: number
   gap?: number = 0
   headingHeight?: number = 48
   loaderHeight?: number = 48
+  orientation?: Orientation = 'vertical'
   padding?: number = 0
   rowHeight?: number = 48
 }

/@react-stately/layout:TableLayoutProps

 TableLayoutProps {
   columnWidths?: Map<Key, number>
   dropIndicatorThickness?: number = 2
   estimatedHeadingHeight?: number
   estimatedRowHeight?: number
   gap?: number = 0
   headingHeight?: number = 48
   loaderHeight?: number = 48
+  orientation?: Orientation = 'vertical'
   padding?: number = 0
   rowHeight?: number = 48
 }

/@react-stately/layout:GridLayout

 GridLayout <O extends GridLayoutOptions = GridLayoutOptions, T> {
+  constructor: (LayoutOptions) => void
   getContentSize: () => Size
   getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getLayoutInfo: (Key) => LayoutInfo | null
+  getOrientation: () => Orientation | null
   getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (GridLayoutOptions, GridLayoutOptions) => boolean
   update: (InvalidationContext<GridLayoutOptions>) => void
   virtualizer: Virtualizer<{}, any> | null
 }

/@react-stately/layout:ListLayout

 ListLayout <O extends ListLayoutOptions = ListLayoutOptions, T> {
   constructor: (ListLayoutOptions) => void
   getContentSize: () => Size
   getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget | null
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getLayoutInfo: (Key) => LayoutInfo | null
+  getOrientation: () => Orientation | null
   getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (ListLayoutOptions, ListLayoutOptions) => boolean
   update: (InvalidationContext<ListLayoutOptions>) => void
   virtualizer: Virtualizer<{}, any> | null
 }

/@react-stately/layout:TableLayout

 TableLayout <O extends TableLayoutProps = TableLayoutProps, T> {
   constructor: (ListLayoutOptions) => void
   getContentSize: () => Size
   getDropTargetFromPoint: (number, number, (DropTarget) => boolean) => DropTarget | null
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getLayoutInfo: (Key) => LayoutInfo | null
+  getOrientation: () => Orientation | null
   getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (TableLayoutProps, TableLayoutProps) => boolean
   update: (InvalidationContext<TableLayoutProps>) => void
   virtualizer: Virtualizer<{}, any> | null
 }

/@react-stately/layout:WaterfallLayout

 WaterfallLayout <O extends WaterfallLayoutOptions = WaterfallLayoutOptions, T extends {}> {
+  constructor: (LayoutOptions) => void
   getContentSize: () => Size
   getDropTargetFromPoint: (number, number) => DropTarget
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getKeyLeftOf: (Key) => Key | null
   getKeyRange: (Key, Key) => Array<Key>
   getKeyRightOf: (Key) => Key | null
   getLayoutInfo: (Key) => LayoutInfo
+  getOrientation: () => Orientation | null
   getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (WaterfallLayoutOptions, WaterfallLayoutOptions) => boolean
   update: (InvalidationContext<WaterfallLayoutOptions>) => void
   virtualizer: Virtualizer<{}, any> | null
 }

@react-stately/virtualizer

/@react-stately/virtualizer:Layout

 Layout <O = any, T extends {} = Node<any>> {
+  constructor: (LayoutOptions) => void
   getContentSize: () => Size
   getDropTargetLayoutInfo: (ItemDropTarget) => LayoutInfo
   getLayoutInfo: (Key) => LayoutInfo | null
+  getOrientation: () => Orientation | null
   getVisibleLayoutInfos: (Rect) => Array<LayoutInfo>
   shouldInvalidate: (Rect, Rect) => boolean
   shouldInvalidateLayoutOptions: (O, O) => boolean
   update: (InvalidationContext<O>) => void
   virtualizer: Virtualizer<{}, any> | null
 }

@nwidynski
Copy link
Contributor

@LFDanLu Thanks 🙏 As I thought, it's a bug for dev-only #8548

@LFDanLu
Copy link
Member Author

LFDanLu commented Jul 15, 2025

sound good, I'll close this for now then

@LFDanLu LFDanLu closed this Jul 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants