0.3.2 • Published 7 months ago

glitzy-native v0.3.2

Weekly downloads
-
License
MIT
Repository
github
Last release
7 months ago

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

NameTypeDefaultDescription
isLoadingboolrequiredShows the skeleton bones when true
LinearGradientComponentReactComponentrequired for shiver animationThe gradient implementation to use for the "shiver" animation
layoutarray of objects[]A custom layout for the skeleton bones
durationnumber1200 msDuration of one cycle of animation
containerStyleobjectflex: 1The style applied to the View containing the bones
easingEasingbezier(0.5, 0, 0.25, 1)Easing of the bones animation
animationTypestring"shiver"The animation to be used for animating the bones (see demos below)
animationDirectionstring"horizontalRight" only for shiver animationTypeUsed only for shiver animation, describes the direction and end-point (ex: horizontalRight goes on the x-axis from left to right)
boneColorstring"#E1E9EE"Color of the bones
highlightColorstring"#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.

0.3.2

7 months ago

0.3.1

7 months ago

0.3.0

7 months ago

0.2.0

7 months ago

0.1.0

7 months ago

0.0.1

7 months ago