One Logo Pool Ball
wwwwwwwwwwwwwwwwwww

Effects

Edge fades, backdrop blur, and masks that render natively on iOS and Android and with CSS on web

Three visual effects under One.UI, each drawn by the platform’s own graphics stack:

Usage

import { One } from 'one'
function Feed() {
return (
<One.UI.EdgeFade top={48} bottom={64} style={{ flex: 1 }}>
<Posts />
</One.UI.EdgeFade>
)
}

Both edges fade to transparent along the default smooth curve, so whatever is behind the feed shows through.

How it works

EdgeFade picks one of three modes. mask fades the content’s alpha, overlay paints a color gradient over it, and blur blurs it more toward the edge. Without mode, it is overlay when any edge has a color and mask otherwise; blur must be asked for.

Presets reach native code by name and use cached gradients there; a bezier or stop list is sampled in JavaScript and sent as alpha values. On web every mode is plain elements: mask and overlay use CSS gradients, and blur puts a backdrop-filter strip on each edge with its own gradient mask.

Blur on iOS is a UIVisualEffectView with the chosen material. UIKit has no blur intensity, so the component holds a paused animator at the intensity point, and rebuilds it when UIKit could have reset it: on return from the background and when entering a window. On Android 12 and later it records what is drawn behind the view and applies a Gaussian RenderEffect to that recording, then draws a tint over it; children draw on top, sharp. On web it is a CSS backdrop-filter blur of up to 20 pixels with a tinted veil.

Mask mounts maskElement as an invisible first child. On iOS its layer becomes the view’s layer mask, which Core Animation renders live. On Android the mask subtree is drawn into a reused bitmap, redrawn only when it changes, and applied as an alpha mask. On web the mask subtree is serialized with its computed styles into an SVG image used as a CSS mask-image.

API reference

One.UI.BlurTypeDescription
intensitynumber = 50Blur strength from 0 to 100. Values outside that range are clamped.
number = 50Blur strength from 0 to 100. Values outside that range are clamped.
tintBlurTint = "default"Native material name. Web approximates its tint with a frost veil.
BlurTint = "default"Native material name. Web approximates its tint with a frost veil.
styleStyleProp<ViewStyle>Container layout and styling. Give the effect explicit bounds.
StyleProp<ViewStyle>Container layout and styling. Give the effect explicit bounds.

BlurTint is light, dark, default, extraLight, regular, prominent, or one of the system materials systemUltraThinMaterial, systemThinMaterial, systemMaterial, systemThickMaterial, and systemChromeMaterial, each also with a Light or Dark suffix.

One.UI.EdgeFadeTypeDescription
topboolean | number | EdgeConfigFade at the top edge.
boolean | number | EdgeConfigFade at the top edge.
bottomboolean | number | EdgeConfigFade at the bottom edge.
boolean | number | EdgeConfigFade at the bottom edge.
leftboolean | number | EdgeConfigFade at the left edge.
boolean | number | EdgeConfigFade at the left edge.
rightboolean | number | EdgeConfigFade at the right edge.
boolean | number | EdgeConfigFade at the right edge.
startboolean | number | EdgeConfigLeading edge for the current layout direction. Overrides its physical edge.
boolean | number | EdgeConfigLeading edge for the current layout direction. Overrides its physical edge.
endboolean | number | EdgeConfigTrailing edge for the current layout direction. Overrides its physical edge.
boolean | number | EdgeConfigTrailing edge for the current layout direction. Overrides its physical edge.
sizenumber = 80Default enabled-edge depth in dp.
number = 80Default enabled-edge depth in dp.
curveEdgeFadeCurve = "smooth"Default alpha or blur-envelope curve.
EdgeFadeCurve = "smooth"Default alpha or blur-envelope curve.
modeEdgeFadeModemask fades alpha; overlay paints color; blur softens edge content. Defaults to overlay when any edge has a color, otherwise mask.
EdgeFadeModemask fades alpha; overlay paints color; blur softens edge content. Defaults to overlay when any edge has a color, otherwise mask.
colorColorValueOverlay color, or an optional frost veil in blur mode. Ignored in mask mode.
ColorValueOverlay color, or an optional frost veil in blur mode. Ignored in mask mode.
blurRadiusnumber = 28Maximum blur radius in dp for blur mode. Clamped to zero or greater.
number = 28Maximum blur radius in dp for blur mode. Clamped to zero or greater.
frostProgressionnumber = 1Fraction of the edge band over which blur reaches full strength. Clamped from 0.05 to 1.
number = 1Fraction of the edge band over which blur reaches full strength. Clamped from 0.05 to 1.
radiusnumberCorner radius shared by the fade and clipping. Use this instead of style.borderRadius.
numberCorner radius shared by the fade and clipping. Use this instead of style.borderRadius.
styleStyleProp<ViewStyle>Container layout and styling; borderRadius is ignored with a development warning.
StyleProp<ViewStyle>Container layout and styling; borderRadius is ignored with a development warning.

