# `@danielsaraldi/react-native-blur-view` 🌫️

A simple blur view in react native based in [`@react-native-community/blur`](https://github.com/margelo/react-native-blur).

Support the animation transitions with [react-native-screens](https://github.com/software-mansion/react-native-screens), [react-native-reanimated](https://github.com/software-mansion/react-native-reanimated/), [react-native-navigation](https://github.com/wix/react-native-navigation) and Modals 😁. This library supports Apple TV and Android TV! 📺

> [!WARNING]
> Bottom tabs customized with the [react-navigation/bottom-tabs](https://reactnavigation.org/docs/bottom-tab-navigator/) aren't supported in Android. For more information, just [click here](https://github.com/DanielAraldi/react-native-blur-view/issues/39#issuecomment-4081708642)!

<div align="center">
  <p>
    <img alt="GitHub package.json version" src="https://img.shields.io/github/package-json/v/DanielAraldi/react-native-blur-view?style=flat&color=brightgreen" />
    <img alt="Unpacked size" src="https://img.shields.io/npm/unpacked-size/%40danielsaraldi%2Freact-native-blur-view?style=flat&color=brightgreen" />
    <img alt="NPM Downloads" src="https://img.shields.io/npm/dm/%40danielsaraldi%2Freact-native-blur-view?style=flat" />
  </p>
</div>

> [!NOTE]
> This package supports **only** [new architecture](https://reactnative.dev/blog/2024/10/23/the-new-architecture-is-here).

<p align="center">
  <img
    height="756px"
    hspace="8"
    src="./.github/previews/ios.gif"
    alt="React Native Blur View on iOS"
  />
  <img
    height="756px"
    hspace="8"
    src="./.github/previews/android.gif"
    alt="React Native Blur View on Android"
  />
</p>

## Summary

- [Installation](#installation)
- [Usage](#usage)
  - [Using lists](#using-lists)
  - [Using `Modal`](#using-modal)
  - [Using `ImageBackground`](#using-imagebackground)
- [Components](#components)
  - [`BlurView`](#blurview)
    - [Properties](#properties)
  - [`BlurTarget`](#blurtarget)
    - [Properties](#properties-1)
  - [`VibrancyView`](#vibrancyview)
    - [Properties](#properties-2)
- [Types](#types)
  - [Blur Types](#blur-types)
  - [Effect Styles](#effect-styles)
- [Migrate to 3.x](#migrate-to-3x)
  - [Why This Change?](#why-this-change)
- [Platform Differences](#platform-differences)
  - [Android](#android)
  - [iOS](#ios)
- [Expo](#expo)
- [TypeScript Support](#typescript-support)
- [Others Libraries](#others-libraries)
- [Contributing](#contributing)
- [License](#license)

## Installation

```sh
npm install @danielsaraldi/react-native-blur-view
# or
yarn add @danielsaraldi/react-native-blur-view
# or
pnpm add @danielsaraldi/react-native-blur-view
# or
bun add @danielsaraldi/react-native-blur-view
```

Install native dependencies (**iOS only**):

```sh
cd ios && pod install && cd ..
```

## Usage

```tsx
import { useRef } from 'react';
import { ScrollView, StyleSheet, Text, View } from 'react-native';
import {
  BlurView,
  BlurTarget,
  VibrancyView,
} from '@danielsaraldi/react-native-blur-view';
// ...

export default function App() {
  const targetRef = useRef<View | null>(null);
  // ...

  return (
    <>
      <BlurView blurTarget={targetRef} style={styles.blurView}>
        <Text style={styles.text}>BlurView</Text>
      </BlurView>

      <VibrancyView style={styles.vibrancyView}>
        <Text style={styles.text}>VibrancyView</Text>
      </VibrancyView>

      <BlurTarget ref={targetRef} style={styles.blurTarget}>
        <ScrollView
          style={styles.scrollView}
          contentContainerStyle={styles.contentContainer}
          showsVerticalScrollIndicator={false}
        >
          {/* ... */}
        </ScrollView>
      </BlurTarget>
    </>
  );
}

export const styles = StyleSheet.create({
  blurView: {
    position: 'absolute',
    top: 0,

    width: '100%',
    height: 256,

    justifyContent: 'center',
    alignItems: 'center',
  },

  vibrancyView: {
    position: 'absolute',
    top: 256,

    width: '100%',
    height: 256,

    justifyContent: 'center',
    alignItems: 'center',
  },

  title: {
    fontSize: 24,
    fontWeight: 'bold',

    color: 'white',
  },

  main: {
    flex: 1,
  },

  content: {
    padding: 20,

    gap: 8,
  },
});
```

### Using lists

You must add `BlurView` elements inside of the list, and the content behind should be added as child of the `BlurTarget` component. Check an example using `ScrollView` below:

```tsx
import { useRef } from 'react';
import { ImageBackground, ScrollView, Text, View } from 'react-native';
import { BlurView, BlurTarget } from '@danielsaraldi/react-native-blur-view';
// ...

export function MyScreen() {
  const targetRef = useRef<View | null>(null);
  // ...

  return (
    <View style={styles.container}>
      <BlurTarget ref={targetRef} style={styles.blurTarget}>
        <ImageBackground
          style={styles.background}
          source={BACKGROUND}
          resizeMode="cover"
        />
      </BlurTarget>

      <ScrollView
        style={styles.scrollView}
        contentContainerStyle={styles.contentContainer}
        showsVerticalScrollIndicator={false}
      >
        <BlurView blurTarget={targetRef} style={styles.blurView}>
          <Text style={styles.text}>BlurView 1</Text>
        </BlurView>

        <BlurView blurTarget={targetRef} style={styles.blurView}>
          <Text style={styles.text}>BlurView 2</Text>
        </BlurView>

        <BlurView blurTarget={targetRef} style={styles.blurView}>
          <Text style={styles.text}>BlurView 3</Text>
        </BlurView>

        {/* ... */}
      </ScrollView>
    </View>
  );
}
```

### Using `Modal`

You must add `BlurTarget` as a parent of content screen because it will be the **target** of blur, the `BlurView` component must be to used inside of `Modal` to blur effect works correctly.

```tsx
import { useRef, useState } from 'react';
import { Modal, View } from 'react-native';
import { BlurTarget, BlurView } from '@danielsaraldi/react-native-blur-view';
// ...

export function MyScreen() {
  const [isOpenModal, setIsOpenModal] = useState<boolean>(false);
  const targetRef = useRef<View | null>(null);
  // ...

  return (
    <>
      <Modal
        transparent
        statusBarTranslucent
        navigationBarTranslucent
        hardwareAccelerated
        visible={isOpenModal}
        onRequestClose={() => setIsOpenModal(false)}
        style={styles.modal}
      >
        <BlurView blurTarget={targetRef} style={styles.blurView} />

        <View style={styles.modalContent}>{/* ... */}</View>
      </Modal>

      <BlurTarget ref={targetRef} style={styles.blurTarget}>
        {/* ... */}
      </BlurTarget>
    </>
  );
}
```

### Using `ImageBackground`

You must add `BlurTarget` as a parent of `ImageBackground` because it will be the **target** of blur, the `BlurView` component must be to used as **brother** of `BlurTarget` to blur effect works correctly.

```tsx
import { useRef } from 'react';
import { ImageBackground, View } from 'react-native';
import { BlurTarget, BlurView } from '@danielsaraldi/react-native-blur-view';
// ...

export function MyScreen() {
  const targetRef = useRef<View | null>(null);
  // ...

  return (
    <>
      <View style={styles.blurViewWrapper}>
        <BlurView
          blurTarget={targetRef}
          style={styles.blurView}
          downscaleFactor={4}
        >
          {/** ... **/}
        </BlurView>
      </View>

      <BlurTarget ref={targetRef} style={styles.blurTarget}>
        <ImageBackground
          style={styles.background}
          source={{ uri: 'https://picsum.photos/seed/picsum/600/900' }}
          resizeMode="cover"
        />
      </BlurTarget>
    </>
  );
}
```

## Components

### `BlurView`

The `BlurView` component is an extends the same properties of the a `View` component. The `blurTarget` prop is **required** for Android blur effect works correctly.

#### Properties

| Property                           | Description                                                                                 | Default     | Platform |
| ---------------------------------- | ------------------------------------------------------------------------------------------- | ----------- | -------- |
| `blurTarget`                       | Ref of the `BlurTarget` component to be identified by the `BlurView` component in the tree. | `undefined` | Android  |
| `type`                             | [Blur type](#blur-types) of the overlay.                                                    | `light`     | All      |
| `radius`                           | Blur radius `0` - `100`.                                                                    | `10.0`      | All      |
| `downscaleFactor`                  | Downscale factor `0` - `100`.                                                               | `6.0`       | Android  |
| `overlayColor`                     | Add the overlay color about component.                                                      | `undefined` | All      |
| `androidColor`                     | Overrides the `type` property color.                                                        | `undefined` | Android  |
| `reducedTransparencyFallbackColor` | Background color about blur effect when reduced transparency is enabled.                    | `white`     | iOS      |

When a value less than `0` or greater than `100` are provided for `radius` or `downscaleFactor` property, the value is clipped.

### `BlurTarget`

The `BlurTarget` component is an extends the same properties of the a `View` component.

This component is available for **Android only**. It's useful because we use [Dimezis's 3v library](https://github.com/Dimezis/BlurView) to apply the blur effect, so its implementation is slightly different than on iOS. The `BlurTarget` component is a common `View` in iOS.

The `BlurTarget` may not contain a `BlurView` that targets the same `BlurTarget`. The `BlurTarget` may contain other `BlurTargets` and `BlurViews` though.

#### Properties

| Property | Description                                                                                 | Default     | Platform |
| -------- | ------------------------------------------------------------------------------------------- | ----------- | -------- |
| `ref`    | Ref of the `BlurTarget` component to be identified by the `BlurView` component in the tree. | `undefined` | Android  |

### `VibrancyView`

The `VibrancyView` component is an extends the same properties of the a `View` component.

This component is available for **iOS only**. It applies a vibrancy effect to child content. On Android, the `VibrancyView` component is a common `View`. The `effectStyle` property **isn't supported** on tvOS.

#### Properties

| Property                           | Description                                                                  | Default     | Platform |
| ---------------------------------- | ---------------------------------------------------------------------------- | ----------- | -------- |
| `type`                             | [Blur type](#blur-types) of the overlay.                                     | `light`     | iOS      |
| `effectStyle`                      | [Effect style](#effect-styles) to vibrancy content.                          | `label`     | iOS      |
| `radius`                           | Blur radius `0` - `100`.                                                     | `10`        | iOS      |
| `overlayColor`                     | Add the overlay color about component.                                       | `undefined` | iOS      |
| `reducedTransparencyFallbackColor` | Background color about vibrancy effect when reduced transparency is enabled. | `white`     | iOS      |

When a value less than `0` or greater than `100` are provided for `radius` property, the `radius` is clipped.

## Types

These are all types of available.

### Blur Types

On iOS all types are supported, but, on Android is simulated the types using RGBA colors.

| Property                    | Description                                                                                                                                               | Platform |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `extra-light`               | The area of the view is lighter than the underlying view.                                                                                                 | All      |
| `light`                     | The area of the view is the same approximate lightness of the underlying view.                                                                            | All      |
| `dark`                      | The area of the view is darker than the underlying view.                                                                                                  | All      |
| `extra-dark`                | The area of the view is even more dark than the underlying view. (**tvOS >= 10**)                                                                         | All      |
| `regular`                   | A regular blur style that adapts to the user interface style. Radius **doesn't apply** to this. (**iOS >= 10**)                                           | All      |
| `prominent`                 | A blur style for making content more prominent that adapts to the user interface style. Radius **doesn't apply** to this. (**iOS >= 10**)                 | All      |
| `chrome-material`           | An adaptable blur effect that creates the appearance of the system chrome. Radius **doesn't apply** to this. (**iOS >= 13**)                              | All      |
| `material`                  | An adaptable blur effect that creates the appearance of a material with normal thickness. Radius **doesn't apply** to this. (**iOS >= 13**)               | All      |
| `thick-material`            | An adaptable blur effect that creates the appearance of a material that’s thicker than normal. Radius **doesn't apply** to this. (**iOS >= 13**)          | All      |
| `thin-material`             | An adaptable blur effect that creates the appearance of a thin material. Radius **doesn't apply** to this. (**iOS >= 13**)                                | All      |
| `ultra-thin-material`       | An adaptable blur effect that creates the appearance of an ultra-thin material. Radius **doesn't apply** to this. (**iOS >= 13**)                         | All      |
| `chrome-material-light`     | A blur effect that creates the appearance of the system chrome and is always light. Radius **doesn't apply** to this. (**iOS >= 13**)                     | All      |
| `material-light`            | A blur effect that creates the appearance of a material with normal thickness and is always light. Radius **doesn't apply** to this. (**iOS >= 13**)      | All      |
| `thick-material-light`      | A blur effect that creates the appearance of a material that’s thicker than normal and is always light. Radius **doesn't apply** to this. (**iOS >= 13**) | All      |
| `thin-material-light`       | A blur effect that creates the appearance of a thin material and is always light. Radius **doesn't apply** to this. (**iOS >= 13**)                       | All      |
| `ultra-thin-material-light` | A blur effect that creates the appearance of an ultra-thin material and is always light. Radius **doesn't apply** to this. (**iOS >= 13**)                | All      |
| `chrome-material-dark`      | A blur effect that creates the appearance of the system chrome and is always dark. Radius **doesn't apply** to this. (**iOS >= 13**)                      | All      |
| `material-dark`             | A blur effect that creates the appearance of a material with normal thickness and is always dark. Radius **doesn't apply** to this. (**iOS >= 13**)       | All      |
| `thick-material-dark`       | A blur effect that creates the appearance of a material that’s thicker than normal and is always dark. Radius **doesn't apply** to this. (**iOS >= 13**)  | All      |
| `thin-material-dark`        | A blur effect that creates the appearance of a thin material and is always dark. Radius **doesn't apply** to this. (**iOS >= 13**)                        | All      |
| `ultra-thin-material-dark`  | A blur effect that creates the appearance of an ultra-thin material and is always dark. Radius **doesn't apply** to this. (**iOS >= 13**)                 | All      |

Learn more about blur types [here](https://developer.apple.com/documentation/uikit/uiblureffect/style).

### Effect Styles

On iOS all effect styles are supported. This property is available in the `VibrancyView` component, it's **iOS only**.

| Property           | Description                                                                             | Platform |
| ------------------ | --------------------------------------------------------------------------------------- | -------- |
| `label`            | A style for labels containing primary content. (**iOS >= 13**)                          | iOS      |
| `secondary-label`  | A style for labels containing secondary content. (**iOS >= 13**)                        | iOS      |
| `tertiary-label`   | A style for labels containing tertiary content. (**iOS >= 13**)                         | iOS      |
| `quaternary-label` | A style for labels containing quaternary content. (**iOS >= 13**)                       | iOS      |
| `fill`             | A style for views with large filled areas containing primary content. (**iOS >= 13**)   | iOS      |
| `secondary-fill`   | A style for views with large filled areas containing secondary content. (**iOS >= 13**) | iOS      |
| `tertiary-fill`    | A style for views with large filled areas containing tertiary content. (**iOS >= 13**)  | iOS      |
| `separator`        | A style for separator lines. (**iOS >= 13**)                                            | iOS      |

- Label styles show progressive opacity drops from full white to near-invisible.
- Fill styles show translucent rectangles at decreasing opacity levels.
- Separator style is specifically for thin, translucent separator lines.

Learn more about effect styles [here](https://developer.apple.com/documentation/uikit/uivibrancyeffectstyle).

## Migrate to 3.x

> [!WARNING]
> Version 3.0.0 introduces significant API changes on Android and iOS applications. If you're upgrading from 2.x, please read this section carefully.

In version 3.0.0, the `x-light` blur `type` has been renamed to `extra-light` in the `BlurView` and `VibrancyView` components:

```tsx
// ❌ Old API (v2.x) - Deprecated
<BlurView blurTarget={targetRef} type='x-light' style={styles.blurView}>
  {/** ... **/}
</BlurView>

<VibrancyView blurTarget={targetRef} type='x-light' style={styles.vibrancyView}>
  {/** ... **/}
</VibrancyView>

// ✅ New API (v3.0.0) - Current
<BlurView blurTarget={targetRef} type='extra-light' style={styles.blurView}>
  {/** ... **/}
</BlurView>

<VibrancyView blurTarget={targetRef} type='extra-light' style={styles.vibrancyView}>
  {/** ... **/}
</VibrancyView>
```

A new `type` of blur called `extra-dark` has been added to the `BlurView` and `VibrancyView` components, below is a small example:

```tsx
// ✅ New type (v3.0.0) - Current
<BlurView blurTarget={targetRef} type="extra-dark" style={styles.blurView}>
  {/** ... **/}
</BlurView>
```

### Why This Change?

This version focused exclusively on full TV device support. The main changes are listed below:

- **New support**: Added full support for Android TV and Apple TV.
- **Types**: The `BlurView` and `VibrancyView` component types have undergone minor changes:
  - **Renaming**: Renamed `x-light` to `extra-light`.
  - **New type**: Added a new `extra-dark` type.
- **Runtime**: Bump Node.js version from `20.x` to `22.x`.

## Platform Differences

### Android

On Android platforms, the component utilizes the [BlurView](https://github.com/Dimezis/BlurView) library to offer native blur effects with hardware-accelerated rendering.

For different types of `extra-light`, `light`, `dark` and `extra-dark`, the `radius` is fixed at `35`. This is done to maintain similarity with the iOS effect.

The `androidColor` property can be useful when you want to achieve a specific look or match the blur effect to other elements in your app. It **overrides** the `type` property.

Bottom tabs customized with the [`react-navigation/bottom-tabs`](https://reactnavigation.org/docs/bottom-tab-navigator/) **aren't** supported! If you want to customize your bottom tabs, opt for [`@sbaiahmed1/react-native-blur`](https://github.com/sbaiahmed1/react-native-blur).

### iOS

On iOS all types are supported by default. However, on Android they are RGBA colors to simulate the same blur color.

The `extra-dark` blur type is not natively available on iOS, so it falls back to the `dark` blur type.

### tvOS

On tvOS, the blur types `extra-light`, `light`, `dark`, `extra-dark`, `regular`, and `prominent` are supported. Other blur types are accepted by the API but fall back to the `light` blur type on tvOS, since the underlying `UIBlurEffectStyle` values are unavailable.

The [effect styles](#effect-styles) **aren't** supported.

## Expo

In Expo, you need to convert to a [custom development build](https://docs.expo.dev/develop/development-builds/introduction/) or use [prebuild](https://docs.expo.dev/workflow/continuous-native-generation/). You can use also React Native without Expo.

## TypeScript Support

Full TypeScript support with proper type definitions!

```ts
import {
  BlurType,
  EffectStyle,
  BlurViewProps,
  BlurTargetProps,
  VibrancyProps,
} from '@danielsaraldi/react-native-blur-view';

export const INITIAL_BLUR_TYPE: BlurType = 'light';
export const INITIAL_EFFECT_STYLE: EffectStyle = 'label';

export interface CustomBlurViewProps extends BlurViewProps {
  // ...
}

export interface CustomBlurTargetProps extends BlurTargetProps {
  // ...
}

export interface CustomVibrancyViewProps extends VibrancyProps {
  // ...
}
```

## Others Libraries

- ✅ [`expo-blur`](https://docs.expo.dev/versions/latest/sdk/blur-view/) - A React component that blurs everything underneath the view. Common usage of this is for navigation bars, tab bars, and modals.
- ✅ [`@sbaiahmed1/react-native-blur`](https://github.com/sbaiahmed1/react-native-blur) - A modern React Native blur view component that provides native blur effects for both iOS and Android platforms. also adds progressive blur and liquidGlass.
- 🛑 [`@react-native-community/blur`](https://github.com/margelo/react-native-blur) - A component for UIVisualEffectView's blur and vibrancy effect on iOS, and BlurView on Android.

## Contributing

See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.

## License

MIT

---

Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob) ❤️
