npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nitro-blur

v0.1.0

Published

Backdrop blur for React Native with native iOS effects and one Android GPU renderer

Readme

Nitro Blur

Backdrop blur for React Native. Place a BlurView over your content and it blurs what's behind it. Text and controls inside the view stay sharp. You don't need a target ref or provider.

iOS uses native blur materials. Android uses a GPU renderer with a choice of detail levels through the quality prop.

Install

bun add nitro-blur react-native-nitro-modules
cd ios && pod install

Rebuild your app after installing the native modules.

Requirements

| Dependency | Requirement | | --- | --- | | React Native | 0.78+ with the New Architecture | | React | 19+ | | Nitro Modules | 0.35.9 or later in the 0.35.x series | | Android | API 24+ with a hardware-accelerated window | | iOS | Your React Native version's minimum deployment target |

This is an early release. The example has been tested with React Native 0.85.3, an iOS simulator, and a Samsung SM-A146P running Android 15. The full declared compatibility range still needs testing.

Usage

import { ScrollView, Text, View } from 'react-native'
import { BlurView } from 'nitro-blur'

export function Screen() {
  return (
    <View style={{ flex: 1 }}>
      <ScrollView>{/* Your content */}</ScrollView>
      <BlurView
        intensity={50}
        quality="high"
        tint="light"
        style={{ position: 'absolute', top: 0, left: 0, right: 0, padding: 24 }}
      >
        <Text>This text stays sharp.</Text>
      </BlurView>
    </View>
  )
}

Place the content behind the blur in the view's drawing order. In this example, the ScrollView comes first and the blur sits above it as an absolute overlay.

Layout and touches

BlurView accepts normal View props. Use style to set its size, position, padding, and borderRadius. The container clips both the blur and its children to its bounds, including rounded corners.

Use pointerEvents="none" for a decorative overlay that lets all touches through. Use pointerEvents="box-none" if the blur contains controls that should remain interactive while touches outside those controls pass through.

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | intensity | number | 50 | Blur strength from 0 to 100. | | quality | BlurQuality | 'medium' | Android detail preset. iOS ignores it. | | tint | BlurTint | 'default' | Light, dark, or system appearance. | | onError | (error: Error) => void | Unset | Handles Android capture or rendering failures. |

The package exports BlurViewProps, BlurQuality, and BlurTint for TypeScript users.

Intensity

intensity controls strength on both platforms. At 0, the blur layer is transparent and its children remain visible. Values outside 0 to 100, NaN, and infinity throw a RangeError during render.

The same value can look different across platforms. iOS interpolates a native material effect. Android maps intensity to a filter radius of up to 40 dp. Treat intensity as effect strength, not a Gaussian radius shared by both platforms.

Android quality

| Value | Working resolution | Tradeoff | | --- | --- | --- | | 'low' | Up to 8× downsampling per dimension | Less rendering work, less detail. | | 'medium' | Up to 4× downsampling per dimension | The default balance of detail and cost. | | 'high' | Up to 2× downsampling per dimension | More detail, more rendering work. |

All presets target the same blur strength. They change the working resolution and filter approximation, so fine detail can differ. Subtle blur uses less downsampling.

Quality does not change the update frequency or select another renderer. iOS ignores this prop.

Tint and accessibility

tint accepts 'light', 'dark', or 'default'. The default follows the system's light or dark appearance.

iOS respects Reduce Transparency. When that setting is enabled and intensity is above zero, the view shows a solid material color. Android's quality prop has no effect on this behavior.

Video on Android

The video player must render into a TextureView for its output to appear behind the blur. A SurfaceView renders into a separate layer that Nitro Blur cannot capture. Protected video cannot be captured either.

The example uses react-native-video 6.15.0 with ViewType.TEXTURE. Other players need their equivalent setting. See the example app for the player setup and its version-specific notes.

Error handling

import { useState } from 'react'
import { Text } from 'react-native'
import { BlurView } from 'nitro-blur'

export function Panel() {
  const [error, setError] = useState<Error>()
  if (error) return <Text>{error.message}</Text>
  return <BlurView style={{ height: 120 }} onError={setError} />
}

An Android capture or rendering failure stops the renderer and makes the blur layer transparent. Its children remain visible. Without onError, the error goes to React Native's exception handler.

Unmount and remount the view to create a fresh renderer after a failure. Unmounting releases the native resources. There is no software or alternate blur backend.

onError handles native Android failures. Invalid intensity values throw during React rendering and do not reach this callback.

Android performance and limits

Each blur owns a capture session and adds capture and composition work. Large blur areas and overlapping layers cost more. Start with the default quality and measure on your target devices before raising it.

The renderer allows one capture in flight at a time. It skips capture when the view is hidden, offscreen, or at zero intensity. Visible views capture on draw updates, even when the source content has not changed.

  • Capture and output are asynchronous. Blur can trail the source during fast scrolling, especially with overlapping layers. Same-frame delivery is not guaranteed.
  • Capture covers ordinary React Native views in the same window. Separate SurfaceView layers, other windows, and protected content are outside its reach. This affects some video, camera, and map views.
  • Custom native drawing and some composition effects are not fully reproduced. The renderer details below describe these cases.

Two overlapping medium-quality blurs over video have been profiled on the Samsung SM-A146P. That result does not establish performance on other devices or at high quality.

The UI thread replays the part of the view hierarchy drawn before the blur into Surface.lockHardwareCanvas(). A SurfaceTexture passes that image to a GL thread, which applies Dual Kawase blur and presents it in a TextureView. This avoids per-frame CPU pixel readback. The renderer uses no RenderScript, RenderEffect, PixelCopy, or private Android APIs.

Capture includes surrounding pixels for the filter and handles ordinary view transforms, scroll offsets, React Native zIndex, and elevation ordering. An upper blur can sample an already-presented lower blur. Capture does not hide or change source views.

Ancestors on the path to the blur replay their backgrounds and children. Sibling subtrees use their normal draw implementation. Custom native ViewGroup.onDraw content, custom child drawing order, animated legacy view transforms, outline clipping, and render effects are not fully reproduced. Elevation order is respected, but shadow fidelity, group opacity, blend modes, and nested clipping need device validation.

The GL thread creates and releases the capture surface, shaders, and render targets. The UI thread borrows the capture surface while a frame is in flight. Closing a session prevents further capture and queues cleanup behind pending render work. The output texture stays with TextureView until its destruction callback transfers ownership. The session releases that texture once GL cleanup finishes. Unmounting also releases the GL context and shuts down the worker thread.

Example and development

The example app includes video and scrolling backdrops, overlapping blur layers, and controls for intensity, tint, Android quality, and mounting the view.

# From the repo root
bun install
bun run blur:specs
bun run example:android

For iOS, install the example's pods in apps/example/ios, then run bun run example:ios from the repo root.

blur:specs runs Nitrogen directly. Generated bindings ship in the package. Edit src/specs and regenerate instead of editing nitrogen/generated.

Report issues at nitroverse/issues. Include your device, OS, React Native version, and a small example that reproduces the problem.

License

MIT. See LICENSE.