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:
- Declarative Props - Use
PeelWrapper props for static or controlled peels
- Presets - Pre-configured effects for common use cases
- 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:
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:
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:
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
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
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:
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
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 |