Skip to content

Conversation

@devongovett
Copy link
Member

Tons of small fixes and polish items. See commits.

Even if they are rendered as links
Also Switch disabled state color
Improves drag and drop experience
Caused nothing to be selected sometimes (e.g. Calendar)
We've wrapped all of this behavior into the [useHover](../useHover) hook in React Aria. It provides a simple way to determine if an element is hovered, and exposes a set of events that you can handle as well. `onHoverStart` is fired when the user hovers over an element with a mouse, and `onHoverEnd` is fired when the user moves their mouse off of the element. We take care of all of the browser inconsistencies discussed above, and also include fallbacks for touch and mouse events to support older devices without pointer events.

The [Button](../../s2/Button) component, and all other components in React Spectrum that support hover states, use the [useHover](../useHover) hook to handle interactions, and apply a CSS class when they are hovered. This ensures that hover states are only applied when interacting with a mouse, which avoids unexpected behavior on touch devices.
The [Button](s2:Button) component, and all other components in React Spectrum that support hover states, use the [useHover](../useHover) hook to handle interactions, and apply a CSS class when they are hovered. This ensures that hover states are only applied when interacting with a mouse, which avoids unexpected behavior on touch devices.
Copy link
Member Author

Choose a reason for hiding this comment

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

These s2: and react-aria: links will resolve to the proper base-url (which depends on the environment).

@rspbot
Copy link

rspbot commented Dec 3, 2025

@rspbot
Copy link

rspbot commented Dec 3, 2025

## API Changes

react-aria-components

/react-aria-components:useListData

+useListData <T> {
+  options: ListOptions<T>
+  returnVal: undefined
+}

/react-aria-components:useTreeData

+useTreeData <T extends {}> {
+  options: TreeOptions<T>
+  returnVal: undefined
+}

/react-aria-components:useAsyncList

+useAsyncList <C = string, T> {
+  options: AsyncListOptions<T, C>
+  returnVal: undefined
+}

/react-aria-components:ListData

+ListData <T> {
+  addKeysToSelection: (Selection) => void
+  append: (Array<T>) => void
+  filterText: string
+  getItem: (Key) => T | undefined
+  insert: (number, Array<T>) => void
+  insertAfter: (Key, Array<T>) => void
+  insertBefore: (Key, Array<T>) => void
+  items: Array<T>
+  move: (Key, number) => void
+  moveAfter: (Key, Iterable<Key>) => void
+  moveBefore: (Key, Iterable<Key>) => void
+  prepend: (Array<T>) => void
+  remove: (Array<Key>) => void
+  removeKeysFromSelection: (Selection) => void
+  removeSelectedItems: () => void
+  selectedKeys: Selection
+  setFilterText: (string) => void
+  setSelectedKeys: (Selection) => void
+  update: (Key, T | (T) => T) => void
+}

/react-aria-components:TreeData

+TreeData <T extends {}> {
+  append: (Key | null, Array<{}>) => void
+  getItem: (Key) => TreeNode<{}> | undefined
+  insert: (Key | null, number, Array<{}>) => void
+  insertAfter: (Key, Array<{}>) => void
+  insertBefore: (Key, Array<{}>) => void
+  items: Array<TreeNode<{}>>
+  move: (Key, Key | null, number) => void
+  moveAfter: (Key, Iterable<Key>) => void
+  moveBefore: (Key, Iterable<Key>) => void
+  prepend: (Key | null, Array<{}>) => void
+  remove: (Array<Key>) => void
+  removeSelectedItems: () => void
+  selectedKeys: Set<Key>
+  setSelectedKeys: (Set<Key>) => void
+  update: (Key, {}) => void
+}

/react-aria-components:AsyncListData

+AsyncListData <T> {
+  addKeysToSelection: (Selection) => void
+  append: (Array<T>) => void
+  error?: Error
+  filterText: string
+  getItem: (Key) => T | undefined
+  insert: (number, Array<T>) => void
+  insertAfter: (Key, Array<T>) => void
+  insertBefore: (Key, Array<T>) => void
+  isLoading: boolean
+  items: Array<T>
+  loadMore: () => void
+  loadingState: LoadingState
+  move: (Key, number) => void
+  moveAfter: (Key, Iterable<Key>) => void
+  moveBefore: (Key, Iterable<Key>) => void
+  prepend: (Array<T>) => void
+  reload: () => void
+  remove: (Array<Key>) => void
+  removeKeysFromSelection: (Selection) => void
+  removeSelectedItems: () => void
+  selectedKeys: Selection
+  setFilterText: (string) => void
+  setSelectedKeys: (Selection) => void
+  sort: (SortDescriptor) => void
+  sortDescriptor?: SortDescriptor
+  update: (Key, T | (T) => T) => void
+}

