feat: add web support via CSS transitions#3
Merged
janicduplessis merged 13 commits intomainfrom Mar 16, 2026
Merged
Conversation
Implement EaseView.web.tsx that uses CSS transitions for timing animations, CSS @Keyframes for loop animations, and a timing approximation for springs. React Native's .web.tsx resolution automatically picks this up on web.
Install expo and web dependencies (react-dom, react-native-web, @expo/metro-runtime) to enable running the example app on web via `npx expo start --web`.
The web EaseView receives RN StyleSheet numeric IDs and style arrays,
but was trying to spread them directly as React.CSSProperties. Spreading
an array gives {0: id} which caused:
TypeError: Failed to set an indexed property [0] on CSSStyleDeclaration
Fix: use StyleSheet.flatten() to resolve any RN StyleProp to a plain
object before spreading into computedStyle.
Replace the raw <div> with react-native View which: - Handles StyleSheet flattening automatically (no more manual flattenStyle) - Accepts StyleProp<ViewStyle> natively - Converts RN transform arrays to CSS transforms via react-native-web - Properly handles all RN style types (numeric IDs, arrays, objects) CSS transitions and keyframe animations are applied imperatively via the DOM ref, since View does not expose those as style props. Also removes accidentally committed .playwright-cli artifacts.
…keyframes Only include border-radius and background-color in CSS @Keyframes when the user explicitly sets them in animate/initialAnimate props. Previously, IDENTITY defaults (borderRadius: 0) were always included, which overrode values set via the style prop (e.g. pulse's borderRadius: 30).
will-change: transform causes the element to be promoted to its own GPU compositing layer, which can escape parent overflow:hidden clipping in some browsers. CSS animations already get GPU-promoted automatically, so the hint is unnecessary.
BANNER_WIDTH was computed at module load time using Dimensions.get('window')
which bakes in the build-time window width on static web exports. Switched
to useWindowDimensions() hook so the banner correctly sizes to the actual
viewport width at render time.
f0304d5 to
2215b53
Compare
…for settings plugin
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.
Web Support
Adds a
.web.tsxplatform-specific implementation ofEaseViewthat uses CSS transitions and@keyframesanimations — no native modules, zero JS thread overhead.How it works
transitionset imperatively on the DOM element viael.style.transition@keyframeswith a dynamically injected<style>tagViewfromreact-native(react-native-web) instead of a raw<div>— handles StyleSheet flattening, RN transform arrays, and style types automaticallytransition,animation,transformOrigin) are set imperatively via a DOM ref since they aren't available as RN style propsExample app changes
expo,react-native-web,@expo/metro-runtime)AppRegistry.registerComponentfor native +runApplicationfor webuseWindowDimensions()for responsive banner widthdomlib to tsconfig for DOM types in.web.tsxDemo — Web (all 17 examples)
web-demo.mp4