Skip to content
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

Support links in collection components #4993

Merged
merged 22 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c67562c
Improve behavior of usePress with HTML links
Jun 23, 2023
c538bb6
Merge branch 'main' of github.com:adobe/react-spectrum into links
devongovett Jul 27, 2023
90e570c
support links in collections
devongovett Jul 28, 2023
41bbbbb
Add link support to spectrum components
devongovett Jul 31, 2023
94e687b
Merge branch 'main' of github.com:adobe/react-spectrum into links
devongovett Aug 1, 2023
8df7a16
Some cleanups
devongovett Aug 2, 2023
8ccd8d0
Add some tests
devongovett Aug 2, 2023
1f5efa8
Merge branch 'main' of github.com:adobe/react-spectrum into links
devongovett Aug 24, 2023
57000e7
Merge branch 'main' of github.com:adobe/react-spectrum into links
devongovett Aug 28, 2023
1ba8caf
Merge branch 'main' of github.com:adobe/react-spectrum into links
devongovett Aug 28, 2023
95b97e3
Merge branch 'main' of github.com:adobe/react-spectrum into links
devongovett Aug 29, 2023
ed2207a
Add linkBehavior option and update tests
devongovett Aug 30, 2023
77c9d45
Fix react 16
devongovett Aug 30, 2023
4e6aef8
remove outdated comment, fix types
devongovett Aug 30, 2023
78405a8
Merge branch 'main' into links
LFDanLu Sep 6, 2023
d664869
Merge branch 'main' of github.com:adobe/react-spectrum into links
devongovett Sep 13, 2023
087f1bf
Fix ListView story
devongovett Sep 13, 2023
ca4e5eb
Update tests for user-event changes
devongovett Sep 13, 2023
f817cb1
Fix tests and package lint
devongovett Sep 13, 2023
283c023
Fix more tests
devongovett Sep 13, 2023
68e90fd
review updates
devongovett Sep 13, 2023
20c72ce
Merge branch 'main' into links
devongovett Sep 14, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/@adobe/spectrum-css-temp/components/menu/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ governing permissions and limitations under the License.
.spectrum-Menu-item {
cursor: default;
position: relative;
display: block;

box-sizing: border-box;

Expand All @@ -89,10 +90,18 @@ governing permissions and limitations under the License.
font-style: normal;
text-decoration: none;

&[href] {
cursor: pointer;
}

&:focus {
outline: none;
}

&.is-disabled {
cursor: default;
}

&.is-selected {
.spectrum-Menu-checkmark {
display: block;
Expand Down
9 changes: 4 additions & 5 deletions packages/@adobe/spectrum-css-temp/components/tabs/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ governing permissions and limitations under the License.
cursor: default;
outline: none;

&[href] {
cursor: pointer;
}

&.is-disabled {
cursor: default;

.spectrum-Tabs-itemLabel {
cursor: default;
}
}

.spectrum-Icon {
Expand Down Expand Up @@ -107,7 +107,6 @@ governing permissions and limitations under the License.
}

.spectrum-Tabs-itemLabel {
cursor: default;
vertical-align: top;
display: inline-block;

Expand Down
7 changes: 6 additions & 1 deletion packages/@adobe/spectrum-css-temp/components/tags/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ governing permissions and limitations under the License.
align-items: center;
box-sizing: border-box;
position: relative;
cursor: default;

margin: var(--spectrum-tag-margin);
padding-inline-start: calc(var(--spectrum-tag-padding-x) - var(--spectrum-tag-border-size));
Expand All @@ -65,7 +66,12 @@ governing permissions and limitations under the License.
box-shadow var(--spectrum-global-animation-duration-100) ease-in-out,
background-color var(--spectrum-global-animation-duration-100) ease-in-out;

&[data-href] {
cursor: pointer;
}

&.is-disabled {
cursor: default;
pointer-events: none;
}

Expand Down Expand Up @@ -100,7 +106,6 @@ governing permissions and limitations under the License.
margin-inline-end: var(--spectrum-tag-padding-x);
flex: 1 1 auto;
font-size: var(--spectrum-tag-text-size);
cursor: default;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
Expand Down
21 changes: 18 additions & 3 deletions packages/@react-aria/combobox/src/useComboBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {AriaComboBoxProps} from '@react-types/combobox';
import {ariaHideOutside} from '@react-aria/overlays';
import {AriaListBoxOptions, getItemId, listData} from '@react-aria/listbox';
import {BaseEvent, DOMAttributes, KeyboardDelegate, PressEvent} from '@react-types/shared';
import {chain, isAppleDevice, mergeProps, useLabels} from '@react-aria/utils';
import {chain, isAppleDevice, mergeProps, useLabels, useRouter} from '@react-aria/utils';
import {ComboBoxState} from '@react-stately/combobox';
import {FocusEvent, InputHTMLAttributes, KeyboardEvent, RefObject, TouchEvent, useEffect, useMemo, useRef} from 'react';
import {getChildNodes, getItemCount} from '@react-stately/collections';
Expand Down Expand Up @@ -106,6 +106,8 @@ export function useComboBox<T>(props: AriaComboBoxOptions<T>, state: ComboBoxSta
isVirtualized: true
});

let router = useRouter();

// For textfield specific keydown operations
let onKeyDown = (e: BaseEvent<KeyboardEvent<any>>) => {
switch (e.key) {
Expand All @@ -116,7 +118,19 @@ export function useComboBox<T>(props: AriaComboBoxOptions<T>, state: ComboBoxSta
e.preventDefault();
}

state.commit();
// If the focused item is a link, trigger opening it. Items that are links are not selectable.
if (state.isOpen && state.selectionManager.focusedKey != null && state.selectionManager.isLink(state.selectionManager.focusedKey)) {
if (e.key === 'Enter') {
let item = listBoxRef.current.querySelector(`[data-key="${state.selectionManager.focusedKey}"]`);
if (item instanceof HTMLAnchorElement) {
router.open(item, e);
}
}

state.close();
} else {
state.commit();
}
break;
case 'Escape':
if (
Expand Down Expand Up @@ -330,7 +344,8 @@ export function useComboBox<T>(props: AriaComboBoxOptions<T>, state: ComboBoxSta
autoFocus: state.focusStrategy,
shouldUseVirtualFocus: true,
shouldSelectOnPressUp: true,
shouldFocusOnHover: true
shouldFocusOnHover: true,
linkBehavior: 'selection' as const
}),
descriptionProps,
errorMessageProps
Expand Down
18 changes: 14 additions & 4 deletions packages/@react-aria/gridlist/src/useGridList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,15 @@ export interface AriaGridListOptions<T> extends Omit<AriaGridListProps<T>, 'chil
* Whether focus should wrap around when the end/start is reached.
* @default false
*/
shouldFocusWrap?: boolean
shouldFocusWrap?: boolean,
/**
* The behavior of links in the collection.
* - 'action': link behaves like onAction.
* - 'selection': link follows selection interactions (e.g. if URL drives selection).
* - 'override': links override all other interactions (link items are not selectable).
* @default 'action'
*/
linkBehavior?: 'action' | 'selection' | 'override'
}

export interface GridListAria {
Expand All @@ -70,7 +78,8 @@ export function useGridList<T>(props: AriaGridListOptions<T>, state: ListState<T
let {
isVirtualized,
keyboardDelegate,
onAction
onAction,
linkBehavior = 'action'
} = props;

if (!props['aria-label'] && !props['aria-labelledby']) {
Expand All @@ -85,11 +94,12 @@ export function useGridList<T>(props: AriaGridListOptions<T>, state: ListState<T
keyboardDelegate: keyboardDelegate,
isVirtualized,
selectOnFocus: state.selectionManager.selectionBehavior === 'replace',
shouldFocusWrap: props.shouldFocusWrap
shouldFocusWrap: props.shouldFocusWrap,
linkBehavior
});

let id = useId(props.id);
listMap.set(state, {id, onAction});
listMap.set(state, {id, onAction, linkBehavior});

let descriptionProps = useHighlightSelectionDescription({
selectionManager: state.selectionManager,
Expand Down
10 changes: 6 additions & 4 deletions packages/@react-aria/gridlist/src/useGridListItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import {DOMAttributes, FocusableElement, Node as RSNode} from '@react-types/shared';
import {focusSafely, getFocusableTreeWalker} from '@react-aria/focus';
import {getRowId, listMap} from './utils';
import {getScrollParent, mergeProps, scrollIntoViewport, useSlotId} from '@react-aria/utils';
import {getScrollParent, getSyntheticLinkProps, mergeProps, scrollIntoViewport, useSlotId} from '@react-aria/utils';
import {isFocusVisible} from '@react-aria/interactions';
import type {ListState} from '@react-stately/list';
import {KeyboardEvent as ReactKeyboardEvent, RefObject, useRef} from 'react';
Expand Down Expand Up @@ -53,7 +53,7 @@ export function useGridListItem<T>(props: AriaGridListItemOptions, state: ListSt
} = props;

let {direction} = useLocale();
let {onAction} = listMap.get(state);
let {onAction, linkBehavior} = listMap.get(state);
let descriptionId = useSlotId();

// We need to track the key of the item at the time it was last focused so that we force
Expand All @@ -77,7 +77,8 @@ export function useGridListItem<T>(props: AriaGridListItemOptions, state: ListSt
isVirtualized,
shouldSelectOnPressUp,
onAction: onAction ? () => onAction(node.key) : undefined,
focus
focus,
linkBehavior
});

let onKeyDown = (e: ReactKeyboardEvent) => {
Expand Down Expand Up @@ -177,7 +178,8 @@ export function useGridListItem<T>(props: AriaGridListItemOptions, state: ListSt
}
};

let rowProps: DOMAttributes = mergeProps(itemProps, {
let linkProps = getSyntheticLinkProps(node.props);
let rowProps: DOMAttributes = mergeProps(itemProps, linkProps, {
role: 'row',
onKeyDownCapture: onKeyDown,
onFocus,
Expand Down
3 changes: 2 additions & 1 deletion packages/@react-aria/gridlist/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import type {ListState} from '@react-stately/list';

interface ListMapShared {
id: string,
onAction: (key: Key) => void
onAction: (key: Key) => void,
linkBehavior?: 'action' | 'selection' | 'override'
}

// Used to share:
Expand Down
Loading