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

glitzy-native

v0.3.2

Published

A simple and fully customizable implementation of a skeleton placeholder for React Native

Downloads

90

Readme

Glitzy Native ✨ npm version

ℹ️ Note
This was originally a fork of react-native-skeleton-content-nonexpo, which depends on the gradient implementation in react-native-linear-gradient. It also resolves the issue with using Reanimated >= v2.0.0 and removes the hard requirement on Redash.

A simple and fully customizable implementation of a skeleton placeholder for React Native. Works on both iOS and Android.

Installation

bun add glitzy-native

or

yarn add glitzy-native

or

npm install glitzy-native

Also install reanimated which is used as the animation driver:

bun install react-native-reanimated

or

npm install react-native-reanimated

or

yarn add react-native-reanimated

Usage

This package exposes three different animationType: shiver, pulse and none. If you want to use the shiver animationType you would need to have a gradient package or implementation.

You have the flexibility of providing your own linear gradient implementation based on your project, all you need to do is to pass the implementation via the LinearGradientComponent prop. There are implementation files for common gradient packages like expo, skia and react-native-linear-gradient.

1. Import glitzy-native:

import { Glitzy } from "glitzy-native";

For shiver animation, you can import based on the default linear gradient implementations ⬇️

If you use expo workflow, install expo-linear-gradient and import like so:

import { Glitzy } from "glitzy-native/expo";

If you prefer to use @shopify/react-native-skia:

import { Glitzy } from "glitzy-native/skia";

If you prefer to use react-native-linear-gradient:

import { Glitzy } from "glitzy-native/native";

OR you can just provide your own gradient implementation and use it like so:

import { Glitzy } from "glitzy-native";
...
const Gradient = /* Your gradient implementation **/
...
  <Glitzy LinearGradientComponent={Gradient} {...props} />
...

2. Once you create the Skeleton, you have two options:

  • Child Layout : The component will figure out the layout of its bones with the dimensions of its direct children.
  • Custom Layout : You provide a prop layout to the component specifying the size of the bones (see the Examples section below). Here is the example with a custom layout. A key prop is optional but highly recommended.
export default function Placeholder() {
  return (
    <Glitzy.Layout
      containerStyle={{ flex: 1, width: 300 }}
      isLoading={false}
      renderContent={
        <>
          <Text style={styles.normalText}>Your content</Text>
          <Text style={styles.bigText}>Other content</Text>
        </>
      }
    >
      <Glitzy.Box key="someId" width={220} height={20} marginBottom={6} />
      <Glitzy.Box key="someOtherId" width={180} height={20} marginBottom={6} />
    </Glitzy.Layout>
  );
}

// OR

export default function Placeholder() {
  return (
    <Glitzy
      containerStyle={{ flex: 1, width: 300 }}
      isLoading={false}
      layout={[
        { key: "someId", width: 220, height: 20, marginBottom: 6 },
        { key: "someOtherId", width: 180, height: 20, marginBottom: 6 },
      ]}
    >
      <Text style={styles.normalText}>Your content</Text>
      <Text style={styles.bigText}>Other content</Text>
    </Glitzy>
  );
}

3. Then simply sync the prop isLoading to your state to show/hide the Skeleton when the assets/data are available to the user.

export default function Placeholder() {
  const [loading, setLoading] = useState(true);
  return (
    <Glitzy
      containerStyle={{ flex: 1, width: 300 }}
      isLoading={isLoading}
      {...otherProps}
    />
  );
}

Props

| Name | Type | Default | Description | | ----------------------- | ---------------- | --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | isLoading | bool | required | Shows the skeleton bones when true | | LinearGradientComponent | ReactComponent | required for shiver animation | The gradient implementation to use for the "shiver" animation | | layout | array of objects | [] | A custom layout for the skeleton bones | | duration | number | 1200 ms | Duration of one cycle of animation | | containerStyle | object | flex: 1 | The style applied to the View containing the bones | | easing | Easing | bezier(0.5, 0, 0.25, 1) | Easing of the bones animation | | animationType | string | "shiver" | The animation to be used for animating the bones (see demos below) | | animationDirection | string | "horizontalRight" only for shiver animationType | Used only for shiver animation, describes the direction and end-point (ex: horizontalRight goes on the x-axis from left to right) | | boneColor | string | "#E1E9EE" | Color of the bones | | highlightColor | string | "#F2F8FC" | Color of the highlight of the bones |

Examples

See the example app to experiment:

1 - Changing the direction of the animation (animationDirection prop) :

export default function Placeholder() {
  return (
    <Glitzy
      containerStyle={{ flex: 1, width: 300 }}
      animationDirection="horizontalLeft"
      isLoading={true}
      // ...
    />
  );
}

2 - Changing the colors and switching to "pulse" animation (boneColor, highlightColor and animationType prop) :

export default function Placeholder() {
  return (
    <Glitzy
      containerStyle={{ flex: 1, width: 300 }}
      boneColor="#121212"
      highlightColor="#333333"
      animationType="pulse"
      isLoading={true}
      // ...
    />
  );
}

3 - Customizing the layout of the bones :

There are 2 ways to customize the layout of the bones, either using the declarative API (via layout components) or imperatively by building your layout.

// Declarative:
export default function Placeholder() {
  return (
    <Glitzy.Layout
      containerStyle={{ flex: 1, width: 300 }}
      animationDirection="horizontalLeft"
      isLoading={true}
      // ...
    >
      {/** long line */}
      <Glitzy.Box width={220} height={20} marginBottom={6} />
      {/** short line */}
      <Glitzy.Box width={180} height={20} marginBottom={6} />
    </Glitzy.Layout>
  );
}

// Imperative:
export default function Placeholder() {
  return (
    <Glitzy
      containerStyle={{ flex: 1, width: 300 }}
      animationDirection="horizontalLeft"
      layout={[
        // long line
        { width: 220, height: 20, marginBottom: 6 },
        // short line
        { width: 180, height: 20, marginBottom: 6 },
        // ...
      ]}
      isLoading={true}
      // ...
    />
  );
}

4 - Syncing skeleton animations in groups

Say we have a group of Glitzy Skeletons that we want to visually keep their animation in sync no matter when any of them mounts, we can wrap these skeletons as children of Glitzy.Group

Before:

export default function Placeholder() {
  return (
    <>
      <Glitzy.Layout
        isLoading={true}
        // ...
      >
        <Glitzy.Box width={200}>{/** ... */}</Glitzy.Box>
      </Glitzy.Layout>
      <Glitzy
        layout={[
          {
            children: [
              //  ...
            ],
            width: 200,
          },
          // ...
        ]}
        isLoading={true}
        // ...
      />
    </>
  );
}

After:

export default function Placeholder() {
  return (
    <Glitzy.Group>
      <Glitzy.Layout
        isLoading={true}
        // ...
      >
        <Glitzy.Box width={200}>{/** ... */}</Glitzy.Box>
      </Glitzy.Layout>
      <Glitzy
        layout={[
          {
            children: [
              //  ...
            ],
            width: 200,
          },
          // ...
        ]}
        isLoading={true}
        // ...
      />
    </Glitzy.Group>
  );
}

In the before case (without group), the animation of each skeleton in the group is independent and kicks off when the skeleton mounts. In the after case (with group), the animation is controlled in a group so no matter when any skeleton is mounted within that group, its animation is kept in sync with the rest of the group.