Skip to content

refactor: rework Surface and elevation shadows - #5078

Draft
satya164 wants to merge 1 commit into
mainfrom
@satya164/rework-surface
Draft

refactor: rework Surface and elevation shadows#5078
satya164 wants to merge 1 commit into
mainfrom
@satya164/rework-surface

Conversation

@satya164

@satya164 satya164 commented Aug 26, 2026

Copy link
Copy Markdown
Member

Motivation

This reworks the Surface component to work with Reanimated + updates components that use Surface.

Previously, since the component rendered outer and inner views, it flattened styles and picked where to apply what. Style flattening adds challenges when using Reanimated, as Reanimated relies on metadata from useAnimatedStyle for UI-thread updates.

After trying a couple of approaches, I arrived at this approach:

  • Single View for Surface so it can accept both position and layout related styles
  • Inner View for second shadow layer, but instead of wrapping children in it (which adds more challenges), we absolutely position it behind the content
  • Background color and border radius are added as props since they need to be applied to inner view, and props make it simple without needing to flatten styles

Test plan

Appbar

Android

Before

appbar-android-before

After

appbar-android-after

iOS

Before

appbar-ios-before

After

appbar-ios-after

Web

Before

appbar-web-before

After

appbar-web-after

Badge

Android

Before

badge-android-before

After

badge-android-after

iOS

Before

badge-ios-before

After

badge-ios-after

Web

Before

badge-web-before

After

badge-web-after

Banner

Android

Before

banner-android-before.mp4

After

banner-android-after.mp4

iOS

Before

banner-ios-before.mp4

After

banner-ios-after.mp4

Web

Before

banner-web-before.mp4

After

banner-web-after.mp4

Bottom Navigation

Android

Before

bottom-navigation-android-before.mp4

After

bottom-navigation-android-after.mp4

iOS

Before

bottom-navigation-ios-before.mp4

After

bottom-navigation-ios-after.mp4

Web

Before

bottom-navigation-web-before.mp4

After

bottom-navigation-web-after.mp4

Button

Android

Before

button-android-before

After

button-android-after

iOS

Before

button-ios-before

After

button-ios-after

Web

Before

button-web-before

After

button-web-after

Card

Android

Before

card-android-before

After

card-android-after

iOS

Before

card-ios-before

After

card-ios-after

Web

Before

card-web-before

After

card-web-after

Chip

Android

Before

chip-android-before

After

chip-android-after

iOS

Before

chip-ios-before

After

chip-ios-after

Web

Before

chip-web-before

After

chip-web-after

Dialog

Android

Before

dialog-android-before.mp4

After

dialog-android-after.mp4

iOS

Before

dialog-ios-before.mp4

After

dialog-ios-after.mp4

Web

Before

dialog-web-before.mp4

After

dialog-web-after.mp4

FAB

Android

Before

fab-android-before.mp4

After

fab-android-after.mp4

iOS

Before

fab-ios-before.mp4

After

fab-ios-after.mp4

Web

Before

fab-web-before.mp4

After

fab-web-after.mp4

Icon Button

Android

Before

icon-button-android-before

After

icon-button-android-after

iOS

Before

icon-button-ios-before

After

icon-button-ios-after

Web

Before

icon-button-web-before

After

icon-button-web-after

Menu

Android

Before

menu-android-before.mp4

After

menu-android-after.mp4

iOS

Before

menu-ios-before.mp4

After

menu-ios-after.mp4

Web

Before

menu-web-before.mp4

After

menu-web-after.mp4

Modal

Android

Before

modal-android-before.mp4

After

modal-android-after.mp4

iOS

Before

modal-ios-before.mp4

After

modal-ios-after.mp4

Web

Before

modal-web-before.mp4

After

modal-web-after.mp4

Searchbar

Android

Before

searchbar-android-before

After

searchbar-android-after

iOS

Before

searchbar-ios-before

After

searchbar-ios-after

Web

Before

searchbar-web-before

