Skip to content

Conversation

devongovett
Copy link
Member

@devongovett devongovett commented Sep 17, 2025

This generalizes the animation code from S2 Tabs and SegmentedControl into a reusable SelectionIndicator component. This is rendered within a selectable item, and only mounts when that item is selected. When the selection changes, we store a snapshot of the previous item's rectangle and style attributes, and the new item animates from this state to its current state. This supports any CSS property listed in transition-property.

SelectionIndicator is actually a shorthand for an even more general pattern called a SharedElementTransition. This creates a scope within which one or more SharedElement components can be rendered, each with a unique name. When a SharedElement moves to a different parent within the same scope, it is automatically animated. SharedElement also supports enter and exit transitions when the first instance mounts or the last instance unmounts.

@rspbot
Copy link

rspbot commented Sep 17, 2025

}
```

### Animation
Copy link
Member Author

Choose a reason for hiding this comment

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

Wasn't quite sure where to document this. For Tabs I just built the animation into the starter kits so it is present in all the examples. For ToggleButtonGroup, it doesn't really make sense for multi-selection, so not sure if it should be in the starter. So I created a separate example here to show it. Thoughts?

Copy link
Member

Choose a reason for hiding this comment

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

For posterity, we discussed this as team and figured that we'd have a single example in the Selection page and then link to it in other pages like Tree. This example will stay as is since this seems like a more common use case for this kind of animation.

Copy link
Member

@snowystinger snowystinger left a comment

Choose a reason for hiding this comment

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

Haha, the animation for changing the orientation of Tabs in s2 is pretty amusing

Include for Radios? they only have single selection as well, and i could see someone building a segmented control equivalent with that instead, or those carousel controls since they nicely change selection on focus.

border-inline-end: 1px solid gray;

.react-aria-Tab {
.react-aria-SelectionIndicator {
Copy link
Member

Choose a reason for hiding this comment

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

move this css farther up the page?

LFDanLu
LFDanLu previously approved these changes Sep 19, 2025
}
```

### Animation
Copy link
Member

Choose a reason for hiding this comment

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

For posterity, we discussed this as team and figured that we'd have a single example in the Selection page and then link to it in other pages like Tree. This example will stay as is since this seems like a more common use case for this kind of animation.

snowystinger
snowystinger previously approved these changes Sep 22, 2025
@devongovett devongovett dismissed stale reviews from snowystinger and LFDanLu via 80b9c16 September 22, 2025 19:01
@rspbot
Copy link

rspbot commented Sep 22, 2025

@rspbot
Copy link

rspbot commented Sep 22, 2025

## API Changes

react-aria-components

/react-aria-components:SelectionIndicator

+SelectionIndicator {
+  children?: ChildrenOrFunction<SharedElementRenderProps>
+  className?: ClassNameOrFunction<SharedElementRenderProps>
+  isSelected?: boolean
+  style?: StyleOrFunction<SharedElementRenderProps>
+}

/react-aria-components:SelectionIndicatorContext

+SelectionIndicatorContext {
+  UNTYPED
+}

/react-aria-components:SharedElementTransition

+SharedElementTransition {
+  children: ReactNode
+}

/react-aria-components:SharedElement

+SharedElement {
+  children?: ChildrenOrFunction<SharedElementRenderProps>
+  className?: ClassNameOrFunction<SharedElementRenderProps>
+  isVisible?: boolean
+  name: string
+  style?: StyleOrFunction<SharedElementRenderProps>
+}

/react-aria-components:SelectionIndicatorProps

+SelectionIndicatorProps {
+  children?: ChildrenOrFunction<SharedElementRenderProps>
+  className?: ClassNameOrFunction<SharedElementRenderProps>
+  isSelected?: boolean
+  style?: StyleOrFunction<SharedElementRenderProps>
+}

/react-aria-components:SharedElementTransitionProps

+SharedElementTransitionProps {
+  children: ReactNode
+}

/react-aria-components:SharedElementProps

+SharedElementProps {
+  children?: ChildrenOrFunction<SharedElementRenderProps>
+  className?: ClassNameOrFunction<SharedElementRenderProps>
+  isVisible?: boolean
+  name: string
+  style?: StyleOrFunction<SharedElementRenderProps>
+}

/react-aria-components:SharedElementRenderProps

+SharedElementRenderProps {
+  isEntering: boolean
+  isExiting: boolean
+}

Copy link
Member

@LFDanLu LFDanLu left a comment

Choose a reason for hiding this comment

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

approving for testing

collection={state.collection}
persistedKeys={usePersistedKeys(state.selectionManager.focusedKey)}
scrollRef={ref} />
<SharedElementTransition>
Copy link
Member

@snowystinger snowystinger Sep 22, 2025

Choose a reason for hiding this comment

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

should this be wherever there is a GroupSelectionManager? or setup by Section?

@devongovett devongovett added this pull request to the merge queue Sep 22, 2025
Merged via the queue into main with commit c12a3b4 Sep 22, 2025
33 checks passed
@devongovett devongovett deleted the selection-indicator branch September 22, 2025 20:50
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.

4 participants