Skip to content

Conversation

devongovett
Copy link
Member

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.

Currently it's built into Tabs and ToggleButtonGroup. Which other components should we support?

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

@rspbot
Copy link

rspbot commented Sep 17, 2025

## API Changes

react-aria-components

/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:SelectionIndicator

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

/react-aria-components:SelectionIndicatorContext

+SelectionIndicatorContext {
+  UNTYPED
+}

/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
+}

/react-aria-components:SelectionIndicatorProps

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

@@ -79,6 +79,37 @@ function Example(props) {
}
```

### 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

@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.

@@ -402,7 +452,10 @@ By default, tabs are horizontally oriented. The `orientation` prop can be set to
flex-direction: column;
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?

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