After

searchbar-web-after

Snackbar

Android

Before

snackbar-android-before.mp4

After

snackbar-android-after.mp4

iOS

Before

snackbar-ios-before.mp4

After

snackbar-ios-after.mp4

Web

Before

snackbar-web-before.mp4

After

snackbar-web-after.mp4

Surface

Android

Before

surface-android-before.mp4

After

surface-android-after.mp4

iOS

Before

surface-ios-before.mp4

After

surface-ios-after.mp4

Web

Before

surface-web-before.mp4

After

surface-web-after.mp4

Toggle Button

Android

Before

toggle-button-android-before

After

toggle-button-android-after

iOS

Before

toggle-button-ios-before

After

toggle-button-ios-after

Web

Before

toggle-button-web-before

After

toggle-button-web-after

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Reworks Surface around Reanimated-compatible styling and updates dependent components, animations, examples, documentation, and tests.

Changes:

  • Replaces layered/style-flattening Surface behavior with explicit visual props and platform shadows.
  • Migrates several component animations to Reanimated.
  • Updates affected APIs, tests, snapshots, examples, and documentation.

Reviewed changes

Copilot reviewed 61 out of 70 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/utils/animations.ts Removes obsolete Animated helper.
src/theme/tokens/sys/elevation.ts Reworks static shadow generation.
src/components/ToggleButton/ToggleButton.tsx Updates animated style typing.
src/components/Surface.tsx Reimplements Surface and visual props.
src/components/Snackbar.tsx Migrates animations to Reanimated.
src/components/Searchbar.tsx Adopts new Surface API.
src/components/Modal.tsx Adds transitions and elevation.
src/components/Menu/Menu.tsx Migrates menu animations and layout.
src/components/IconButton/IconButton.tsx Replaces Surface with Animated View.
src/components/FAB/useVisibility.ts Removes superseded visibility hook.
src/components/FAB/Shell.tsx Integrates Surface and visibility animation.
src/components/FAB/Extended.tsx Updates measurement behavior.
src/components/Dialog/Dialog.tsx Uses Modal elevation.
src/components/Chip/Chip.tsx Adopts numeric elevation transitions.
src/components/Card/Card.tsx Adopts new Surface visual props.
src/components/Button/Button.tsx Adopts new Surface visual props.
src/components/BottomNavigation/BottomNavigationBar.tsx Adds animated wrapper around Surface.
src/components/Banner.tsx Migrates animations to Reanimated.
src/components/Appbar/utils.ts Updates elevation and border helpers.
src/components/Appbar/AppbarHeader.tsx Replaces elevated flag with elevation.
src/components/Appbar/Appbar.tsx Integrates new Surface API.
src/components/__tests__/ToggleButton.test.tsx Removes legacy animation test.
src/components/__tests__/Surface.test.tsx Updates Surface layer assertions.
src/components/__tests__/Snackbar.test.tsx Removes legacy animation test.
src/components/__tests__/Searchbar.test.tsx Removes legacy animation test.
src/components/__tests__/Modal.test.tsx Updates Surface and style assertions.
src/components/__tests__/Menu.test.tsx Updates content-style assertion.
src/components/__tests__/IconButton.test.tsx Removes legacy animation test.
src/components/__tests__/Chip.test.tsx Removes legacy animation test.
src/components/__tests__/Checkbox/__snapshots__/CheckboxItem.test.tsx.snap Refreshes Reanimated snapshots.
src/components/__tests__/Checkbox/__snapshots__/Checkbox.test.tsx.snap Refreshes Reanimated snapshots.
src/components/__tests__/Card/Card.test.tsx Removes legacy animation test.
src/components/__tests__/Card/__snapshots__/Card.test.tsx.snap Reflects new Surface structure.
src/components/__tests__/Button.test.tsx Removes legacy animation test.
src/components/__tests__/BottomNavigation.test.tsx Targets new animated wrapper.
src/components/__tests__/Banner.test.tsx Removes legacy animation test.
src/components/__tests__/Appbar/Appbar.test.tsx Updates Appbar API assertions.
src/components/__tests__/__snapshots__/ToggleButton.test.tsx.snap Reflects IconButton structure.
src/components/__tests__/__snapshots__/Switch.test.tsx.snap Refreshes Reanimated snapshots.
src/components/__tests__/__snapshots__/ListItem.test.tsx.snap Reflects new Chip Surface structure.
src/components/__tests__/__snapshots__/Badge.test.tsx.snap Refreshes Reanimated snapshots.
jest/testSetup.js Adjusts worklets mocking.
example/src/RootNavigator.tsx Updates Appbar usage.
example/src/Examples/TooltipExample.tsx Updates Appbar usage.
example/src/Examples/TeamDetails.tsx Updates Appbar usage.
example/src/Examples/SurfaceExample.tsx Demonstrates new Surface props.
example/src/Examples/MenuExample.tsx Updates Appbar usage.
example/src/Examples/BottomNavigationExample.tsx Updates Appbar usage.
example/src/Examples/AppbarExample.tsx Uses numeric elevation.
docs/6.x/docs/components/Surface.mdx Documents Surface visual props.
docs/6.x/docs/components/Modal.mdx Documents Modal elevation.
docs/6.x/docs/components/Chip/Chip.mdx Documents Chip ref.
docs/6.x/docs/components/Card/Card.mdx Documents Card ref.
docs/6.x/docs/components/Appbar/AppbarHeader.mdx Documents elevation API.
docs/6.x/docs/components/Appbar/Appbar.mdx Documents elevation API.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