An edge takes true to use size, a number for its own depth, or an EdgeConfig. start and end follow the layout direction and win over left and right.

EdgeConfigTypeDescription
sizenumberOverride the component fade depth for this edge.
numberOverride the component fade depth for this edge.
curveEdgeFadeCurveOverride the component curve for this edge.
EdgeFadeCurveOverride the component curve for this edge.
colorColorValueOverride the overlay color for this edge. Ignored in blur and mask modes.
ColorValueOverride the overlay color for this edge. Ignored in blur and mask modes.

An EdgeFadeCurve is a preset (smooth, smoother, sharp, gentle, soft, linear), a cubic bezier, or a list of alpha stops from the inner edge to the outer edge.

CubicBezierCurveTypeDescription
type (required)"cubicBezier"Select the cubic bezier curve.
"cubicBezier"Select the cubic bezier curve.
x1 (required)numberFirst control point x coordinate.
numberFirst control point x coordinate.
y1 (required)numberFirst control point y coordinate.
numberFirst control point y coordinate.
x2 (required)numberSecond control point x coordinate.
numberSecond control point x coordinate.
y2 (required)numberSecond control point y coordinate.
numberSecond control point y coordinate.
StopsCurveTypeDescription
type (required)"stops"Select an alpha-stop list.
"stops"Select an alpha-stop list.
values (required)[number, number, ...number[]]At least two alpha values, ordered from the inner edge to the outer edge.
[number, number, ...number[]]At least two alpha values, ordered from the inner edge to the outer edge.
One.UI.MaskTypeDescription
maskElementReactNodeThe offscreen mask element. Opaque pixels show children; transparent pixels hide them.
ReactNodeThe offscreen mask element. Opaque pixels show children; transparent pixels hide them.
styleStyleProp<ViewStyle>Container layout and styling.
StyleProp<ViewStyle>Container layout and styling.

One.UI.sampleCurve(curve) returns the inner to outer alpha values: 32 samples for a preset or bezier, rounded to four places, or the stop list clamped to 0 through 1. One.UI.serializeCurve(curve) returns a preset’s name, or the samples joined with commas.

Platform differences

iOSAndroidWeb
BlurUIKit materialRenderEffect, Android 12CSS backdrop filter
Blur before Android 12Tint only, no blur
Edge fade blur modeEffect views per edgeAndroid 12; mask mode beforeBackdrop filter strips
MaskLive layer maskBitmap, redrawn on changeCSS mask image

Limits and gotchas

Examples

Frosted header over a scrolling list

import { ScrollView, Text, View } from 'react-native'
import { One } from 'one'
function Screen() {
return (
<View style={{ flex: 1 }}>
<ScrollView contentContainerStyle={{ paddingTop: 96 }}>
<Posts />
</ScrollView>
<One.UI.Blur
tint="systemChromeMaterial"
style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 96, justifyContent: 'flex-end', padding: 16 }}
>
<Text style={{ fontSize: 28, fontWeight: '700' }}>Feed</Text>
</One.UI.Blur>
</View>
)
}

The list scrolls under the header and shows through it blurred, while the title stays sharp. The top padding keeps the first post clear of the header at rest.

Fade a horizontal list into the background color

import { ScrollView } from 'react-native'
import { One } from 'one'
function Chips() {
return (
<One.UI.EdgeFade end={{ size: 32, color: '#ffffff' }} style={{ height: 44 }}>
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
<ChipRow />
</ScrollView>
</One.UI.EdgeFade>
)
}

A color makes this overlay mode, which paints white over the trailing edge. end flips to the left side in right to left layouts.

Gradient text

import { Text, View } from 'react-native'
import { One } from 'one'
function Title() {
return (
<One.UI.Mask maskElement={<Text style={{ fontSize: 40, fontWeight: '800' }}>One</Text>}>
<View style={{ height: 48, width: 120, backgroundImage: 'linear-gradient(to right, #ff5f6d, #ffc371)' }} />
</One.UI.Mask>
)
}

The text is the mask, so the gradient view shows only inside the letters.

Credit

The ordinary iOS blur is adapted from react-native-blur by Ahmed Sbai. The EdgeFade native masks and blur are adapted from react-native-edge-fade by Giulio Amato.

Edit this page on GitHub.