@react-aria/interactions

/@react-aria/interactions:getPointerType

+getPointerType {
+  returnVal: undefined
+}

@react-spectrum/s2

/@react-spectrum/s2:useLocale

+useLocale {
+  returnVal: undefined
+}

/@react-spectrum/s2:useListData

+useListData <T> {
+  options: ListOptions<T>
+  returnVal: undefined
+}

/@react-spectrum/s2:useTreeData

+useTreeData <T extends {}> {
+  options: TreeOptions<T>
+  returnVal: undefined
+}

/@react-spectrum/s2:useAsyncList

+useAsyncList <C = string, T> {
+  options: AsyncListOptions<T, C>
+  returnVal: undefined
+}

/@react-spectrum/s2:ListData

+ListData <T> {
+  addKeysToSelection: (Selection) => void
+  append: (Array<T>) => void
+  filterText: string
+  getItem: (Key) => T | undefined
+  insert: (number, Array<T>) => void
+  insertAfter: (Key, Array<T>) => void
+  insertBefore: (Key, Array<T>) => void
+  items: Array<T>
+  move: (Key, number) => void
+  moveAfter: (Key, Iterable<Key>) => void
+  moveBefore: (Key, Iterable<Key>) => void
+  prepend: (Array<T>) => void
+  remove: (Array<Key>) => void
+  removeKeysFromSelection: (Selection) => void
+  removeSelectedItems: () => void
+  selectedKeys: Selection
+  setFilterText: (string) => void
+  setSelectedKeys: (Selection) => void
+  update: (Key, T | (T) => T) => void
+}

/@react-spectrum/s2:TreeData

+TreeData <T extends {}> {
+  append: (Key | null, Array<{}>) => void
+  getItem: (Key) => TreeNode<{}> | undefined
+  insert: (Key | null, number, Array<{}>) => void
+  insertAfter: (Key, Array<{}>) => void
+  insertBefore: (Key, Array<{}>) => void
+  items: Array<TreeNode<{}>>
+  move: (Key, Key | null, number) => void
+  moveAfter: (Key, Iterable<Key>) => void
+  moveBefore: (Key, Iterable<Key>) => void
+  prepend: (Key | null, Array<{}>) => void
+  remove: (Array<Key>) => void
+  removeSelectedItems: () => void
+  selectedKeys: Set<Key>
+  setSelectedKeys: (Set<Key>) => void
+  update: (Key, {}) => void
+}

/@react-spectrum/s2:AsyncListData

+AsyncListData <T> {
+  addKeysToSelection: (Selection) => void
+  append: (Array<T>) => void
+  error?: Error
+  filterText: string
+  getItem: (Key) => T | undefined
+  insert: (number, Array<T>) => void
+  insertAfter: (Key, Array<T>) => void
+  insertBefore: (Key, Array<T>) => void
+  isLoading: boolean
+  items: Array<T>
+  loadMore: () => void
+  loadingState: LoadingState
+  move: (Key, number) => void
+  moveAfter: (Key, Iterable<Key>) => void
+  moveBefore: (Key, Iterable<Key>) => void
+  prepend: (Array<T>) => void
+  reload: () => void
+  remove: (Array<Key>) => void
+  removeKeysFromSelection: (Selection) => void
+  removeSelectedItems: () => void
+  selectedKeys: Selection
+  setFilterText: (string) => void
+  setSelectedKeys: (Selection) => void
+  sort: (SortDescriptor) => void
+  sortDescriptor?: SortDescriptor
+  update: (Key, T | (T) => T) => void
+}

})}>
<Button
{...props}
ref={buttonRef}
Copy link
Member

Choose a reason for hiding this comment

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

Not sure when this broke, but we had something where if the fake button was focused and you pressed a character key, that character would get added to the search field input value.

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.

5 participants