height: shadowLayers[layer].height[elevation],
},
shadowRadius: shadowLayers[layer].shadowRadius[elevation],
export type Props = Omit<ViewProps, 'pointerEvents' | 'style'> &
* - `overflow: 'hidden'` is not supported with `elevation` as it can clip the shadow.
* To achieve the same effect, wrap the content in a child View with the overflow style.
*/
style?: StyleProp<AnimatedStyle<Omit<ViewStyle, keyof SurfaceVisualProps>>>;
Comment thread src/components/Modal.tsx Outdated
theme={theme}
style={[{ opacity }, styles.content, contentContainerStyle]}
container
backgroundColor="transparent"
@satya164
satya164 force-pushed the @satya164/rework-surface branch 2 times, most recently from f72f11a to 66bded7 Compare August 27, 2026 16:39
@satya164
satya164 marked this pull request as ready for review August 27, 2026 17:14
Copilot AI review requested due to automatic review settings August 27, 2026 17:14
@satya164
satya164 force-pushed the @satya164/rework-surface branch from 66bded7 to b61df18 Compare August 27, 2026 17:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 59 out of 68 changed files in this pull request and generated 3 comments.

Suppressed comments (3)

src/components/Surface.tsx:258

  • Elevation also changes the derived backgroundColor, but this branch only transitions native elevation. Changing levels on Android makes the surface color jump while the shadow animates; include the background color in the transition as well.
    src/components/Surface.tsx:282
  • The elevation-derived background changes together with these shadow properties, but it is omitted from the transition. This causes level colors to snap on iOS while the shadow animates; transition backgroundColor too.
    src/components/Surface.tsx:194
  • The central behavior of this refactor—reacting to updates from Reanimated shared/animated styles—is not covered. The new Surface tests only assert static styles, while the prior animation tests in its consumers were removed. Add a test that mutates a shared value and verifies the rendered Surface style updates so metadata-preserving behavior cannot regress.


transitionStyle = {
...transitionStyle,
transitionProperty: 'boxShadow',
elevation={0}
testID={testID}
style={{ pointerEvents }}
onLayout={onLayout}
Comment on lines +62 to +65
- `Banner`
- `Button`
- `Card`
- `Chip`
@satya164
satya164 marked this pull request as draft August 27, 2026 18:01
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.

2 participants