-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Feat: Add support for horizontal orientation
to GridList
& ListBox
#8533
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
base: main
Are you sure you want to change the base?
Changes from all commits
b07954a
ef61fa4
36ad8c4
bc57b0c
e92c7db
58ad7a2
22ddea9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ | |
*/ | ||
|
||
import {AriaListBoxProps} from '@react-types/listbox'; | ||
import {DOMAttributes, KeyboardDelegate, LayoutDelegate, RefObject} from '@react-types/shared'; | ||
import {DOMAttributes, KeyboardDelegate, LayoutDelegate, Orientation, RefObject} from '@react-types/shared'; | ||
import {filterDOMProps, mergeProps, useId} from '@react-aria/utils'; | ||
import {listData} from './utils'; | ||
import {ListState} from '@react-stately/list'; | ||
|
@@ -55,7 +55,12 @@ export interface AriaListBoxOptions<T> extends Omit<AriaListBoxProps<T>, 'childr | |
* - 'override': links override all other interactions (link items are not selectable). | ||
* @default 'override' | ||
*/ | ||
linkBehavior?: 'action' | 'selection' | 'override' | ||
linkBehavior?: 'action' | 'selection' | 'override', | ||
|
||
/** | ||
* The orientation of the listbox. | ||
*/ | ||
orientation?: Orientation | ||
} | ||
|
||
/** | ||
|
@@ -68,6 +73,7 @@ export function useListBox<T>(props: AriaListBoxOptions<T>, state: ListState<T>, | |
let domProps = filterDOMProps(props, {labelable: true}); | ||
// Use props instead of state here. We don't want this to change due to long press. | ||
let selectionBehavior = props.selectionBehavior || 'toggle'; | ||
let orientation = props.orientation || props.keyboardDelegate?.getOrientation?.(); | ||
let linkBehavior = props.linkBehavior || (selectionBehavior === 'replace' ? 'action' : 'override'); | ||
if (selectionBehavior === 'toggle' && linkBehavior === 'action') { | ||
// linkBehavior="action" does not work with selectionBehavior="toggle" because there is no way | ||
|
@@ -117,6 +123,7 @@ export function useListBox<T>(props: AriaListBoxOptions<T>, state: ListState<T>, | |
'aria-multiselectable': 'true' | ||
} : {}, { | ||
role: 'listbox', | ||
'aria-orientation': orientation === 'horizontal' ? orientation : undefined, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @majornista Should we set |
||
...mergeProps(fieldProps, listProps) | ||
}) | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,13 +11,39 @@ | |
*/ | ||
|
||
import {getItemElement} from './utils'; | ||
import {Key, LayoutDelegate, Rect, RefObject, Size} from '@react-types/shared'; | ||
import {Key, LayoutDelegate, Orientation, Rect, RefObject, Size} from '@react-types/shared'; | ||
|
||
export class DOMLayoutDelegate implements LayoutDelegate { | ||
private ref: RefObject<HTMLElement | null>; | ||
private orientation?: Orientation; | ||
|
||
constructor(ref: RefObject<HTMLElement | null>) { | ||
constructor(ref: RefObject<HTMLElement | null>, orientation?: Orientation) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not entirely happy with having to pass this here, but I couldn't think of any reliable alternative. I guess we could do something similar to the drop target delegate and place this information in a data attribute, but is this really preferable? |
||
this.ref = ref; | ||
this.orientation = orientation; | ||
} | ||
|
||
getOrientation(): Orientation | null { | ||
let container = this.ref.current; | ||
if (this.orientation) { | ||
return this.orientation; | ||
} | ||
|
||
// https://w3c.github.io/aria/#aria-orientation | ||
switch (container?.role) { | ||
case 'menubar': | ||
case 'slider': | ||
case 'separator': | ||
case 'tablist': | ||
case 'toolbar': | ||
return 'horizontal'; | ||
case 'listbox': | ||
case 'menu': | ||
case 'scrollbar': | ||
case 'tree': | ||
return 'vertical'; | ||
default: | ||
return null; | ||
} | ||
} | ||
|
||
getItemRect(key: Key): Rect | null { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should explicitly set
orientation
whenever known to avoid queries to theDOMLayoutDelegate
internally.