feat: add shadow properties (iOS) and elevation (Android)#35
Merged
janicduplessis merged 14 commits intomainfrom Apr 14, 2026
Merged
feat: add shadow properties (iOS) and elevation (Android)#35janicduplessis merged 14 commits intomainfrom
janicduplessis merged 14 commits intomainfrom
Conversation
…upport Adds animatable shadow/elevation properties following the existing per-property pattern: bitmask flags, codegen props, native change detection, and platform-specific animation. iOS: shadowOpacity, shadowRadius, shadowColor, shadowOffset via Core Animation key-path animations. Android: elevation via ObjectAnimator.
clang-format introduced a stray 'l' at the beginning of the file, causing a compilation error.
…emove web elevation
- shadowOffset is now { width, height } matching RN style API (flattened to native props)
- Consolidated MASK_SHADOW_OFFSET into single bit (1 << 15)
- MASK_ELEVATION shifted to 1 << 16
- Removed elevation from web (no-op in react-native-web)
fb7d691 to
11791cb
Compare
…ius is not animated When borderRadius is not in the animated bitmask, use ViewOutlineProvider.BACKGROUND so elevation shadows respect the style borderRadius from the background drawable. Only switch to the custom provider when borderRadius is actively animated.
cornerRadius alone rounds the view's background visually. masksToBounds clips children and shadows, which conflicts with shadow animations and doesn't match RN's default overflow:visible. Let the style system control masksToBounds via the overflow prop instead.
When borderRadius is animated via ObjectAnimator, the BorderDrawable was not updated, causing borders to render with square corners. Now setAnimateBorderRadius also calls BackgroundStyleApplicator.setBorderRadius to keep the border drawable in sync with the animated corner radius.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
React Native's shadow API (
shadowOpacity,shadowRadius,shadowColor,shadowOffset) is iOS-only and uses CALayer properties, while Android useselevationfor material shadows. Neither is currently animatable through EaseView.This PR adds native animation support for both platforms following the existing per-property pattern:
shadowOpacity,shadowRadius,shadowColor,shadowOffsetX,shadowOffsetY— animated via Core Animation key-path animations on the corresponding CALayer properties. Shadow offset X/Y are animated together as a singleshadowOffsetCGSize animation.elevation— animated via ObjectAnimator (timing) with spring falling back to timing, matching theborderRadiuspattern.All six properties get their own bitmask flag so they can coexist with style-managed values. A new
shadowtransition category allows per-category animation config for all shadow/elevation properties.Test Plan
yarn format:write && yarn lint && yarn test— all 71 tests pass, including 15 new tests covering shadow/elevation prop resolution, bitmask flags, initialAnimate, shadowColor, and style conflict stripping.animate: