Skip to content

Instantly share code, notes, and snippets.

@aleqsio
Created September 18, 2025 09:37
Show Gist options
  • Select an option

  • Save aleqsio/55513bde1d1e454f3156f68a28057a39 to your computer and use it in GitHub Desktop.

Select an option

Save aleqsio/55513bde1d1e454f3156f68a28057a39 to your computer and use it in GitHub Desktop.
import { ThemedText } from "@/components/themed-text";
import { BottomSheet, Button, Host, Slider } from "@expo/ui/swift-ui";
import { frame, offset } from "@expo/ui/swift-ui/modifiers";
import { Canvas, Fill, Shader, Skia, vec } from "@shopify/react-native-skia";
import { useState } from "react";
import {
PlatformColor,
StyleSheet,
useWindowDimensions,
View,
} from "react-native";
// Add Reanimated imports
import Animated, {
Easing,
useAnimatedReaction,
useAnimatedStyle,
useDerivedValue,
useSharedValue,
withTiming,
} from "react-native-reanimated";
const source = Skia.RuntimeEffect.Make(`
uniform float sheetAnim;
uniform int type;
uniform vec2 size;
float rand(vec2 co){
return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453);
}
vec4 main(vec2 pos) {
vec2 normalized = pos/vec2(256);
vec2 offset;
float dist;
offset = (pos - vec2(size.x/2, -size.y));
dist = sqrt(pow(offset.x, 2.0) + pow(offset.y, 2.0)) / sqrt(pow(size.x/2, 2.0) + pow(size.y/2, 2.0));
float mixVal = 0;
vec4 colorA;
float anim = 1 - sheetAnim;
if(type == 0) {
mixVal = anim;
colorA = vec4(normalized.y, normalized.x, 1.0,1.0);
}
if(type == 1) {
mixVal = (1-dist) - anim;
colorA = vec4(normalized.y, normalized.x, 1.0,1.0);
}
if(type == 2) {
mixVal = max(0,1.0- pow(1-dist,2.0) + pow(anim*0.7,1));
colorA = vec4(normalized.y, normalized.x, 1.0,1.0);
}
if(type == 3) {
offset = (pos - vec2(size.x*anim, size.y*anim));
dist = sqrt(pow(offset.x, 2.0) + pow(offset.y, 2.0)) / sqrt(pow(size.x/2, 2.0) + pow(size.x/2, 2.0)) - pow(sheetAnim,1.3);
mixVal = max(0.0,dist);
colorA = vec4(1.0, normalized.x, normalized.y,1.0);
}
// float mixVal = (1-dist) - anim;
// float mixVal = max(0,1.0- pow(1-dist,2.0) + pow(anim*0.7,1));
vec4 colorB = vec4(0.0, 0.0, 0.0,0.0);
vec4 color = mix(colorA, colorB, mixVal+rand(pos)/(6.0));
return vec4(color);
}`)!;
export default function ModalScreen() {
const [isOpen, setIsOpen] = useState(false);
const [type, setType] = useState(0);
const { width } = useWindowDimensions();
// Create shared value
const sheetAnim = useSharedValue(0);
// Animate sheetAnim when isOpen changes
useAnimatedReaction(
() => isOpen,
(opened, prev) => {
if (opened !== prev) {
if (opened) {
sheetAnim.value = withTiming(1, {
duration: 2000,
easing: Easing.bezier(0, 0.3, 0.7, 1),
});
} else {
sheetAnim.value = 0;
}
}
},
[isOpen]
);
const uniforms = useDerivedValue(
() => ({
sheetAnim: sheetAnim.value,
size: vec(width, 500),
type: Math.round(type),
}),
[sheetAnim, type]
);
const opacityStyle = useAnimatedStyle(() => ({
opacity: 1 - Math.abs(1 - sheetAnim.value * 2.0),
}));
return (
<View style={styles.container}>
<Animated.View style={[opacityStyle, { position: "absolute" }]}>
<Canvas
style={{
width: width,
height: 500,
transform: [{ scale: 1.8 }],
filter: "blur(10px)",
}}
>
<Fill>
<Shader source={source} uniforms={uniforms} />
</Fill>
</Canvas>
</Animated.View>
<Host>
<BottomSheet isOpened={isOpen} onIsOpenedChange={setIsOpen}>
<View style={{ height: 450 }}>
<Animated.View style={[opacityStyle, { position: "absolute" }]}>
<Canvas style={{ width: width, height: 500 }}>
<Fill>
<Shader source={source} uniforms={uniforms} />
</Fill>
</Canvas>
</Animated.View>
<View style={{ position: "absolute", top: 40, left: 20 }}>
<ThemedText type="title">
{"Shaders\nGlass UI\nExpo\n\n🔥"}
</ThemedText>
</View>
</View>
</BottomSheet>
</Host>
<Host style={{ width: 400, height: 200 }}>
<Button variant="glass" onPress={() => setIsOpen((o) => !o)}>
{`Shader ${Math.round(type)}`}
</Button>
<Slider
modifiers={[offset({ x: 0, y: 50 }), frame({ width: 200 })]}
onValueChange={setType}
value={type}
steps={1}
max={3}
min={0}
></Slider>
</Host>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: PlatformColor("tertiarySystemBackground"),
},
link: {
marginTop: 15,
paddingVertical: 15,
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment