Implementation Guide

This comprehensive guide provides live demos and code examples for implementing peel effects in your React applications. Each example includes an interactive preview and copy-ready code snippets.

React Peel offers three main ways to create peel effects:

  1. Declarative Props - Use PeelWrapper props for static or controlled peels
  2. Presets - Pre-configured effects for common use cases
  3. Programmatic Control - Use the usePeel hook for animations and fine-grained control

Quick Start

The simplest way to create a peel effect:

1import { PeelWrapper, PeelTop, PeelBack, PeelBottom } from "react-peel";
2
3<PeelWrapper height={200} width={200} drag>
4  <PeelTop>Your top content</PeelTop>
5  <PeelBack>Back of the peel</PeelBack>
6  <PeelBottom>Hidden content revealed</PeelBottom>
7</PeelWrapper>;

Static Examples

Simple Peel

Basic peel effect with a static position:

1import { PeelWrapper, PeelTop, PeelBack, PeelBottom } from "react-peel";
2
3<PeelWrapper height={200} width={200} peelPosition={{ x: 80, y: 120 }}>
4  <PeelTop style={{ backgroundColor: "#81afcb" }} />
5  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
6  <PeelBottom style={{ backgroundColor: "#688394" }} />
7</PeelWrapper>;

Controlled Peel Position

Drive peel position directly from state:

1import React, { useState } from "react";
2import { PeelWrapper, PeelTop, PeelBack, PeelBottom } from "react-peel";
3
4function ControlledPosition() {
5  const [t, setT] = useState(0.4);
6  const size = 200;
7  const pos = { x: size - size * t, y: size - size * t };
8
9  return (
10    <div>
11      <input
12        type="range"
13        min="0"
14        max="1"
15        step="0.01"
16        value={t}
17        onChange={(e) => setT(Number(e.target.value))}
18      />
19      <PeelWrapper height={size} width={size} peelPosition={pos}>
20        <PeelTop style={{ backgroundColor: "#81afcb" }} />
21        <PeelBack style={{ backgroundColor: "#a0c7df" }} />
22        <PeelBottom style={{ backgroundColor: "#688394" }} />
23      </PeelWrapper>
24    </div>
25  );
26}

Corner Selection

Peel from different corners:

1// Top left corner
2<PeelWrapper corner="TOP_LEFT" height={160} width={160} peelPosition={{ x: 80, y: 70 }}>
3  <PeelTop style={{ backgroundColor: "#81afcb" }} />
4  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
5  <PeelBottom style={{ backgroundColor: "#688394" }} />
6</PeelWrapper>
7
8// Top right corner
9<PeelWrapper corner="TOP_RIGHT" height={160} width={160} peelPosition={{ x: 120, y: 70 }}>
10  <PeelTop style={{ backgroundColor: "#81afcb" }} />
11  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
12  <PeelBottom style={{ backgroundColor: "#688394" }} />
13</PeelWrapper>
14
15// Bottom left corner
16<PeelWrapper corner="BOTTOM_LEFT" height={160} width={160} peelPosition={{ x: 80, y: 130 }}>
17  <PeelTop style={{ backgroundColor: "#81afcb" }} />
18  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
19  <PeelBottom style={{ backgroundColor: "#688394" }} />
20</PeelWrapper>

Custom Shadows

Fine-tune shadow effects:

1<PeelWrapper
2  height={200}
3  width={200}
4  options={{
5    topShadow: false,
6    backShadowSize: 0.12,
7    bottomShadowDarkAlpha: 1,
8    bottomShadowLightAlpha: 0.4,
9  }}
10  peelPosition={{ x: 150, y: 0 }}
11>
12  <PeelTop style={{ backgroundColor: "#81afcb" }} />
13  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
14  <PeelBottom style={{ backgroundColor: "#688394" }} />
15</PeelWrapper>

Shiny Reflection

Add a reflective sheen to the back layer:

1<PeelWrapper
2  height={200}
3  width={200}
4  options={{
5    backReflection: true,
6    backReflectionAlpha: 0.3,
7  }}
8  peelPosition={{ x: 150, y: 0 }}
9>
10  <PeelTop style={{ backgroundColor: "#81afcb" }} />
11  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
12  <PeelBottom style={{ backgroundColor: "#688394" }} />
13</PeelWrapper>

Custom Shapes

React Peel supports custom SVG shapes for unique peel effects.

Circle Shape

Use SVG shapes for custom clipping:

1<PeelWrapper
2  options={{
3    shape: {
4      circle: { cx: 100, cy: 100, r: 100 },
5    },
6  }}
7  peelPosition={{ x: 100, y: 80 }}
8>
9  <PeelTop style={{ backgroundColor: "#81afcb" }} />
10  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
11  <PeelBottom style={{ backgroundColor: "#688394" }} />
12</PeelWrapper>

Polygon Shape (Pentagon)

Clip to a polygon:

1<PeelWrapper
2  options={{
3    shape: {
4      polygon: {
5        points: "100,0 200,70 160,200 40,200 0,70",
6      },
7    },
8  }}
9  peelPosition={{ x: 120, y: 60 }}
10>
11  <PeelTop style={{ backgroundColor: "#81afcb" }} />
12  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
13  <PeelBottom style={{ backgroundColor: "#688394" }} />
14</PeelWrapper>

Star Shape

Five-pointed star using polygon:

1<PeelWrapper
2  height={200}
3  width={200}
4  options={{
5    shape: {
6      polygon: {
7        points: "100,10 40,198 190,78 10,78 160,198",
8      },
9    },
10  }}
11  corner={{ x: 100, y: 198 }}
12  peelPosition={{ x: 140, y: 60 }}
13  drag
14>
15  <PeelTop style={{ backgroundColor: "#ffd700" }} />
16  <PeelBack style={{ backgroundColor: "#ffec8b" }} />
17  <PeelBottom style={{ backgroundColor: "#cd853f" }} />
18</PeelWrapper>

Heart Shape

Custom SVG path shape:

1<PeelWrapper
2  options={{
3    shape: {
4      path: {
5        d: "M101.26,31.42 C122.40,-11.27 173.11,1.11 183.01,11.84 C237.31,70.73 142.52,119.35 101.26,174.57 C51.81,119.35 -39.07,68.31 18.45,11.84 C33.18,-2.62 77.79,-11.27 101.26,31.42 Z",
6      },
7    },
8  }}
9  corner={{ x: 101, y: 175 }}
10  peelPosition={{ x: 150, y: 0 }}
11>
12  <PeelTop style={{ backgroundColor: "#81afcb" }} />
13  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
14  <PeelBottom style={{ backgroundColor: "#688394" }} />
15</PeelWrapper>

Ellipse Shape (via Path)

Oval shape using SVG path:

1<PeelWrapper
2  height={150}
3  width={250}
4  options={{
5    shape: {
6      path: {
7        d: "M125,10 C200,10 240,40 240,75 C240,110 200,140 125,140 C50,140 10,110 10,75 C10,40 50,10 125,10 Z",
8      },
9    },
10  }}
11  peelPosition={{ x: 180, y: 50 }}
12  drag
13>
14  <PeelTop style={{ backgroundColor: "#81afcb" }} />
15  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
16  <PeelBottom style={{ backgroundColor: "#688394" }} />
17</PeelWrapper>

Interactive Examples

Dragging

Enable mouse or touch dragging:

1<PeelWrapper height={200} width={200} drag>
2  <PeelTop style={{ backgroundColor: "#81afcb" }} />
3  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
4  <PeelBottom style={{ backgroundColor: "#688394" }} />
5</PeelWrapper>

Disabled State

Toggle interactions on and off:

1import React, { useState } from "react";
2import { PeelWrapper, PeelTop, PeelBack, PeelBottom } from "react-peel";
3
4function DisabledExample() {
5  const [disabled, setDisabled] = useState(true);
6
7  return (
8    <div>
9      <button onClick={() => setDisabled((value) => !value)}>
10        {disabled ? "Enable" : "Disable"}
11      </button>
12      <PeelWrapper height={200} width={200} drag disabled={disabled}>
13        <PeelTop style={{ backgroundColor: "#81afcb" }} />
14        <PeelBack style={{ backgroundColor: "#a0c7df" }} />
15        <PeelBottom style={{ backgroundColor: "#688394" }} />
16      </PeelWrapper>
17    </div>
18  );
19}

Press Handler

Handle taps or clicks without dragging:

Click
1import React, { useState } from "react";
2import { PeelWrapper, PeelTop, PeelBack, PeelBottom } from "react-peel";
3
4function PressHandlerExample() {
5  const [pressed, setPressed] = useState(false);
6
7  return (
8    <PeelWrapper
9      height={200}
10      width={200}
11      handlePress={() => setPressed((v) => !v)}
12    >
13      <PeelTop style={{ backgroundColor: "#81afcb", color: "#fff" }}>
14        {pressed ? "Pressed" : "Click"}
15      </PeelTop>
16      <PeelBack style={{ backgroundColor: "#a0c7df" }} />
17      <PeelBottom style={{ backgroundColor: "#688394" }} />
18    </PeelWrapper>
19  );
20}

Constrained Peel

Limit peel distance with constraints:

1<PeelWrapper constraints="BOTTOM_LEFT" drag>
2  <PeelTop style={{ backgroundColor: "#81afcb" }} />
3  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
4  <PeelBottom style={{ backgroundColor: "#688394" }} />
5</PeelWrapper>

Multiple Constraints

Apply multiple constraints for complex behavior:

1<PeelWrapper
2  height={200}
3  width={200}
4  constraints={["BOTTOM_LEFT", "BOTTOM_RIGHT"]}
5  drag
6>
7  <PeelTop style={{ backgroundColor: "#81afcb" }} />
8  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
9  <PeelBottom style={{ backgroundColor: "#688394" }} />
10</PeelWrapper>

Book Mode

Create a page-turning effect:

1<PeelWrapper height={160} width={130} mode="book" drag>
2  <PeelTop style={{ backgroundColor: "#81afcb" }} />
3  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
4  <PeelBottom style={{ backgroundColor: "#688394" }} />
5</PeelWrapper>

Calendar Mode

Top-edge constrained flip:

1<PeelWrapper height={200} width={150} mode="calendar" drag>
2  <PeelTop style={{ backgroundColor: "#81afcb" }} />
3  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
4  <PeelBottom style={{ backgroundColor: "#688394" }} />
5</PeelWrapper>

Fade Out Effect

Fade the top layer as it peels:

1<PeelWrapper fadeThreshold={0.9} drag>
2  <PeelTop style={{ backgroundColor: "#81afcb" }} />
3  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
4  <PeelBottom style={{ backgroundColor: "#688394" }} />
5</PeelWrapper>

Custom Drag Handler

Control behavior during drag:

1<PeelWrapper
2  fadeThreshold={0.9}
3  handleDrag={(evt, x, y, peel) => {
4    peel.setPeelPosition(x, y);
5    if (peel.getAmountClipped() >= 1) {
6      peel.removeEvents();
7    }
8  }}
9>
10  <PeelTop style={{ backgroundColor: "#81afcb" }} />
11  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
12  <PeelBottom style={{ backgroundColor: "#688394" }} />
13</PeelWrapper>

Gradient Background Peel

Use gradients for beautiful effects:

Peel Me!
🎉 Hidden Content!
1<PeelWrapper height={200} width={300} drag>
2  <PeelTop
3    style={{
4      backgroundImage: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
5      display: "flex",
6      alignItems: "center",
7      justifyContent: "center",
8      color: "#fff",
9      fontSize: "18px",
10      fontWeight: 600,
11    }}
12  >
13    Peel Me!
14  </PeelTop>
15  <PeelBack
16    style={{
17      backgroundImage: "linear-gradient(135deg, #f093fb 0%, #f5576c 100%)",
18    }}
19  />
20  <PeelBottom
21    style={{
22      backgroundImage: "linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)",
23      display: "flex",
24      alignItems: "center",
25      justifyContent: "center",
26      color: "#fff",
27      fontSize: "24px",
28      fontWeight: 600,
29    }}
30  >
31    🎉 Hidden Content!
32  </PeelBottom>
33</PeelWrapper>

Event Callbacks

React Peel provides callbacks to track peel state.

Progress Callback

Monitor peel progress in real-time:

Progress: 0%
1import React, { useState } from "react";
2import { PeelWrapper, PeelTop, PeelBack, PeelBottom } from "react-peel";
3
4function ProgressExample() {
5  const [progress, setProgress] = useState(0);
6
7  return (
8    <div>
9      <div>Progress: {(progress * 100).toFixed(0)}%</div>
10      <PeelWrapper
11        height={200}
12        width={200}
13        drag
14        onPeelProgress={(p) => setProgress(p)}
15      >
16        <PeelTop style={{ backgroundColor: "#81afcb" }} />
17        <PeelBack style={{ backgroundColor: "#a0c7df" }} />
18        <PeelBottom style={{ backgroundColor: "#688394" }} />
19      </PeelWrapper>
20    </div>
21  );
22}

Start/End Callbacks

Detect when peeling starts and ends:

Status: Ready
1import React, { useState } from "react";
2import { PeelWrapper, PeelTop, PeelBack, PeelBottom } from "react-peel";
3
4function EventCallbacksExample() {
5  const [status, setStatus] = useState("Ready");
6
7  return (
8    <div>
9      <div>Status: {status}</div>
10      <PeelWrapper
11        height={200}
12        width={200}
13        drag
14        onPeelStart={() => setStatus("Peeling started!")}
15        onPeelEnd={() => setStatus("Peeling ended!")}
16      >
17        <PeelTop style={{ backgroundColor: "#81afcb" }} />
18        <PeelBack style={{ backgroundColor: "#a0c7df" }} />
19        <PeelBottom style={{ backgroundColor: "#688394" }} />
20      </PeelWrapper>
21    </div>
22  );
23}

Path Animation Examples

Linear Path

Animate along a straight line:

1<PeelWrapper
2  peelPath={[200, 200, -200, -200]}
3  handleDrag={(evt, x, y, p) => {
4    const t = (x - p.width) / -p.width;
5    p.setTimeAlongPath(t);
6  }}
7>
8  <PeelTop style={{ backgroundColor: "#81afcb" }} />
9  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
10  <PeelBottom style={{ backgroundColor: "#688394" }} />
11</PeelWrapper>

Bezier Curve Path

Smooth curved path animation:

1<PeelWrapper
2  peelPath={[130, 160, 50, 60, -70, 210, -130, 160]}
3  handleDrag={(evt, x, y, p) => {
4    const t = (x - p.width) / (-p.width * 2);
5    p.setTimeAlongPath(t);
6  }}
7>
8  <PeelTop style={{ backgroundColor: "#81afcb" }} />
9  <PeelBack style={{ backgroundColor: "#a0c7df" }} />
10  <PeelBottom style={{ backgroundColor: "#688394" }} />
11</PeelWrapper>

Time Along Path

Control the peel with a slider:

1import React, { useState } from "react";
2import { PeelWrapper, PeelTop, PeelBack, PeelBottom } from "react-peel";
3
4function TimeAlongPathExample() {
5  const [t, setT] = useState(0.5);
6
7  return (
8    <div>
9      <input
10        type="range"
11        min="0"
12        max="1"
13        step="0.01"
14        value={t}
15        onChange={(e) => setT(Number(e.target.value))}
16      />
17      <PeelWrapper
18        height={200}
19        width={200}
20        peelPath={[200, 200, -200, -200]}
21        timeAlongPath={t}
22      >
23        <PeelTop style={{ backgroundColor: "#81afcb" }} />
24        <PeelBack style={{ backgroundColor: "#a0c7df" }} />
25        <PeelBottom style={{ backgroundColor: "#688394" }} />
26      </PeelWrapper>
27    </div>
28  );
29}

Using Presets

Presets provide pre-configured options for common use cases.

Available Presets

Preset Description
stickyNote Small corner curl like a sticky note
pageFlip Book-like page turn with spine constraint
revealCard Scratch-off style reveal
calendar Top-edge constrained calendar flip
envelope Envelope flap opening
giftCard Dramatic reveal with reflection
photoAlbum Smooth page turn for galleries
scratchCard Lottery ticket scratch-off

Sticky Note Preset

Remember to call mom

1import { PeelWrapper, PeelTop, PeelBack, PeelBottom } from "react-peel";
2
3<PeelWrapper preset="stickyNote" height={150} width={150} drag>
4  <PeelTop
5    style={{
6      backgroundColor: "#fff9c4",
7      padding: "12px",
8      fontFamily: "cursive",
9      color: "#333",
10    }}
11  >
12    Remember to call mom
13  </PeelTop>
14  <PeelBack style={{ backgroundColor: "#fff59d" }} />
15  <PeelBottom style={{ backgroundColor: "#78909c" }} />
16</PeelWrapper>;

Scratch Card Preset

Scratch to reveal

YOU WON

1<PeelWrapper preset="scratchCard" height={100} width={200} drag>
2  <PeelTop
3    style={{
4      backgroundColor: "#9e9e9e",
5      display: "flex",
6      alignItems: "center",
7      justifyContent: "center",
8      color: "#fff",
9    }}
10  >
11    Scratch to reveal
12  </PeelTop>
13  <PeelBack style={{ backgroundColor: "#bdbdbd" }} />
14  <PeelBottom
15    style={{
16      backgroundColor: "#4caf50",
17      display: "flex",
18      alignItems: "center",
19      justifyContent: "center",
20      color: "#fff",
21      fontSize: "24px",
22    }}
23  >
24    YOU WON
25  </PeelBottom>
26</PeelWrapper>

Preset Overrides

Override preset options to tune the look:

Gift Card

CODE-123

1<PeelWrapper
2  preset="giftCard"
3  height={160}
4  width={260}
5  drag
6  options={{
7    topShadowBlur: 8,
8    backReflection: true,
9    backReflectionAlpha: 0.35,
10  }}
11>
12  <PeelTop
13    style={{ backgroundColor: "#667eea", color: "#fff", padding: "16px" }}
14  >
15    Gift Card
16  </PeelTop>
17  <PeelBack style={{ backgroundColor: "#5e60ce" }} />
18  <PeelBottom style={{ backgroundColor: "#b39ddb", padding: "16px", color: "#1a1a2e" }}>
19    CODE-123
20  </PeelBottom>
21</PeelWrapper>

Using the usePeel Hook

The usePeel hook provides programmatic control over peel animations.

Hook API

1const { peelRef, animate, reset, setPosition, getProgress, stop, isAnimating } =
2  usePeel();
Method Description
peelRef

Ref to attach to PeelWrapper

animate(options) Animate peel to a position
reset() Reset to initial corner position
setPosition(x, y) Set position immediately
getProgress() Get current progress (0-1)
stop() Stop current animation
isAnimating() Check if animating

Animated Reveal

Click Reveal

...

1import React, { useState } from "react";
2import {
3  PeelWrapper,
4  PeelTop,
5  PeelBack,
6  PeelBottom,
7  usePeel,
8} from "react-peel";
9
10function AnimatedReveal() {
11  const { peelRef, animate, reset } = usePeel();
12  const [revealed, setRevealed] = useState(false);
13
14  const handleReveal = async () => {
15    await animate({
16      to: { x: -50, y: -50 },
17      duration: 800,
18      easing: "easeOut",
19      onProgress: (progress) => {
20        if (progress > 0.8) setRevealed(true);
21      },
22    });
23  };
24
25  return (
26    <div>
27      <div style={{ marginBottom: "16px" }}>
28        <button onClick={handleReveal}>Reveal</button>
29        <button
30          onClick={() => {
31            reset();
32            setRevealed(false);
33          }}
34        >
35          Reset
36        </button>
37      </div>
38
39      <PeelWrapper ref={peelRef} height={200} width={200}>
40        <PeelTop style={{ backgroundColor: "#90caf9", padding: "20px" }}>
41          <h3>Click Reveal</h3>
42        </PeelTop>
43        <PeelBack style={{ backgroundColor: "#64b5f6" }} />
44        <PeelBottom
45          style={{ backgroundColor: "#1976d2", color: "#fff", padding: "20px" }}
46        >
47          <h3>{revealed ? "Surprise" : "..."}</h3>
48        </PeelBottom>
49      </PeelWrapper>
50    </div>
51  );
52}

Sequential Animation

Chain multiple animations:

1import React from "react";
2import {
3  PeelWrapper,
4  PeelTop,
5  PeelBack,
6  PeelBottom,
7  usePeel,
8} from "react-peel";
9
10function SequentialAnimation() {
11  const { peelRef, animate, reset } = usePeel();
12
13  const runSequence = async () => {
14    // First peek
15    await animate({
16      to: { x: 150, y: 150 },
17      duration: 400,
18      easing: "easeOut",
19    });
20    // Pause
21    await new Promise((r) => setTimeout(r, 200));
22    // Pull back slightly
23    await animate({
24      to: { x: 180, y: 180 },
25      duration: 200,
26      easing: "easeIn",
27    });
28    // Full reveal
29    await animate({
30      to: { x: -50, y: -50 },
31      duration: 600,
32      easing: "easeOut",
33    });
34  };
35
36  return (
37    <div>
38      <button onClick={runSequence}>Run Sequence</button>
39      <button onClick={reset}>Reset</button>
40      <PeelWrapper ref={peelRef} height={200} width={200}>
41        <PeelTop style={{ backgroundColor: "#81afcb" }} />
42        <PeelBack style={{ backgroundColor: "#a0c7df" }} />
43        <PeelBottom style={{ backgroundColor: "#688394" }} />
44      </PeelWrapper>
45    </div>
46  );
47}

Hint Animation

1import React, { useEffect } from "react";
2import {
3  PeelWrapper,
4  PeelTop,
5  PeelBack,
6  PeelBottom,
7  usePeel,
8  peelHint,
9} from "react-peel";
10
11function HintExample() {
12  const { peelRef } = usePeel();
13
14  useEffect(() => {
15    const timer = setTimeout(async () => {
16      if (peelRef.current) {
17        await peelHint(peelRef.current, {
18          peekSize: 40,
19          duration: 400,
20          repeat: 3,
21        });
22      }
23    }, 1000);
24
25    return () => clearTimeout(timer);
26  }, [peelRef]);
27
28  return (
29    <PeelWrapper ref={peelRef} height={200} width={200} drag>
30      <PeelTop style={{ backgroundColor: "#81afcb" }} />
31      <PeelBack style={{ backgroundColor: "#a0c7df" }} />
32      <PeelBottom style={{ backgroundColor: "#688394" }} />
33    </PeelWrapper>
34  );
35}

Looping Animation

Create continuous peel animations:

1import React, { useEffect, useRef, useState } from "react";
2import {
3  PeelWrapper,
4  PeelTop,
5  PeelBack,
6  PeelBottom,
7  usePeel,
8  loopPeel,
9} from "react-peel";
10
11function LoopingAnimation() {
12  const { peelRef } = usePeel();
13  const stopRef = useRef(null);
14  const [isPlaying, setIsPlaying] = useState(false);
15
16  const handleToggle = () => {
17    if (isPlaying && stopRef.current) {
18      stopRef.current();
19      stopRef.current = null;
20      setIsPlaying(false);
21    } else if (peelRef.current) {
22      stopRef.current = loopPeel({
23        peel: peelRef.current,
24        path: [200, 200, 100, 0, 0, 100, -200, -200],
25        duration: 2000,
26        easing: "easeInOut",
27        pingPong: true,
28      });
29      setIsPlaying(true);
30    }
31  };
32
33  useEffect(() => {
34    return () => {
35      if (stopRef.current) stopRef.current();
36    };
37  }, []);
38
39  return (
40    <div>
41      <button onClick={handleToggle}>
42        {isPlaying ? "Stop" : "Start Loop"}
43      </button>
44      <PeelWrapper ref={peelRef} height={200} width={200}>
45        <PeelTop style={{ backgroundColor: "#81afcb" }} />
46        <PeelBack style={{ backgroundColor: "#a0c7df" }} />
47        <PeelBottom style={{ backgroundColor: "#688394" }} />
48      </PeelWrapper>
49    </div>
50  );
51}

Animation Options

Easing Functions

Available easing functions for animations:

Easing Description
linear No easing - constant speed
easeIn Slow start, fast end
easeOut Fast start, slow end
easeInOut Slow start and end
easeInQuad Quadratic ease in
easeOutQuad Quadratic ease out
easeInOutQuad Quadratic ease in/out
easeInExpo Exponential ease in
easeOutExpo Exponential ease out
spring Spring-like bounce
bounce Bouncy ending
backOut Slight overshoot

Animation Config

1await animate({
2  to: { x: 0, y: 0 }, // Target position
3  from: { x: 200, y: 200 }, // Optional start position
4  duration: 500, // Duration in ms
5  easing: "easeOut", // Easing function
6  onStart: () => {}, // Called when animation starts
7  onEnd: () => {}, // Called when animation ends
8  onProgress: (p) => {}, // Called each frame with progress (0-1)
9});

Real-World Examples

Check out these production-ready implementations:


Tips & Best Practices

Performance

  • Use drag prop for simple interactions instead of custom handleDrag
  • Prefer presets over custom options when possible
  • Avoid re-rendering during animations by using refs

Accessibility

  • Provide alternative ways to reveal hidden content
  • Use appropriate ARIA labels for interactive elements
  • Consider users who may not be able to perform drag gestures

Styling

  • Ensure sufficient contrast between layers
  • Test with different content lengths
  • Use consistent shadow settings across your app

Common Issues

Issue Solution
Peel not visible

Check height and width props are set

Drag not working

Ensure drag prop is true and disabled is not set

Animation choppy Reduce animation duration or simplify content
Wrong corner

Set corner prop explicitly