├── .eslintrc.json ├── .github └── FUNDING.yml ├── .gitignore ├── .prettierrc.json ├── README.md ├── desktop.ini ├── jsconfig.json ├── next.config.mjs ├── package.json ├── pnpm-lock.yaml ├── postcss.config.mjs ├── public ├── assets │ ├── banner.png │ ├── desktop.png │ ├── mobile.png │ └── preview.mp4 └── images │ ├── favicon-dark.ico │ └── favicon-light.ico └── src ├── app ├── globals.css ├── layout.jsx └── page.jsx ├── components ├── common │ ├── ButtonCopy.jsx │ ├── ButtonSwitch.jsx │ └── TooltipList.jsx ├── effects │ ├── BottomBlur.jsx │ ├── TextBlurIn.jsx │ └── TextScroll.jsx ├── icons │ └── Favicon.jsx ├── layouts │ ├── Content.jsx │ ├── Footer.jsx │ ├── Header.jsx │ └── Hero.jsx └── snippets │ └── CodeViewer.jsx ├── hooks ├── useClickOutside.js ├── useInjectAnimations.js └── useTheme.js └── styles └── gradient-blur.css /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next", "next/core-web-vitals"] 3 | } 4 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [JhojanGgarcia] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | thanks_dev: # Replace with a single thanks.dev username 15 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["prettier-plugin-tailwindcss"] 3 | } 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Welcome to **Popply**, a refined animation library for tooltips—those subtle yet powerful UI elements that enhance user guidance and interaction. 4 | 5 | Tooltips are typically activated by a `mouseEnter` event. With **Popply**, bringing them to life is seamless and efficient. 6 | Simply copy the desired animation, place it into your `./styles` folder, and apply it to any tooltip that could use a touch of motion. 7 | 8 | Explore a curated collection of **50+ animations**, including `fadeIn`, `slideIn`, `flyIn`, `punchIn`, `zoomIn`, and many others—each designed to complement your user experience with precision. 9 | 10 | Start exploring and find the animation that best aligns with your design vision. 11 | 12 | 13 | 14 | # Preview 15 | 16 | By default, **Popply** animations are adaptive, this ensures smooth performance on all devices. 17 | However, tooltips often behave differently on desktop (hovering) and mobile (tapping), so it is important to preview them in both contexts. 18 | 19 | 20 | 21 | On mobile, consider triggering tooltips via ```onClick```, or accessibility-focused interactions. 22 | 23 | 24 | 25 | 26 | 27 | 28 | > [!IMPORTANT] 29 | > **Popply** is a free and open source project. 30 | > If you find it useful, please consider [donating](https://buymeacoffee.com/jhojanggar6). 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /desktop.ini: -------------------------------------------------------------------------------- 1 | [.ShellClassInfo] 2 | IconResource=C:\Users\USUARIO\Pictures\Logos\popply.ico,0 3 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "@/*": ["src/*"] 6 | } 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "popply", 3 | "version": "0.1.0", 4 | "type": "module", 5 | "private": true, 6 | "scripts": { 7 | "dev": "next dev", 8 | "build": "next build", 9 | "start": "next start", 10 | "lint": "next lint" 11 | }, 12 | "dependencies": { 13 | "@tailwindcss/postcss": "^4.0.15", 14 | "@vercel/speed-insights": "^1.2.0", 15 | "framer-motion": "^11.9.0", 16 | "lucide-react": "^0.483.0", 17 | "next": "^14.2.25", 18 | "postcss": "^8.5.3", 19 | "react": "^18.3.1", 20 | "react-dom": "^18.3.1", 21 | "react-syntax-highlighter": "^15.6.1", 22 | "tailwindcss": "^4.0.15" 23 | }, 24 | "devDependencies": { 25 | "@types/node": "^22.7.4", 26 | "@types/react": "18.3.3", 27 | "eslint": "^8.57.1", 28 | "eslint-config-next": "14.2.3", 29 | "eslint-import-resolver-alias": "^1.1.2", 30 | "eslint-plugin-import": "^2.31.0", 31 | "prettier": "^3.5.3", 32 | "prettier-plugin-tailwindcss": "^0.6.11", 33 | "shiki": "^1.20.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | "@tailwindcss/postcss": {}, 5 | }, 6 | }; 7 | export default config; 8 | -------------------------------------------------------------------------------- /public/assets/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JhojanGgarcia/PopplyLibrary/8fde4baa642f311e1c631e9dc5a51c780e5f819e/public/assets/banner.png -------------------------------------------------------------------------------- /public/assets/desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JhojanGgarcia/PopplyLibrary/8fde4baa642f311e1c631e9dc5a51c780e5f819e/public/assets/desktop.png -------------------------------------------------------------------------------- /public/assets/mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JhojanGgarcia/PopplyLibrary/8fde4baa642f311e1c631e9dc5a51c780e5f819e/public/assets/mobile.png -------------------------------------------------------------------------------- /public/assets/preview.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JhojanGgarcia/PopplyLibrary/8fde4baa642f311e1c631e9dc5a51c780e5f819e/public/assets/preview.mp4 -------------------------------------------------------------------------------- /public/images/favicon-dark.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JhojanGgarcia/PopplyLibrary/8fde4baa642f311e1c631e9dc5a51c780e5f819e/public/images/favicon-dark.ico -------------------------------------------------------------------------------- /public/images/favicon-light.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JhojanGgarcia/PopplyLibrary/8fde4baa642f311e1c631e9dc5a51c780e5f819e/public/images/favicon-light.ico -------------------------------------------------------------------------------- /src/app/globals.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | @custom-variant dark (&:where(.dark, .dark *)); 3 | 4 | /* Custom scrollbar styles */ 5 | ::-webkit-scrollbar { 6 | width: 3px; 7 | height: 3px; 8 | } 9 | 10 | ::-webkit-scrollbar-thumb { 11 | background-color: #323232; 12 | border-radius: 10px; 13 | -webkit-border-radius: 10px; 14 | -moz-border-radius: 10px; 15 | -ms-border-radius: 10px; 16 | -o-border-radius: 10px; 17 | } 18 | 19 | ::-webkit-scrollbar { 20 | width: 4px; 21 | height: 4px; 22 | } 23 | 24 | ::-webkit-scrollbar-thumb { 25 | background-color: #bfb3dc77; 26 | border-radius: 10px; 27 | } 28 | 29 | ::-webkit-scrollbar-thumb:hover { 30 | background-color: #222121a1; 31 | } 32 | 33 | ::-webkit-scrollbar-track { 34 | background-color: #0f0f0f; 35 | } 36 | 37 | .dark ::-webkit-scrollbar-thumb { 38 | background-color: #bfb3dc; 39 | } 40 | 41 | .dark ::-webkit-scrollbar-track { 42 | background-color: #fff; 43 | } 44 | 45 | html { 46 | position: relative; 47 | } 48 | -------------------------------------------------------------------------------- /src/app/layout.jsx: -------------------------------------------------------------------------------- 1 | import { Bricolage_Grotesque } from "next/font/google"; 2 | import { SpeedInsights } from "@vercel/speed-insights/next" 3 | import "./globals.css"; 4 | 5 | const bricolageFont = Bricolage_Grotesque({ 6 | subsets: ["latin"], 7 | variable: "--font-bricolage", 8 | weight: ["200", "300", "400", "500", "600", "700", "800"], 9 | }); 10 | 11 | export const metadata = { 12 | title: "Popply library", 13 | description: "Components about animations and Effects for your website.", 14 | icons: { 15 | icon: [ 16 | { 17 | media: "(prefers-color-scheme: light)", 18 | url: "/images/favicon-dark.ico", 19 | href: "/images/favicon-dark.ico", 20 | }, 21 | { 22 | media: "(prefers-color-scheme: dark)", 23 | url: "/images/favicon-light.ico", 24 | href: "/images/favicon-light.ico", 25 | }, 26 | ], 27 | }, 28 | }; 29 | 30 | export default function RootLayout({ children }) { 31 | return ( 32 | 33 | 37 | {children} 38 | 39 | 40 | 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /src/app/page.jsx: -------------------------------------------------------------------------------- 1 | import Header from "@/components/layouts/Header"; 2 | import Hero from "@/components/layouts/Hero"; 3 | import Content from "@/components/layouts/Content"; 4 | import Footer from "@/components/layouts/Footer"; 5 | 6 | export default function Home() { 7 | return ( 8 |
9 |
10 |
11 | 12 |
13 | 14 |
15 |
16 | 17 |
18 | 19 |
20 |
21 | 22 |
23 |
24 |
25 |
26 |
27 |
28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /src/components/common/ButtonCopy.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useCallback, useState } from "react"; 4 | import { Check, Copy, LoaderCircle } from "lucide-react"; 5 | import { AnimatePresence, motion } from "framer-motion"; 6 | 7 | const buttonCopy = { 8 | idle: , 9 | loading: , 10 | success: , 11 | }; 12 | 13 | export default function ButtonCopy({ onClick }) { 14 | const [buttonState, setButtonState] = useState("idle"); 15 | 16 | const handleClick = useCallback(() => { 17 | setButtonState("loading"); 18 | setTimeout(() => { 19 | setButtonState("success"); 20 | }, 1000); 21 | 22 | setTimeout(() => { 23 | setButtonState("idle"); 24 | }, 3000); 25 | }, []); 26 | 27 | return ( 28 |
29 | 51 |
52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /src/components/common/ButtonSwitch.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React from "react"; 4 | 5 | import useTheme from "@/hooks/useTheme"; 6 | import { Moon, Sun } from "lucide-react"; 7 | import { motion } from "framer-motion"; 8 | 9 | export default function Switch() { 10 | const { theme, toggleTheme } = useTheme(); 11 | return ( 12 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /src/components/common/TooltipList.jsx: -------------------------------------------------------------------------------- 1 | import Favicon from "@/components/icons/Favicon"; 2 | import Image from "next/image"; 3 | 4 | const TooltipContent = [ 5 | { 6 | name: "fadeIn", 7 | category: "fade", 8 | css: ` 9 | .fadein { 10 | animation: fade-in 1s ease-in-out; 11 | -webkit-animation: fade-in 1s ease-in-out; 12 | } 13 | @keyframes fade-in { 14 | from { 15 | opacity: 0; 16 | } 17 | to { 18 | opacity: 1; 19 | } 20 | } 21 | `, 22 | tooltipContainer: () => { 23 | return ( 24 |
25 | 26 |
27 | ); 28 | }, 29 | tooltipSample: () => { 30 | return ( 31 |
32 | Sample 33 |
34 | ); 35 | }, 36 | }, 37 | { 38 | name: "fadeInDown", 39 | category: "fade", 40 | css: ` 41 | .fadeindown { 42 | animation: fade-in-down 1s ease-in; 43 | -webkit-animation: fade-in-down 1s ease-in; 44 | } 45 | @keyframes fade-in-down { 46 | from { 47 | opacity: 0; 48 | -webkit-transform: translate3d(0, -100%, 0); 49 | transform: translate3d(0, -100%, 0); 50 | } 51 | to { 52 | opacity: 1; 53 | -webkit-transform: translate3d(0, 0, 0); 54 | transform: translate3d(0, 0, 0); 55 | } 56 | } 57 | `, 58 | tooltipContainer: () => { 59 | return ( 60 |
61 | 62 |
63 | ); 64 | }, 65 | tooltipSample: () => { 66 | return ( 67 |
68 | Sample 69 |
70 | ); 71 | }, 72 | }, 73 | { 74 | name: "fadeInLeft", 75 | category: "fade", 76 | css: ` 77 | .fadeinleft { 78 | animation: fade-in-left 1s ease-in-out; 79 | -webkit-animation: fade-in-left 1s ease-in-out; 80 | } 81 | @keyframes fade-in-left { 82 | from { 83 | opacity: 0; 84 | -webkit-transform: translate3d(-100%, 0, 0); 85 | transform: translate3d(-100%, 0, 0); 86 | } 87 | to { 88 | opacity: 1; 89 | -webkit-transform: translate3d(0, 0, 0); 90 | transform: translate3d(0, 0, 0); 91 | } 92 | } 93 | `, 94 | tooltipContainer: () => { 95 | return ( 96 |
97 | 98 |
99 | ); 100 | }, 101 | tooltipSample: () => { 102 | return ( 103 |
104 | Sample 105 |
106 | ); 107 | }, 108 | }, 109 | { 110 | name: "fadeInRight", 111 | category: "fade", 112 | css: ` 113 | .fadeinright { 114 | animation: fade-in-right 1s ease-in-out; 115 | -webkit-animation: fade-in-right 1s ease-in-out; 116 | } 117 | @keyframes fade-in-right { 118 | from { 119 | opacity: 0; 120 | -webkit-transform: translate3d(100%, 0, 0); 121 | transform: translate3d(100%, 0, 0); 122 | } 123 | to { 124 | opacity: 1; 125 | -webkit-transform: translate3d(0, 0, 0); 126 | transform: translate3d(0, 0, 0); 127 | } 128 | } 129 | `, 130 | tooltipContainer: () => { 131 | return ( 132 |
133 | 134 |
135 | ); 136 | }, 137 | tooltipSample: () => { 138 | return ( 139 |
140 | Sample 141 |
142 | ); 143 | }, 144 | }, 145 | { 146 | name: "fadeInUp", 147 | category: "fade", 148 | css: ` 149 | .fadeinup { 150 | animation: fade-in-up 1s ease-in-out; 151 | -webkit-animation: fade-in-up 1s ease-in-out; 152 | } 153 | @keyframes fade-in-up { 154 | from { 155 | opacity: 0; 156 | -webkit-transform: translate3d(0, -100%, 0); 157 | transform: translate3d(0, -100%, 0); 158 | } 159 | to { 160 | opacity: 1; 161 | -webkit-transform: translate3d(0, 0, 0); 162 | transform: translate3d(0, 0, 0); 163 | } 164 | } 165 | `, 166 | 167 | tooltipContainer: () => { 168 | return ( 169 |
170 | 171 |
172 | ); 173 | }, 174 | tooltipSample: () => { 175 | return ( 176 |
177 | Sample 178 |
179 | ); 180 | }, 181 | }, 182 | { 183 | name: "fadeOut", 184 | category: "fade", 185 | css: ` 186 | .fadeout { 187 | animation: fade-out 1s ease-out; 188 | -webkit-animation: fade-out 1s ease-out; 189 | } 190 | @keyframes fade-out { 191 | from { 192 | opacity: 1; 193 | } 194 | to { 195 | opacity: 0; 196 | } 197 | } 198 | `, 199 | 200 | tooltipContainer: () => { 201 | return ( 202 |
203 | 204 |
205 | ); 206 | }, 207 | tooltipSample: () => { 208 | return ( 209 |
210 | Sample 211 |
212 | ); 213 | }, 214 | }, 215 | { 216 | name: "fadeOutDown", 217 | category: "fade", 218 | css: ` 219 | .fadeoutdown { 220 | animation: fade-out-down 1s ease-out; 221 | -webkit-animation: fade-out-down 1s ease-out; 222 | } 223 | @keyframes fade-out-down { 224 | from { 225 | opacity: 1; 226 | } 227 | to { 228 | opacity: 0; 229 | } 230 | } 231 | `, 232 | tooltipContainer: () => { 233 | return ( 234 |
235 | 236 |
237 | ); 238 | }, 239 | tooltipSample: () => { 240 | return ( 241 |
242 | Sample 243 |
244 | ); 245 | }, 246 | }, 247 | { 248 | name: "fadeOutLeft", 249 | category: "fade", 250 | css: ` 251 | .fadeoutleft { 252 | animation: fade-out-left 1s ease-out; 253 | -webkit-animation: fade-out-left 1s ease-out; 254 | } 255 | @keyframes fade-out-left { 256 | from { 257 | opacity: 1; 258 | } 259 | to { 260 | opacity: 0; 261 | }} 262 | `, 263 | tooltipContainer: () => { 264 | return ( 265 |
266 | 267 |
268 | ); 269 | }, 270 | tooltipSample: () => { 271 | return ( 272 |
273 | Sample 274 |
275 | ); 276 | }, 277 | }, 278 | { 279 | name: "fadeOutRight", 280 | category: "fade", 281 | css: ` 282 | .fadeoutright { 283 | animation: fade-out-right 1s ease-out; 284 | -webkit-animation: fade-out-right 1s ease-out; 285 | } 286 | @keyframes fade-out-right { 287 | from { 288 | opacity: 1; 289 | } 290 | to { 291 | opacity: 0; 292 | }} 293 | `, 294 | tooltipContainer: () => { 295 | return ( 296 |
297 | 298 |
299 | ); 300 | }, 301 | tooltipSample: () => { 302 | return ( 303 |
304 | Sample 305 |
306 | ); 307 | }, 308 | }, 309 | { 310 | name: "fadeOutUp", 311 | category: "fade", 312 | css: ` 313 | .fadeoutup { 314 | animation: fade-out-up 1s ease-out; 315 | -webkit-animation: fade-out-up 1s ease-out; 316 | } 317 | @keyframes fade-out-up { 318 | from { 319 | opacity: 1; 320 | } 321 | to { 322 | opacity: 0; 323 | }} 324 | `, 325 | tooltipContainer: () => { 326 | return ( 327 |
328 | 329 |
330 | ); 331 | }, 332 | tooltipSample: () => { 333 | return ( 334 |
335 | Sample 336 |
337 | ); 338 | }, 339 | }, 340 | { 341 | name: "slideInDown", 342 | category: "slide", 343 | css: ` 344 | .slideindown { 345 | animation: slide-in-down 1s ease-out; 346 | -webkit-animation: slide-in-down 1s ease-out; 347 | } 348 | @keyframes slide-in-down { 349 | from { 350 | opacity: 0; 351 | transform: translate3d(0, -100%, 0); 352 | } 353 | to { 354 | opacity: 1; 355 | transform: translate3d(0, 0, 0); 356 | } 357 | } 358 | `, 359 | tooltipContainer: () => { 360 | return ( 361 |
362 | 363 |
364 | ); 365 | }, 366 | tooltipSample: () => { 367 | return ( 368 |
369 | Sample 370 |
371 | ); 372 | }, 373 | }, 374 | { 375 | name: "slideInLeft", 376 | category: "slide", 377 | css: ` 378 | .slideinleft { 379 | animation: slide-in-left 1s ease-out; 380 | -webkit-animation: slide-in-left 1s ease-out; 381 | } 382 | @keyframes slide-in-left { 383 | from { 384 | opacity: 0; 385 | transform: translate3d(-100%, 0, 0); 386 | } 387 | to { 388 | opacity: 1; 389 | transform: translate3d(0, 0, 0); 390 | } 391 | } 392 | `, 393 | tooltipContainer: () => { 394 | return ( 395 |
396 | 397 |
398 | ); 399 | }, 400 | tooltipSample: () => { 401 | return ( 402 |
403 | Sample 404 |
405 | ); 406 | }, 407 | }, 408 | { 409 | name: "slideInRight", 410 | category: "slide", 411 | css: ` 412 | .slideinright { 413 | animation: slide-in-right 1s ease-out; 414 | -webkit-animation: slide-in-right 1s ease-out; 415 | } 416 | @keyframes slide-in-right { 417 | from { 418 | opacity: 0; 419 | transform: translate3d(100%, 0, 0); 420 | } 421 | to { 422 | opacity: 1; 423 | transform: translate3d(0, 0, 0); 424 | } 425 | } 426 | `, 427 | tooltipContainer: () => { 428 | return ( 429 |
430 | 431 |
432 | ); 433 | }, 434 | tooltipSample: () => { 435 | return ( 436 |
437 | Sample 438 |
439 | ); 440 | }, 441 | }, 442 | { 443 | name: "slideInUp", 444 | category: "slide", 445 | css: ` 446 | .slideinup { 447 | animation: slide-in-up 1s ease-out; 448 | -webkit-animation: slide-in-up 1s ease-out; 449 | } 450 | @keyframes slide-in-up { 451 | from { 452 | opacity: 0; 453 | transform: translate3d(0, 100%, 0); 454 | } 455 | to { 456 | opacity: 1; 457 | transform: translate3d(0, 0, 0); 458 | } 459 | } 460 | `, 461 | tooltipContainer: () => { 462 | return ( 463 |
464 | 465 |
466 | ); 467 | }, 468 | tooltipSample: () => { 469 | return ( 470 |
471 | Sample 472 |
473 | ); 474 | }, 475 | }, 476 | { 477 | name: "slideOutDown", 478 | category: "slide", 479 | css: ` 480 | .slideoutdown { 481 | animation: slide-out-down 1s ease-out; 482 | -webkit-animation: slide-out-down 1s ease-out; 483 | } 484 | @keyframes slide-out-down { 485 | from { 486 | opacity: 1; 487 | transform: translate3d(0, 0, 0); 488 | } 489 | to { 490 | opacity: 0; 491 | transform: translate3d(0, 100%, 0); 492 | } 493 | } 494 | `, 495 | tooltipContainer: () => { 496 | return ( 497 |
498 | 499 |
500 | ); 501 | }, 502 | tooltipSample: () => { 503 | return ( 504 |
505 | Sample 506 |
507 | ); 508 | }, 509 | }, 510 | { 511 | name: "slideOutLeft", 512 | category: "slide", 513 | css: ` 514 | .slideoutleft { 515 | animation: slide-out-left 1s ease-out; 516 | -webkit-animation: slide-out-left 1s ease-out; 517 | } 518 | @keyframes slide-out-left { 519 | from { 520 | opacity: 1; 521 | transform: translate3d(0, 0, 0); 522 | } 523 | to { 524 | opacity: 0; 525 | transform: translate3d(-100%, 0, 0); 526 | } 527 | } 528 | `, 529 | tooltipContainer: () => { 530 | return ( 531 |
532 | 533 |
534 | ); 535 | }, 536 | tooltipSample: () => { 537 | return ( 538 |
539 | Sample 540 |
541 | ); 542 | }, 543 | }, 544 | { 545 | name: "slideOutRight", 546 | category: "slide", 547 | css: ` 548 | .slideoutright { 549 | animation: slide-out-right 1s ease-out; 550 | -webkit-animation: slide-out-right 1s ease-out; 551 | } 552 | @keyframes slide-out-right { 553 | from { 554 | opacity: 1; 555 | transform: translate3d(0, 0, 0); 556 | } 557 | to { 558 | opacity: 0; 559 | transform: translate3d(100%, 0, 0); 560 | } 561 | } 562 | `, 563 | tooltipContainer: () => { 564 | return ( 565 |
566 | 567 |
568 | ); 569 | }, 570 | tooltipSample: () => { 571 | return ( 572 |
573 | Sample 574 |
575 | ); 576 | }, 577 | }, 578 | { 579 | name: "slideOutUp", 580 | category: "slide", 581 | css: ` 582 | .slideoutup { 583 | animation: slide-out-up 1s ease-out; 584 | -webkit-animation: slide-out-up 1s ease-out; 585 | } 586 | @keyframes slide-out-up { 587 | from { 588 | opacity: 1; 589 | transform: translate3d(0, 0, 0); 590 | } 591 | to { 592 | opacity: 0; 593 | transform: translate3d(0, -100%, 0); 594 | } 595 | } 596 | `, 597 | tooltipContainer: () => { 598 | return ( 599 |
600 | 601 |
602 | ); 603 | }, 604 | tooltipSample: () => { 605 | return ( 606 |
607 | Sample 608 |
609 | ); 610 | }, 611 | }, 612 | { 613 | name: "slideDown", 614 | category: "slide", 615 | css: ` 616 | .slidedown { 617 | animation: slide-down 1s ease-out; 618 | -webkit-animation: slide-down 1s ease-out; 619 | } 620 | @keyframes slide-down { 621 | from { 622 | opacity: 0; 623 | transform: translate3d(0, -100%, 0); 624 | } 625 | to { 626 | opacity: 1; 627 | transform: translate3d(0, 0, 0); 628 | } 629 | } 630 | `, 631 | tooltipContainer: () => { 632 | return ( 633 |
634 | 635 |
636 | ); 637 | }, 638 | tooltipSample: () => { 639 | return ( 640 |
641 | Sample 642 |
643 | ); 644 | }, 645 | }, 646 | { 647 | name: "slideLeft", 648 | category: "slide", 649 | css: ` 650 | .slideleft { 651 | animation: slide-left 1s ease-out; 652 | -webkit-animation: slide-left 1s ease-out; 653 | } 654 | @keyframes slide-left { 655 | from { 656 | opacity: 0; 657 | transform: translate3d(-100%, 0, 0); 658 | } 659 | to { 660 | opacity: 1; 661 | transform: translate3d(0, 0, 0); 662 | } 663 | } 664 | `, 665 | tooltipContainer: () => { 666 | return ( 667 |
668 | 669 |
670 | ); 671 | }, 672 | tooltipSample: () => { 673 | return ( 674 |
675 | Sample 676 |
677 | ); 678 | }, 679 | }, 680 | { 681 | name: "slideRight", 682 | category: "slide", 683 | css: ` 684 | .slideright { 685 | animation: slide-right 1s ease-out; 686 | -webkit-animation: slide-right 1s ease-out; 687 | } 688 | @keyframes slide-right { 689 | from { 690 | opacity: 0; 691 | transform: translate3d(100%, 0, 0); 692 | } 693 | to { 694 | opacity: 1; 695 | transform: translate3d(0, 0, 0); 696 | } 697 | } 698 | `, 699 | tooltipContainer: () => { 700 | return ( 701 |
702 | 703 |
704 | ); 705 | }, 706 | tooltipSample: () => { 707 | return ( 708 |
709 | Sample 710 |
711 | ); 712 | }, 713 | }, 714 | { 715 | name: "slideUp", 716 | category: "slide", 717 | css: ` 718 | .slideup { 719 | animation: slide-up 1s ease-out; 720 | -webkit-animation: slide-up 1s ease-out; 721 | } 722 | @keyframes slide-up { 723 | from { 724 | opacity: 0; 725 | transform: translate3d(0, 100%, 0); 726 | } 727 | to { 728 | opacity: 1; 729 | transform: translate3d(0, 0, 0); 730 | } 731 | } 732 | `, 733 | tooltipContainer: () => { 734 | return ( 735 |
736 | 737 |
738 | ); 739 | }, 740 | tooltipSample: () => { 741 | return ( 742 |
743 | Sample 744 |
745 | ); 746 | }, 747 | }, 748 | { 749 | name: "zoomIn", 750 | category: "zoom", 751 | css: ` 752 | .zoomin { 753 | animation: zoom-in 1s ease-out; 754 | -webkit-animation: zoom-in 1s ease-out; 755 | } 756 | @keyframes zoom-in { 757 | from { 758 | opacity: 0; 759 | transform: scale(0); 760 | } 761 | to { 762 | opacity: 1; 763 | transform: scale(1); 764 | } 765 | } 766 | `, 767 | tooltipContainer: () => { 768 | return ( 769 |
770 | 771 |
772 | ); 773 | }, 774 | tooltipSample: () => { 775 | return ( 776 |
777 | Sample 778 |
779 | ); 780 | }, 781 | }, 782 | { 783 | name: "zoomOut", 784 | category: "zoom", 785 | css: ` 786 | .zoomout { 787 | animation: zoom-out 1s ease-out; 788 | -webkit-animation: zoom-out 1s ease-out; 789 | } 790 | @keyframes zoom-out { 791 | from { 792 | opacity: 1; 793 | transform: scale(1); 794 | } 795 | to { 796 | opacity: 0; 797 | transform: scale(0); 798 | } 799 | } 800 | `, 801 | tooltipContainer: () => { 802 | return ( 803 |
804 | 805 |
806 | ); 807 | }, 808 | tooltipSample: () => { 809 | return ( 810 |
811 | Sample 812 |
813 | ); 814 | }, 815 | }, 816 | { 817 | name: "Tada", 818 | category: "special", 819 | css: ` 820 | .tada { 821 | animation: tada 1s ease-out; 822 | -webkit-animation: tada 1s ease-out; 823 | } 824 | @keyframes tada { 825 | 0% { 826 | transform: scale3d(1, 1, 1); 827 | } 828 | 10%, 829 | 20% { 830 | transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); 831 | } 832 | 30%, 833 | 50%, 834 | 70%, 835 | 90% { 836 | transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); 837 | } 838 | 40%, 839 | 60%, 840 | 80% { 841 | transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); 842 | } 843 | 100% { 844 | transform: scale3d(1, 1, 1); 845 | } 846 | } 847 | `, 848 | tooltipContainer: () => { 849 | return ( 850 |
851 | 852 |
853 | ); 854 | }, 855 | tooltipSample: () => { 856 | return ( 857 |
858 | Sample 859 |
860 | ); 861 | }, 862 | }, 863 | { 864 | name: "spinnerGrow", 865 | category: "special", 866 | css: ` 867 | .spinnergrow { 868 | animation: spinner-grow 1s ease-out infinite; 869 | -webkit-animation: spinner-grow 1s ease-out infinite; 870 | transform-origin: center; 871 | display: inline-block; 872 | } 873 | 874 | @keyframes spinner-grow { 875 | 0% { 876 | transform: scale(0); 877 | opacity: 0.2; 878 | } 879 | 50% { 880 | transform: scale(1.1); 881 | opacity: 1; 882 | } 883 | 100% { 884 | transform: scale(0.95); 885 | opacity: 0; 886 | } 887 | } 888 | `, 889 | tooltipContainer: () => { 890 | return ( 891 |
892 | 893 |
894 | ); 895 | }, 896 | tooltipSample: () => { 897 | return ( 898 |
899 | Sample 900 |
901 | ); 902 | }, 903 | }, 904 | { 905 | name: "spinnerShrink", 906 | category: "special", 907 | css: ` 908 | .spinnershrink { 909 | animation: spinner-shrink 1s ease-in-out forwards; 910 | -webkit-animation: spinner-shrink 1s ease-in-out forwards; 911 | transform-origin: center; 912 | display: inline-block; 913 | } 914 | 915 | @keyframes spinner-shrink { 916 | 0% { 917 | transform: scale(1); 918 | opacity: 1; 919 | } 920 | 50% { 921 | transform: scale(0.8); 922 | opacity: 0.7; 923 | } 924 | 100% { 925 | transform: scale(0); 926 | opacity: 0; 927 | } 928 | } 929 | `, 930 | tooltipContainer: () => { 931 | return ( 932 |
933 | 934 |
935 | ); 936 | }, 937 | tooltipSample: () => { 938 | return ( 939 |
940 | Sample 941 |
942 | ); 943 | }, 944 | }, 945 | { 946 | name: "fadeInTopLeft", 947 | category: "fade", 948 | css: ` 949 | .fadeintopleft { 950 | animation: fade-in-top-left 1s ease-out; 951 | -webkit-animation: fade-in-top-left 1s ease-out; 952 | } 953 | @keyframes fade-in-top-left { 954 | from { 955 | opacity: 0; 956 | transform: translate3d(-100%, -100%, 0); 957 | } 958 | to { 959 | opacity: 1; 960 | transform: translate3d(0, 0, 0); 961 | } 962 | } 963 | `, 964 | tooltipContainer: () => { 965 | return ( 966 |
967 | 968 |
969 | ); 970 | }, 971 | tooltipSample: () => { 972 | return ( 973 |
974 | Sample 975 |
976 | ); 977 | }, 978 | }, 979 | { 980 | name: "fadeInTopRight", 981 | category: "fade", 982 | css: ` 983 | .fadeintopright { 984 | animation: fade-in-top-right 1s ease-out; 985 | -webkit-animation: fade-in-top-right 1s ease-out; 986 | } 987 | @keyframes fade-in-top-right { 988 | from { 989 | opacity: 0; 990 | transform: translate3d(100%, -100%, 0); 991 | } 992 | to { 993 | opacity: 1; 994 | transform: translate3d(0, 0, 0); 995 | } 996 | } 997 | `, 998 | tooltipContainer: () => { 999 | return ( 1000 |
1001 | 1002 |
1003 | ); 1004 | }, 1005 | tooltipSample: () => { 1006 | return ( 1007 |
1008 | Sample 1009 |
1010 | ); 1011 | }, 1012 | }, 1013 | { 1014 | name: "fadeInBottomLeft", 1015 | category: "fade", 1016 | css: ` 1017 | .fadeinbottomleft { 1018 | animation: fade-in-bottom-left 1s ease-out; 1019 | -webkit-animation: fade-in-bottom-left 1s ease-out; 1020 | } 1021 | @keyframes fade-in-bottom-left { 1022 | from { 1023 | opacity: 0; 1024 | transform: translate3d(-100%, 100%, 0); 1025 | } 1026 | to { 1027 | opacity: 1; 1028 | transform: translate3d(0, 0, 0); 1029 | } 1030 | } 1031 | `, 1032 | tooltipContainer: () => { 1033 | return ( 1034 |
1035 | 1036 |
1037 | ); 1038 | }, 1039 | tooltipSample: () => { 1040 | return ( 1041 |
1042 | Sample 1043 |
1044 | ); 1045 | }, 1046 | }, 1047 | { 1048 | name: "fadeInBottomRight", 1049 | category: "fade", 1050 | css: ` 1051 | .fadeinbottomright { 1052 | animation: fade-in-bottom-right 1s ease-out; 1053 | -webkit-animation: fade-in-bottom-right 1s ease-out; 1054 | } 1055 | @keyframes fade-in-bottom-right { 1056 | from { 1057 | opacity: 0; 1058 | transform: translate3d(100%, 100%, 0); 1059 | } 1060 | to { 1061 | opacity: 1; 1062 | transform: translate3d(0, 0, 0); 1063 | } 1064 | } 1065 | `, 1066 | tooltipContainer: () => { 1067 | return ( 1068 |
1069 | 1070 |
1071 | ); 1072 | }, 1073 | tooltipSample: () => { 1074 | return ( 1075 |
1076 | Sample 1077 |
1078 | ); 1079 | }, 1080 | }, 1081 | { 1082 | name: "fadeInBounceDown", 1083 | category: "fade", 1084 | css: ` 1085 | .fadeinbouncedown { 1086 | animation: fade-in-bounce-down 1s ease-out; 1087 | -webkit-animation: fade-in-bounce-down 1s ease-out; 1088 | } 1089 | @keyframes fade-in-bounce-down { 1090 | from { 1091 | opacity: 0; 1092 | transform: translate3d(0, -100%, 0); 1093 | } 1094 | to { 1095 | opacity: 1; 1096 | transform: translate3d(0, 0, 0); 1097 | } 1098 | } 1099 | `, 1100 | tooltipContainer: () => { 1101 | return ( 1102 |
1103 | 1104 |
1105 | ); 1106 | }, 1107 | tooltipSample: () => { 1108 | return ( 1109 |
1110 | Sample 1111 |
1112 | ); 1113 | }, 1114 | }, 1115 | { 1116 | name: "fadeInBounceUp", 1117 | category: "fade", 1118 | css: ` 1119 | .fadeinbounceup { 1120 | animation: fade-in-bounce-up 1s ease-out; 1121 | -webkit-animation: fade-in-bounce-up 1s ease-out; 1122 | } 1123 | @keyframes fade-in-bounce-up { 1124 | from { 1125 | opacity: 0; 1126 | transform: translate3d(0, 100%, 0); 1127 | } 1128 | to { 1129 | opacity: 1; 1130 | transform: translate3d(0, 0, 0); 1131 | } 1132 | } 1133 | `, 1134 | tooltipContainer: () => { 1135 | return ( 1136 |
1137 | 1138 |
1139 | ); 1140 | }, 1141 | tooltipSample: () => { 1142 | return ( 1143 |
1144 | Sample 1145 |
1146 | ); 1147 | }, 1148 | }, 1149 | { 1150 | name: "fadeInBounceRight", 1151 | category: "fade", 1152 | css: ` 1153 | .fadeinbounceright { 1154 | animation: fade-in-bounce-right 1s ease-out; 1155 | -webkit-animation: fade-in-bounce-right 1s ease-out; 1156 | } 1157 | @keyframes fade-in-bounce-right { 1158 | from { 1159 | opacity: 0; 1160 | transform: translate3d(-100%, 0, 0); 1161 | } 1162 | to { 1163 | opacity: 1; 1164 | transform: translate3d(0, 0, 0); 1165 | } 1166 | } 1167 | `, 1168 | description: "Fade in bounce right effect", 1169 | tooltipContainer: () => { 1170 | return ( 1171 |
1172 | 1173 |
1174 | ); 1175 | }, 1176 | tooltipSample: () => { 1177 | return ( 1178 |
1179 | Sample 1180 |
1181 | ); 1182 | }, 1183 | }, 1184 | { 1185 | name: "fadeInBounceLeft", 1186 | category: "fade", 1187 | css: ` 1188 | .fadeinbounceleft { 1189 | animation: fade-in-bounce-left 1s ease-out; 1190 | -webkit-animation: fade-in-bounce-left 1s ease-out; 1191 | } 1192 | @keyframes fade-in-bounce-left { 1193 | from { 1194 | opacity: 0; 1195 | transform: translate3d(100%, 0, 0); 1196 | } 1197 | to { 1198 | opacity: 1; 1199 | transform: translate3d(0, 0, 0); 1200 | } 1201 | } 1202 | `, 1203 | tooltipContainer: () => { 1204 | return ( 1205 |
1206 | 1207 |
1208 | ); 1209 | }, 1210 | tooltipSample: () => { 1211 | return ( 1212 |
1213 | Sample 1214 |
1215 | ); 1216 | }, 1217 | }, 1218 | { 1219 | name: "fadeOutLeft", 1220 | category: "fade", 1221 | css: ` 1222 | .fadeoutleft { 1223 | animation: fade-out-left 1s ease-out; 1224 | -webkit-animation: fade-out-left 1s ease-out; 1225 | } 1226 | @keyframes fade-out-left { 1227 | from { 1228 | opacity: 1; 1229 | transform: translate3d(0, 0, 0); 1230 | } 1231 | to { 1232 | opacity: 0; 1233 | transform: translate3d(-100%, 0, 0); 1234 | } 1235 | } 1236 | `, 1237 | tooltipContainer: () => { 1238 | return ( 1239 |
1240 | 1241 |
1242 | ); 1243 | }, 1244 | tooltipSample: () => { 1245 | return ( 1246 |
1247 | Sample 1248 |
1249 | ); 1250 | }, 1251 | }, 1252 | { 1253 | name: "fadeOutTopLeft", 1254 | category: "fade", 1255 | css: ` 1256 | .fadeouttopleft { 1257 | animation: fade-out-top-left 1s ease-out; 1258 | -webkit-animation: fade-out-top-left 1s ease-out; 1259 | } 1260 | @keyframes fade-out-top-left { 1261 | from { 1262 | opacity: 1; 1263 | transform: translate3d(0, 0, 0); 1264 | } 1265 | to { 1266 | opacity: 0; 1267 | transform: translate3d(-100%, -100%, 0); 1268 | } 1269 | } 1270 | `, 1271 | tooltipContainer: () => { 1272 | return ( 1273 |
1274 | 1275 |
1276 | ); 1277 | }, 1278 | tooltipSample: () => { 1279 | return ( 1280 |
1281 | Sample 1282 |
1283 | ); 1284 | }, 1285 | }, 1286 | { 1287 | name: "fadeOutTopRight", 1288 | category: "fade", 1289 | css: ` 1290 | .fadeouttopright { 1291 | animation: fade-out-top-right 1s ease-out; 1292 | -webkit-animation: fade-out-top-right 1s ease-out; 1293 | } 1294 | @keyframes fade-out-top-right { 1295 | from { 1296 | opacity: 1; 1297 | transform: translate3d(0, 0, 0); 1298 | } 1299 | to { 1300 | opacity: 0; 1301 | transform: translate3d(100%, -100%, 0); 1302 | } 1303 | } 1304 | `, 1305 | tooltipContainer: () => { 1306 | return ( 1307 |
1308 | 1309 |
1310 | ); 1311 | }, 1312 | tooltipSample: () => { 1313 | return ( 1314 |
1315 | Sample 1316 |
1317 | ); 1318 | }, 1319 | }, 1320 | { 1321 | name: "dropIn", 1322 | category: "drop", 1323 | css: ` 1324 | .dropin { 1325 | animation: drop-in 1s ease-out; 1326 | -webkit-animation: drop-in 1s ease-out; 1327 | } 1328 | @keyframes drop-in { 1329 | from { 1330 | opacity: 0; 1331 | transform: translate3d(0, 100%, 0); 1332 | } 1333 | to { 1334 | opacity: 1; 1335 | transform: translate3d(0, 0, 0); 1336 | } 1337 | } 1338 | `, 1339 | tooltipContainer: () => { 1340 | return ( 1341 |
1342 | 1343 |
1344 | ); 1345 | }, 1346 | tooltipSample: () => { 1347 | return ( 1348 |
1349 | Sample 1350 |
1351 | ); 1352 | }, 1353 | }, 1354 | { 1355 | name: "dropOut", 1356 | category: "drop", 1357 | css: ` 1358 | .dropout { 1359 | animation: drop-out 1s ease-out; 1360 | -webkit-animation: drop-out 1s ease-out; 1361 | } 1362 | @keyframes drop-out { 1363 | from { 1364 | opacity: 1; 1365 | transform: translate3d(0, 0, 0); 1366 | } 1367 | to { 1368 | opacity: 0; 1369 | transform: translate3d(0, 100%, 0); 1370 | } 1371 | } 1372 | `, 1373 | tooltipContainer: () => { 1374 | return ( 1375 |
1376 | 1377 |
1378 | ); 1379 | }, 1380 | tooltipSample: () => { 1381 | return ( 1382 |
1383 | Sample 1384 |
1385 | ); 1386 | }, 1387 | }, 1388 | { 1389 | name: "flyIn", 1390 | category: "fly", 1391 | css: ` 1392 | .flyin { 1393 | animation: fly-in 1s ease-out; 1394 | -webkit-animation: fly-in 1s ease-out; 1395 | } 1396 | @keyframes fly-in { 1397 | from { 1398 | opacity: 0; 1399 | transform: translate3d(-100%, 0, 0); 1400 | } 1401 | to { 1402 | opacity: 1; 1403 | transform: translate3d(0, 0, 0); 1404 | } 1405 | } 1406 | `, 1407 | tooltipContainer: () => { 1408 | return ( 1409 |
1410 | 1411 |
1412 | ); 1413 | }, 1414 | tooltipSample: () => { 1415 | return ( 1416 |
1417 | Sample 1418 |
1419 | ); 1420 | }, 1421 | }, 1422 | { 1423 | name: "flyInUp", 1424 | category: "fly", 1425 | css: ` 1426 | .flyinup { 1427 | animation: fly-in-up 1s ease-out; 1428 | -webkit-animation: fly-in-up 1s ease-out; 1429 | } 1430 | @keyframes fly-in-up { 1431 | from { 1432 | opacity: 0; 1433 | transform: translate3d(0, -100%, 0); 1434 | } 1435 | to { 1436 | opacity: 1; 1437 | transform: translate3d(0, 0, 0); 1438 | } 1439 | } 1440 | `, 1441 | tooltipContainer: () => { 1442 | return ( 1443 |
1444 | 1445 |
1446 | ); 1447 | }, 1448 | tooltipSample: () => { 1449 | return ( 1450 |
1451 | Sample 1452 |
1453 | ); 1454 | }, 1455 | }, 1456 | { 1457 | name: "flyInDown", 1458 | category: "fly", 1459 | css: ` 1460 | .flyindown { 1461 | animation: fly-in-down 1s ease-out; 1462 | -webkit-animation: fly-in-down 1s ease-out; 1463 | } 1464 | @keyframes fly-in-down { 1465 | from { 1466 | opacity: 0; 1467 | transform: translate3d(0, 100%, 0); 1468 | } 1469 | to { 1470 | opacity: 1; 1471 | transform: translate3d(0, 0, 0); 1472 | } 1473 | } 1474 | `, 1475 | tooltipContainer: () => { 1476 | return ( 1477 |
1478 | 1479 |
1480 | ); 1481 | }, 1482 | tooltipSample: () => { 1483 | return ( 1484 |
1485 | Sample 1486 |
1487 | ); 1488 | }, 1489 | }, 1490 | { 1491 | name: "flyInLeft", 1492 | category: "fly", 1493 | css: ` 1494 | .flyinleft { 1495 | animation: fly-in-left 1s ease-out; 1496 | -webkit-animation: fly-in-left 1s ease-out; 1497 | } 1498 | @keyframes fly-in-left { 1499 | from { 1500 | opacity: 0; 1501 | transform: translate3d(100%, 0, 0); 1502 | } 1503 | to { 1504 | opacity: 1; 1505 | transform: translate3d(0, 0, 0); 1506 | } 1507 | } 1508 | `, 1509 | description: "Fly in left effect", 1510 | tooltipContainer: () => { 1511 | return ( 1512 |
1513 | 1514 |
1515 | ); 1516 | }, 1517 | tooltipSample: () => { 1518 | return ( 1519 |
1520 | Sample 1521 |
1522 | ); 1523 | }, 1524 | }, 1525 | { 1526 | name: "flyInRight", 1527 | category: "fly", 1528 | css: ` 1529 | .flyinright { 1530 | animation: fly-in-right 1s ease-out; 1531 | -webkit-animation: fly-in-right 1s ease-out; 1532 | } 1533 | @keyframes fly-in-right { 1534 | from { 1535 | opacity: 0; 1536 | transform: translate3d(-100%, 0, 0); 1537 | } 1538 | to { 1539 | opacity: 1; 1540 | transform: translate3d(0, 0, 0); 1541 | } 1542 | } 1543 | `, 1544 | tooltipContainer: () => { 1545 | return ( 1546 |
1547 | 1548 |
1549 | ); 1550 | }, 1551 | tooltipSample: () => { 1552 | return ( 1553 |
1554 | Sample 1555 |
1556 | ); 1557 | }, 1558 | }, 1559 | { 1560 | name: "flyOut", 1561 | category: "fly", 1562 | css: ` 1563 | .flyout { 1564 | animation: fly-out 1s ease-out; 1565 | -webkit-animation: fly-out 1s ease-out; 1566 | } 1567 | @keyframes fly-out { 1568 | from { 1569 | opacity: 1; 1570 | transform: translate3d(0, 0, 0); 1571 | } 1572 | to { 1573 | opacity: 0; 1574 | transform: translate3d(0, 100%, 0); 1575 | } 1576 | } 1577 | `, 1578 | tooltipContainer: () => { 1579 | return ( 1580 |
1581 | 1582 |
1583 | ); 1584 | }, 1585 | tooltipSample: () => { 1586 | return ( 1587 |
1588 | Sample 1589 |
1590 | ); 1591 | }, 1592 | }, 1593 | { 1594 | name: "flyOutUp", 1595 | category: "fly", 1596 | css: ` 1597 | .flyoutup { 1598 | animation: fly-out-up 1s ease-out; 1599 | -webkit-animation: fly-out-up 1s ease-out; 1600 | } 1601 | @keyframes fly-out-up { 1602 | from { 1603 | opacity: 1; 1604 | transform: translate3d(0, 0, 0); 1605 | } 1606 | to { 1607 | opacity: 0; 1608 | transform: translate3d(0, -100%, 0); 1609 | } 1610 | } 1611 | `, 1612 | tooltipContainer: () => { 1613 | return ( 1614 |
1615 | 1616 |
1617 | ); 1618 | }, 1619 | tooltipSample: () => { 1620 | return ( 1621 |
1622 | Sample 1623 |
1624 | ); 1625 | }, 1626 | }, 1627 | { 1628 | name: "flyOutDown", 1629 | category: "fly", 1630 | css: ` 1631 | .flyoutdown { 1632 | animation: fly-out-down 1s ease-out; 1633 | -webkit-animation: fly-out-down 1s ease-out; 1634 | } 1635 | @keyframes fly-out-down { 1636 | from { 1637 | opacity: 1; 1638 | transform: translate3d(0, 0, 0); 1639 | } 1640 | to { 1641 | opacity: 0; 1642 | transform: translate3d(0, 100%, 0); 1643 | } 1644 | } 1645 | `, 1646 | tooltipContainer: () => { 1647 | return ( 1648 |
1649 | 1650 |
1651 | ); 1652 | }, 1653 | tooltipSample: () => { 1654 | return ( 1655 |
1656 | Sample 1657 |
1658 | ); 1659 | }, 1660 | }, 1661 | { 1662 | name: "flyOutLeft", 1663 | category: "fly", 1664 | css: ` 1665 | .flyoutleft { 1666 | animation: fly-out-left 1s ease-out; 1667 | -webkit-animation: fly-out-left 1s ease-out; 1668 | } 1669 | @keyframes fly-out-left { 1670 | from { 1671 | opacity: 1; 1672 | transform: translate3d(0, 0, 0); 1673 | } 1674 | to { 1675 | opacity: 0; 1676 | transform: translate3d(-100%, 0, 0); 1677 | } 1678 | } 1679 | `, 1680 | tooltipContainer: () => { 1681 | return ( 1682 |
1683 | 1684 |
1685 | ); 1686 | }, 1687 | tooltipSample: () => { 1688 | return ( 1689 |
1690 | Sample 1691 |
1692 | ); 1693 | }, 1694 | }, 1695 | { 1696 | name: "flyOutRight", 1697 | category: "fly", 1698 | css: ` 1699 | .flyoutright { 1700 | animation: fly-out-right 1s ease-out; 1701 | -webkit-animation: fly-out-right 1s ease-out; 1702 | } 1703 | @keyframes fly-out-right { 1704 | from { 1705 | opacity: 1; 1706 | transform: translate3d(0, 0, 0); 1707 | } 1708 | to { 1709 | opacity: 0; 1710 | transform: translate3d(100%, 0, 0); 1711 | } 1712 | } 1713 | `, 1714 | tooltipContainer: () => { 1715 | return ( 1716 |
1717 | 1718 |
1719 | ); 1720 | }, 1721 | tooltipSample: () => { 1722 | return ( 1723 |
1724 | Sample 1725 |
1726 | ); 1727 | }, 1728 | }, 1729 | { 1730 | name: "browseIn", 1731 | category: "browse", 1732 | css: ` 1733 | .browsein { 1734 | animation: browse-in 1s ease-out; 1735 | -webkit-animation: browse-in 1s ease-out; 1736 | } 1737 | @keyframes browse-in { 1738 | from { 1739 | opacity: 0; 1740 | } 1741 | to { 1742 | opacity: 1; 1743 | } 1744 | } 1745 | `, 1746 | tooltipContainer: () => { 1747 | return ( 1748 |
1749 | 1750 |
1751 | ); 1752 | }, 1753 | tooltipSample: () => { 1754 | return ( 1755 |
1756 | Sample 1757 |
1758 | ); 1759 | }, 1760 | }, 1761 | { 1762 | name: "browseOut", 1763 | category: "browse", 1764 | css: ` 1765 | .browseout { 1766 | animation: browse-out 1s ease-out; 1767 | -webkit-animation: browse-out 1s ease-out; 1768 | } 1769 | @keyframes browse-out { 1770 | from { 1771 | opacity: 1; 1772 | } 1773 | to { 1774 | opacity: 0; 1775 | } 1776 | } 1777 | `, 1778 | tooltipContainer: () => { 1779 | return ( 1780 |
1781 | 1782 |
1783 | ); 1784 | }, 1785 | tooltipSample: () => { 1786 | return ( 1787 |
1788 | Sample 1789 |
1790 | ); 1791 | }, 1792 | }, 1793 | { 1794 | name: "browseOutLeft", 1795 | category: "browse", 1796 | css: ` 1797 | .browseoutleft { 1798 | animation: browse-out-left 1s ease-out; 1799 | -webkit-animation: browse-out-left 1s ease-out; 1800 | } 1801 | @keyframes browse-out-left { 1802 | from { 1803 | opacity: 1; 1804 | } 1805 | to { 1806 | opacity: 0; 1807 | } 1808 | } 1809 | `, 1810 | tooltipContainer: () => { 1811 | return ( 1812 |
1813 | 1814 |
1815 | ); 1816 | }, 1817 | tooltipSample: () => { 1818 | return ( 1819 |
1820 | Sample 1821 |
1822 | ); 1823 | }, 1824 | }, 1825 | { 1826 | name: "browseOutRight", 1827 | category: "browse", 1828 | css: ` 1829 | .browseoutright { 1830 | animation: browse-out-right 1s ease-out; 1831 | -webkit-animation: browse-out-right 1s ease-out; 1832 | } 1833 | @keyframes browse-out-right { 1834 | from { 1835 | opacity: 1; 1836 | } 1837 | to { 1838 | opacity: 0; 1839 | } 1840 | } 1841 | `, 1842 | tooltipContainer: () => { 1843 | return ( 1844 |
1845 | 1846 |
1847 | ); 1848 | }, 1849 | tooltipSample: () => { 1850 | return ( 1851 |
1852 | Sample 1853 |
1854 | ); 1855 | }, 1856 | }, 1857 | { 1858 | name: "jiggle", 1859 | category: "special", 1860 | css: ` 1861 | .jiggle { 1862 | animation: jiggle 1s ease-out; 1863 | -webkit-animation: jiggle 1s ease-out; 1864 | } 1865 | @keyframes jiggle { 1866 | 0% { 1867 | transform: scale3d(1, 1, 1); 1868 | } 1869 | 30% { 1870 | transform: scale3d(1.25, 0.75, 1); 1871 | } 1872 | 40% { 1873 | transform: scale3d(0.75, 1.25, 1); 1874 | } 1875 | 50% { 1876 | transform: scale3d(1.15, 0.85, 1); 1877 | } 1878 | 65% { 1879 | transform: scale3d(0.95, 1.05, 1); 1880 | } 1881 | 75% { 1882 | transform: scale3d(1.05, 0.95, 1); 1883 | } 1884 | 100% { 1885 | transform: scale3d(1, 1, 1); 1886 | } 1887 | } 1888 | `, 1889 | tooltipContainer: () => { 1890 | return ( 1891 |
1892 | 1893 |
1894 | ); 1895 | }, 1896 | tooltipSample: () => { 1897 | return ( 1898 |
1899 | Sample 1900 |
1901 | ); 1902 | }, 1903 | }, 1904 | { 1905 | name: "flash", 1906 | category: "special", 1907 | css: ` 1908 | .flash { 1909 | animation: flash 1s ease-out; 1910 | -webkit-animation: flash 1s ease-out; 1911 | } 1912 | @keyframes flash { 1913 | 0%, 1914 | 50%, 1915 | 100% { 1916 | opacity: 1; 1917 | } 1918 | 25%, 1919 | 75% { 1920 | opacity: 0; 1921 | } 1922 | } 1923 | `, 1924 | tooltipContainer: () => { 1925 | return ( 1926 |
1927 | 1928 |
1929 | ); 1930 | }, 1931 | tooltipSample: () => { 1932 | return ( 1933 |
1934 | Sample 1935 |
1936 | ); 1937 | }, 1938 | }, 1939 | { 1940 | name: "shake", 1941 | category: "special", 1942 | css: ` 1943 | .shake { 1944 | animation: shake 1s ease-out; 1945 | -webkit-animation: shake 1s ease-out; 1946 | } 1947 | @keyframes shake { 1948 | 0%, 1949 | 100% { 1950 | transform: translateX(0); 1951 | } 1952 | 10%, 1953 | 30%, 1954 | 50%, 1955 | 70%, 1956 | 90% { 1957 | transform: translateX(-10px); 1958 | } 1959 | 20%, 1960 | 40%, 1961 | 60%, 1962 | 80% { 1963 | transform: translateX(10px); 1964 | } 1965 | } 1966 | `, 1967 | tooltipContainer: () => { 1968 | return ( 1969 |
1970 | 1971 |
1972 | ); 1973 | }, 1974 | tooltipSample: () => { 1975 | return ( 1976 |
1977 | Sample 1978 |
1979 | ); 1980 | }, 1981 | }, 1982 | { 1983 | name: "glow", 1984 | category: "special", 1985 | css: ` 1986 | .glow { 1987 | animation: glow 1s ease-out; 1988 | -webkit-animation: glow 1s ease-out; 1989 | } 1990 | @keyframes glow { 1991 | 0%, 1992 | 100% { 1993 | opacity: 1; 1994 | } 1995 | 50% { 1996 | opacity: 0.5; 1997 | } 1998 | } 1999 | `, 2000 | tooltipContainer: () => { 2001 | return ( 2002 |
2003 | 2004 |
2005 | ); 2006 | }, 2007 | tooltipSample: () => { 2008 | return ( 2009 |
2010 | Sample 2011 |
2012 | ); 2013 | }, 2014 | }, 2015 | { 2016 | name: "wiggle", 2017 | category: "special", 2018 | css: ` 2019 | .wiggle { 2020 | animation: wiggle 1s ease-out; 2021 | -webkit-animation: wiggle 1s ease-out; 2022 | } 2023 | @keyframes wiggle { 2024 | 0%, 2025 | 100% { 2026 | transform: translateX(0); 2027 | } 2028 | 10%, 2029 | 30%, 2030 | 50%, 2031 | 70%, 2032 | 90% { 2033 | transform: translateX(-10px); 2034 | } 2035 | 20%, 2036 | 40%, 2037 | 60%, 2038 | 80% { 2039 | transform: translateX(10px); 2040 | } 2041 | } 2042 | `, 2043 | tooltipContainer: () => { 2044 | return ( 2045 |
2046 | 2047 |
2048 | ); 2049 | }, 2050 | tooltipSample: () => { 2051 | return ( 2052 |
2053 | Sample 2054 |
2055 | ); 2056 | }, 2057 | }, 2058 | { 2059 | name: "bounceBlurIn", 2060 | badge: "New", 2061 | category: "special", 2062 | css: ` 2063 | .bounceblurin { 2064 | animation: bounce-blur-in 0.5s cubic-bezier(0.4, 0, 0.2, 1) both; 2065 | } 2066 | 2067 | @keyframes bounce-blur-in { 2068 | 0% { 2069 | transform: scale(0.8); 2070 | opacity: 0; 2071 | filter: blur(4px); 2072 | } 2073 | 60% { 2074 | transform: scale(1.05); 2075 | opacity: 1; 2076 | filter: blur(0); 2077 | } 2078 | 100% { 2079 | transform: scale(1); 2080 | } 2081 | } 2082 | `, 2083 | tooltipContainer: () => { 2084 | return ( 2085 |
2086 | 2087 |
2088 | ); 2089 | }, 2090 | tooltipSample: () => { 2091 | return ( 2092 |
2093 | Sample 2094 |
2095 | ); 2096 | }, 2097 | }, 2098 | { 2099 | name: "floatFadeIn", 2100 | badge: "New", 2101 | category: "special", 2102 | css: ` 2103 | .floatfadein { 2104 | animation: float-fade-in 0.5s ease-out both; 2105 | } 2106 | @keyframes float-fade-in { 2107 | 0% { 2108 | opacity: 0; 2109 | transform: translateY(10px); 2110 | } 2111 | 100% { 2112 | opacity: 1; 2113 | transform: translateY(0); 2114 | } 2115 | } 2116 | `, 2117 | tooltipContainer: () => { 2118 | return ( 2119 |
2120 | 2121 |
2122 | ); 2123 | }, 2124 | tooltipSample: () => { 2125 | return ( 2126 |
2127 | Sample 2128 |
2129 | ); 2130 | }, 2131 | }, 2132 | { 2133 | name: "scalePunchIn", 2134 | badge: "New", 2135 | category: "special", 2136 | css: ` 2137 | .scalepunchin { 2138 | animation: scale-punch-in 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) both; 2139 | } 2140 | @keyframes scale-punch-in { 2141 | 0% { 2142 | opacity: 0; 2143 | transform: scale(0.5); 2144 | } 2145 | 60% { 2146 | opacity: 1; 2147 | transform: scale(1.2); 2148 | } 2149 | 100% { 2150 | transform: scale(1); 2151 | } 2152 | } 2153 | `, 2154 | tooltipContainer: () => { 2155 | return ( 2156 |
2157 | 2158 |
2159 | ); 2160 | }, 2161 | tooltipSample: () => { 2162 | return ( 2163 |
2164 | Sample 2165 |
2166 | ); 2167 | }, 2168 | }, 2169 | { 2170 | name: "flipPopIn", 2171 | badge: "New", 2172 | category: "special", 2173 | css: ` 2174 | .flippopin { 2175 | animation: flip-pop-in 0.6s ease-out both; 2176 | transform-style: preserve-3d; 2177 | } 2178 | @keyframes flip-pop-in { 2179 | 0% { 2180 | opacity: 0; 2181 | transform: rotateX(90deg) scale(0.8); 2182 | transform-origin: top; 2183 | } 2184 | 100% { 2185 | opacity: 1; 2186 | transform: rotateX(0deg) scale(1); 2187 | } 2188 | } 2189 | `, 2190 | tooltipContainer: () => { 2191 | return ( 2192 |
2193 | 2194 |
2195 | ); 2196 | }, 2197 | tooltipSample: () => { 2198 | return ( 2199 |
2200 | Sample 2201 |
2202 | ); 2203 | }, 2204 | }, 2205 | ]; 2206 | export default TooltipContent; 2207 | -------------------------------------------------------------------------------- /src/components/effects/BottomBlur.jsx: -------------------------------------------------------------------------------- 1 | import "@/styles/gradient-blur.css"; 2 | 3 | export default function BottomBlurOut() { 4 | return ( 5 |
6 | {Array.from({ length: 5 }).map((_, index) => ( 7 |
16 | ))} 17 |
18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /src/components/effects/TextBlurIn.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { motion } from "framer-motion"; 3 | 4 | export const BlurIn = ({ text = "", className = "" }) => { 5 | const container = { 6 | hidden: {}, 7 | visible: { 8 | transition: { 9 | staggerChildren: 0.05, 10 | }, 11 | }, 12 | }; 13 | 14 | const letter = { 15 | hidden: { 16 | opacity: 0, 17 | filter: "blur(10px)", 18 | y: 20, 19 | scale: 0.95, 20 | rotate: -3, 21 | }, 22 | visible: { 23 | opacity: 1, 24 | filter: "blur(0px)", 25 | y: 0, 26 | scale: 1, 27 | rotate: 0, 28 | transition: { 29 | duration: 0.8, 30 | ease: [0.22, 1, 0.36, 1], 31 | }, 32 | }, 33 | }; 34 | 35 | return ( 36 | 42 | {text.split("").map((char, i) => ( 43 | 44 | {char === " " ? "\u00A0" : char} 45 | 46 | ))} 47 | 48 | ); 49 | }; 50 | -------------------------------------------------------------------------------- /src/components/effects/TextScroll.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React, { useRef } from "react"; 4 | import { useScroll, motion, useTransform } from "framer-motion"; 5 | 6 | export default function Character({ value }) { 7 | const element = useRef(null); 8 | const { scrollYProgress } = useScroll({ 9 | target: element, 10 | offset: ["start 0.9", "start 0.25"], 11 | }); 12 | 13 | const words = value.split(" "); 14 | 15 | return ( 16 |

20 | {words.map((word, i) => { 21 | const start = i / words.length; 22 | const end = start + 1 / words.length; 23 | return ( 24 | 25 | {word} 26 | 27 | ); 28 | })} 29 |

30 | ); 31 | } 32 | 33 | const Word = ({ children, range, progress }) => { 34 | const characters = children.split(""); 35 | const amount = range[1] - range[0]; 36 | const step = amount / characters.length; 37 | return ( 38 | 39 | {characters.map((character, i) => { 40 | const start = range[0] + step * i; 41 | const end = range[0] + step * (i + 1); 42 | return ( 43 | 44 | {character} 45 | 46 | ); 47 | })} 48 | 49 | ); 50 | }; 51 | 52 | const Characters = ({ children, range, progress }) => { 53 | const opacity = useTransform(progress, range, [0, 1]); 54 | return ( 55 | 56 | 57 | {children} 58 | 59 | {children} 60 | 61 | ); 62 | }; 63 | -------------------------------------------------------------------------------- /src/components/icons/Favicon.jsx: -------------------------------------------------------------------------------- 1 | export default function Favicon() { 2 | return ( 3 | 4 | 10 | 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /src/components/layouts/Content.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React, { useRef, useState } from "react"; 4 | import TooltipContent from "@/components/common/TooltipList"; 5 | import BottomBlurOut from "@/components/effects/BottomBlur"; 6 | import useInjectAnimations from "@/hooks/useInjectAnimations"; 7 | import Code from "@/components/snippets/CodeViewer"; 8 | import useClickOutside from "@/hooks/useClickOutside"; 9 | import ButtonCopy from "@/components/common/ButtonCopy"; 10 | 11 | import { AnimatePresence, motion } from "framer-motion"; 12 | 13 | import { Info, Frame, X, ChevronRight, Terminal } from "lucide-react"; 14 | 15 | export default function Content() { 16 | useInjectAnimations(TooltipContent); 17 | 18 | const [showCode, setShowCode] = useState( 19 | new Array(TooltipContent.length).fill(false), 20 | ); 21 | const [isOpenTooltip, setIsOpenTooltip] = useState( 22 | new Array(TooltipContent.length).fill(false), 23 | ); 24 | const [copied, setCopied] = useState( 25 | new Array(TooltipContent.length).fill(false), 26 | ); 27 | const [openModals, setOpenModals] = useState({}); 28 | const modalRef = useRef(null); 29 | 30 | const handleOpenModal = (index) => { 31 | setOpenModals((prevOpenModals) => ({ ...prevOpenModals, [index]: true })); 32 | }; 33 | 34 | const handleCloseModal = (index) => { 35 | setOpenModals((prevOpenModals) => ({ ...prevOpenModals, [index]: false })); 36 | }; 37 | 38 | const handleCopy = (index) => { 39 | navigator.clipboard.writeText(TooltipContent[index].css); 40 | setCopied((prevCopied) => { 41 | const newCopied = [...prevCopied]; 42 | newCopied[index] = true; 43 | return newCopied; 44 | }); 45 | }; 46 | 47 | const groupTooltips = TooltipContent.reduce((acc, tooltip) => { 48 | const { category } = tooltip; 49 | if (!acc[category]) acc[category] = []; 50 | acc[category].push(tooltip); 51 | return acc; 52 | }, {}); 53 | 54 | useClickOutside(modalRef, () => { 55 | setOpenModals({}); 56 | }); 57 | 58 | const modalVariants = { 59 | hidden: { 60 | opacity: 0, 61 | y: 100, 62 | rotateX: 90, 63 | transformOrigin: "bottom center", 64 | }, 65 | visible: { 66 | opacity: 1, 67 | y: 0, 68 | rotateX: 0, 69 | transition: { 70 | duration: 0.6, 71 | ease: [0.16, 1, 0.3, 1], 72 | }, 73 | }, 74 | exit: { 75 | opacity: 0, 76 | y: 100, 77 | rotateX: 90, 78 | transition: { 79 | duration: 0.4, 80 | ease: [0.4, 0, 0.2, 1], 81 | }, 82 | }, 83 | }; 84 | 85 | return ( 86 |
87 | 88 | 89 |
90 | {Object.entries(groupTooltips).map(([category, tooltips]) => ( 91 | 92 |
93 |
94 | 95 | {category} 96 | 97 | 98 | {tooltips.length} 99 | 100 |
101 |
102 | {tooltips.map((tooltip, index) => { 103 | const globalIndex = TooltipContent.findIndex( 104 | (t) => t.name === tooltip.name, 105 | ); 106 | return ( 107 |
111 |
116 |
117 |
118 | 119 | {tooltip.name} 120 |
121 | {tooltip.badge && ( 122 |
123 | {tooltip.badge} 124 |
125 | )} 126 | 136 |
{ 139 | const newIsOpenTooltip = [...isOpenTooltip]; 140 | newIsOpenTooltip[globalIndex] = true; 141 | setIsOpenTooltip(newIsOpenTooltip); 142 | }} 143 | onMouseLeave={() => { 144 | const newIsOpenTooltip = [...isOpenTooltip]; 145 | newIsOpenTooltip[globalIndex] = false; 146 | setIsOpenTooltip(newIsOpenTooltip); 147 | }} 148 | > 149 | {tooltip.tooltipContainer && tooltip.tooltipContainer()} 150 | {isOpenTooltip[globalIndex] && 151 | tooltip.tooltipSample && 152 | tooltip.tooltipSample()} 153 |
154 |
155 | 156 | {openModals[globalIndex] && ( 157 | 164 | 172 | 179 | 180 | 185 |
186 | handleCopy(globalIndex)} 188 | /> 189 |
190 |
191 | 192 |
193 | 194 | 195 | Adjust the time according to your app's 196 | requirements 197 | 198 |
199 |
200 |
201 | )} 202 |
203 |
204 | ); 205 | })} 206 |
207 | ))} 208 |
209 |
210 | ); 211 | } 212 | -------------------------------------------------------------------------------- /src/components/layouts/Footer.jsx: -------------------------------------------------------------------------------- 1 | import { Github } from "lucide-react"; 2 | 3 | import Link from "next/link"; 4 | 5 | export default function Footer() { 6 | return ( 7 |
8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 23 | 24 |

25 | © 2025{" "} 26 | 27 | Popply 28 | 29 | . All rights reserved. 30 |

31 |
32 | 36 | 37 | Stars on Github 38 | 39 |
40 |
41 |
42 | ); 43 | } 44 | -------------------------------------------------------------------------------- /src/components/layouts/Header.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import React from "react"; 3 | import Image from "next/image"; 4 | import Switch from "@/components/common/ButtonSwitch"; 5 | import { motion } from "framer-motion"; 6 | import Favicon from "../icons/Favicon"; 7 | 8 | export default function Header() { 9 | return ( 10 |
11 |
12 | 13 | 19 | 20 | Popply Library 21 | 22 | 23 |
29 | 30 |
31 |
32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /src/components/layouts/Hero.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import BottomBlurOut from "@/components/effects/BottomBlur"; 4 | import Character from "@/components/effects/TextScroll"; 5 | import { BlurIn } from "../effects/TextBlurIn"; 6 | import { motion } from "framer-motion"; 7 | 8 | export default function Hero() { 9 | return ( 10 |
11 | 17 | 23 | 29 | 30 |
31 |

32 | 33 | Eleveate Your 34 | 35 |
36 | 37 | Tooltip's   38 | 39 | 40 | 41 | 42 |

43 |
44 |
45 |
46 | 47 | 53 | 58 | 59 | 60 | 66 | 67 | 73 |
74 | ); 75 | } 76 | -------------------------------------------------------------------------------- /src/components/snippets/CodeViewer.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; 4 | import { materialDark } from "react-syntax-highlighter/dist/esm/styles/prism"; 5 | import { useEffect, useState } from "react"; 6 | 7 | export default function Code({ code, language = "css", filename, children }) { 8 | const [mounted, setMounted] = useState(false); 9 | 10 | useEffect(() => { 11 | setMounted(true); 12 | }, []); 13 | 14 | if (!mounted) return null; 15 | 16 | return ( 17 |
18 |
19 | {filename && ( 20 | 21 | {filename} 22 | 23 | )} 24 | 25 |
26 |
27 | {children} 28 | 42 | {code} 43 | 44 |
45 |
46 |
47 |
48 | ); 49 | } 50 | -------------------------------------------------------------------------------- /src/hooks/useClickOutside.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useEffect } from "react"; 4 | 5 | export default function useClickOutside(ref, handler) { 6 | useEffect(() => { 7 | const handleClickOutside = (event) => { 8 | if (!ref || !ref.current || ref.current.contains(event.target)) { 9 | return; 10 | } 11 | 12 | handler(event); 13 | }; 14 | 15 | document.addEventListener("mousedown", handleClickOutside); 16 | document.addEventListener("touchstart", handleClickOutside); 17 | 18 | return () => { 19 | document.removeEventListener("mousedown", handleClickOutside); 20 | document.removeEventListener("touchstart", handleClickOutside); 21 | }; 22 | }, [ref, handler]); 23 | } 24 | -------------------------------------------------------------------------------- /src/hooks/useInjectAnimations.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useEffect } from "react"; 4 | 5 | export default function useInjectAnimations(animations) { 6 | useEffect(() => { 7 | if (typeof window === "undefined") return; 8 | 9 | const styleId = "global-animation-styles"; 10 | 11 | if (!document.getElementById(styleId)) { 12 | const style = document.createElement("style"); 13 | style.id = styleId; 14 | style.innerHTML = animations.map((anim) => anim.css).join("\n\n"); 15 | document.head.appendChild(style); 16 | } 17 | }, [animations]); 18 | } 19 | -------------------------------------------------------------------------------- /src/hooks/useTheme.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useState, useEffect } from "react"; 4 | 5 | export default function useTheme() { 6 | const [theme, setTheme] = useState(null); 7 | 8 | useEffect(() => { 9 | const savedTheme = 10 | localStorage.getItem("theme") || 11 | (window.matchMedia("(prefers-color-scheme: dark)").matches 12 | ? "dark" 13 | : "light"); 14 | setTheme(savedTheme); 15 | }, [setTheme]); 16 | 17 | useEffect(() => { 18 | if (theme) { 19 | document.documentElement.classList.toggle("dark", theme === "dark"); 20 | localStorage.setItem("theme", theme); 21 | } 22 | }, [theme]); 23 | 24 | const toggleTheme = () => { 25 | setTheme((prev) => (prev === "dark" ? "light" : "dark")); 26 | }; 27 | 28 | return { theme, toggleTheme }; 29 | } 30 | -------------------------------------------------------------------------------- /src/styles/gradient-blur.css: -------------------------------------------------------------------------------- 1 | .gradient-blur:before { 2 | -webkit-mask: linear-gradient( 3 | 180deg, 4 | transparent 0%, 5 | #000 12.5%, 6 | #000 25%, 7 | transparent 37.5% 8 | ); 9 | mask: linear-gradient( 10 | 180deg, 11 | transparent 0%, 12 | #000 12.5%, 13 | #000 25%, 14 | transparent 37.5% 15 | ); 16 | } 17 | 18 | .gradient-blur > div:nth-of-type(1) { 19 | -webkit-mask: linear-gradient( 20 | 180deg, 21 | transparent 12.5%, 22 | #000 25%, 23 | #000 37.5%, 24 | transparent 50% 25 | ); 26 | mask: linear-gradient( 27 | 180deg, 28 | transparent 12.5%, 29 | #000 25%, 30 | #000 37.5%, 31 | transparent 50% 32 | ); 33 | } 34 | 35 | .gradient-blur > div:nth-of-type(2) { 36 | -webkit-mask: linear-gradient( 37 | 180deg, 38 | transparent 25%, 39 | #000 37.5%, 40 | #000 50%, 41 | transparent 62.5% 42 | ); 43 | mask: linear-gradient( 44 | 180deg, 45 | transparent 25%, 46 | #000 37.5%, 47 | #000 50%, 48 | transparent 62.5% 49 | ); 50 | } 51 | 52 | .gradient-blur > div:nth-of-type(3) { 53 | -webkit-mask: linear-gradient( 54 | 180deg, 55 | transparent 37.5%, 56 | #000 50%, 57 | #000 62.5%, 58 | transparent 75% 59 | ); 60 | mask: linear-gradient( 61 | 180deg, 62 | transparent 37.5%, 63 | #000 50%, 64 | #000 62.5%, 65 | transparent 75% 66 | ); 67 | } 68 | 69 | .gradient-blur > div:nth-of-type(4) { 70 | -webkit-mask: linear-gradient( 71 | 180deg, 72 | transparent 50%, 73 | #000 62.5%, 74 | #000 75%, 75 | transparent 87.5% 76 | ); 77 | mask: linear-gradient( 78 | 180deg, 79 | transparent 50%, 80 | #000 62.5%, 81 | #000 75%, 82 | transparent 87.5% 83 | ); 84 | } 85 | 86 | .gradient-blur > div:nth-of-type(5) { 87 | -webkit-mask: linear-gradient( 88 | 180deg, 89 | transparent 62.5%, 90 | #000 75%, 91 | #000 87.5%, 92 | transparent 93 | ); 94 | mask: linear-gradient( 95 | 180deg, 96 | transparent 62.5%, 97 | #000 75%, 98 | #000 87.5%, 99 | transparent 100 | ); 101 | } 102 | 103 | .gradient-blur:after { 104 | -webkit-mask: linear-gradient(180deg, transparent 75%, #000 87.5%, #000); 105 | mask: linear-gradient(180deg, transparent 75%, #000 87.5%, #000); 106 | } 107 | --------------------------------------------------------------------------------