From 96ea3b6fe1b261c8b7ae727da208e8e123ba4b6f Mon Sep 17 00:00:00 2001 From: Shubham Singh Date: Wed, 26 Feb 2025 11:53:46 +0530 Subject: [PATCH 1/2] Optimized Testimonials Done --- components.json | 21 ++++ package-lock.json | 127 +++++++++++++++++++++++- package.json | 8 +- public/assets/Stats/HeartLeft.svg | 4 + public/assets/Stats/HeartRight.svg | 4 + public/assets/Stats/quote-icon.svg | 4 + src/components/Testimonials.tsx | 117 ++++++++++++++++++++++ src/components/Try.tsx | 2 +- src/components/TryMore3D.tsx | 107 ++++++++++++++++++++ src/components/magicui/Marquee.tsx | 73 ++++++++++++++ src/constants/Stats.ts | 6 ++ src/constants/Testimonials.ts | 38 +++++++ src/constants/TryMore3D.ts | 25 +++++ src/lib/utils.ts | 6 ++ src/pages/MainPage.tsx | 4 + src/styles/globals.css | 153 ++++++++++++++++++++++++++++- tsconfig.app.json | 8 +- tsconfig.json | 16 ++- vite.config.ts | 25 ++--- 19 files changed, 725 insertions(+), 23 deletions(-) create mode 100644 components.json create mode 100644 public/assets/Stats/HeartLeft.svg create mode 100644 public/assets/Stats/HeartRight.svg create mode 100644 public/assets/Stats/quote-icon.svg create mode 100644 src/components/Testimonials.tsx create mode 100644 src/components/TryMore3D.tsx create mode 100644 src/components/magicui/Marquee.tsx create mode 100644 src/constants/Testimonials.ts create mode 100644 src/constants/TryMore3D.ts create mode 100644 src/lib/utils.ts diff --git a/components.json b/components.json new file mode 100644 index 00000000..3cc2342f --- /dev/null +++ b/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/styles/globals.css", + "baseColor": "zinc", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} diff --git a/package-lock.json b/package-lock.json index ed02ef7c..c8275084 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,15 +9,21 @@ "version": "0.0.0", "dependencies": { "@tailwindcss/vite": "^4.0.4", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "framer-motion": "^12.4.7", + "lucide-react": "^0.476.0", "react": "^19.0.0", "react-dom": "^19.0.0", "react-responsive-carousel": "^3.2.23", "react-router-dom": "^7.1.5", - "tailwindcss": "^4.0.4" + "tailwind-merge": "^3.0.2", + "tailwindcss": "^4.0.4", + "tailwindcss-animate": "^1.0.7" }, "devDependencies": { "@eslint/js": "^9.19.0", + "@types/node": "^22.13.5", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^1.3.2", @@ -405,6 +411,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -421,6 +428,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -437,6 +445,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -453,6 +462,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -469,6 +479,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -485,6 +496,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -501,6 +513,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -517,6 +530,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -533,6 +547,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -549,6 +564,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -565,6 +581,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -581,6 +598,7 @@ "cpu": [ "loong64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -597,6 +615,7 @@ "cpu": [ "mips64el" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -613,6 +632,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -629,6 +649,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -645,6 +666,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -661,6 +683,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -677,6 +700,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -693,6 +717,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -709,6 +734,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -725,6 +751,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -741,6 +768,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -757,6 +785,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -773,6 +802,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -789,6 +819,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1159,6 +1190,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1172,6 +1204,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1185,6 +1218,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1198,6 +1232,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1211,6 +1246,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1224,6 +1260,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1237,6 +1274,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1250,6 +1288,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1263,6 +1302,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1276,6 +1316,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1289,6 +1330,7 @@ "cpu": [ "loong64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1302,6 +1344,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1315,6 +1358,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1328,6 +1372,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1341,6 +1386,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1354,6 +1400,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1367,6 +1414,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1380,6 +1428,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1393,6 +1442,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1643,6 +1693,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, "license": "MIT" }, "node_modules/@types/json-schema": { @@ -1666,6 +1717,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/node": { + "version": "22.13.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.5.tgz", + "integrity": "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, "node_modules/@types/react": { "version": "19.0.10", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.10.tgz", @@ -2382,12 +2443,33 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, "node_modules/classnames": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", "license": "MIT" }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2918,6 +3000,7 @@ "version": "0.24.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "dev": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -3513,6 +3596,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -4886,6 +4970,15 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-react": { + "version": "0.476.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.476.0.tgz", + "integrity": "sha512-x6cLTk8gahdUPje0hSgLN1/MgiJH+Xl90Xoxy9bkPAsMPOUiyRSKR4JCDPGVCEpyqnZXH3exFWNItcvra9WzUQ==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -5641,6 +5734,7 @@ "version": "3.3.8", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "dev": true, "funding": [ { "type": "github", @@ -5958,6 +6052,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -6056,6 +6151,7 @@ "version": "8.5.3", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "dev": true, "funding": [ { "type": "opencollective", @@ -6361,6 +6457,7 @@ "version": "4.34.8", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz", "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==", + "dev": true, "license": "MIT", "dependencies": { "@types/estree": "1.0.6" @@ -6700,6 +6797,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -6986,12 +7084,31 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/tailwind-merge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.0.2.tgz", + "integrity": "sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.8.tgz", "integrity": "sha512-Me7N5CKR+D2A1xdWA5t5+kjjT7bwnxZOE6/yDI/ixJdJokszsn2n++mdU5yJwrsTpqFX2B9ZNMBJDwcqk9C9lw==", "license": "MIT" }, + "node_modules/tailwindcss-animate": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", + "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", + "license": "MIT", + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -7216,6 +7333,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true, + "license": "MIT" + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -7271,6 +7395,7 @@ "version": "6.1.1", "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.1.tgz", "integrity": "sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA==", + "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.24.2", diff --git a/package.json b/package.json index da64e61e..ca82db70 100644 --- a/package.json +++ b/package.json @@ -18,15 +18,21 @@ }, "dependencies": { "@tailwindcss/vite": "^4.0.4", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "framer-motion": "^12.4.7", + "lucide-react": "^0.476.0", "react": "^19.0.0", "react-dom": "^19.0.0", "react-responsive-carousel": "^3.2.23", "react-router-dom": "^7.1.5", - "tailwindcss": "^4.0.4" + "tailwind-merge": "^3.0.2", + "tailwindcss": "^4.0.4", + "tailwindcss-animate": "^1.0.7" }, "devDependencies": { "@eslint/js": "^9.19.0", + "@types/node": "^22.13.5", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^1.3.2", diff --git a/public/assets/Stats/HeartLeft.svg b/public/assets/Stats/HeartLeft.svg new file mode 100644 index 00000000..311ed8ee --- /dev/null +++ b/public/assets/Stats/HeartLeft.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/assets/Stats/HeartRight.svg b/public/assets/Stats/HeartRight.svg new file mode 100644 index 00000000..9e38e6e5 --- /dev/null +++ b/public/assets/Stats/HeartRight.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/assets/Stats/quote-icon.svg b/public/assets/Stats/quote-icon.svg new file mode 100644 index 00000000..00651800 --- /dev/null +++ b/public/assets/Stats/quote-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/Testimonials.tsx b/src/components/Testimonials.tsx new file mode 100644 index 00000000..db1ecd05 --- /dev/null +++ b/src/components/Testimonials.tsx @@ -0,0 +1,117 @@ +import { Marquee } from '@/components/magicui/Marquee'; // Marquee for scrolling effect +import { testimonials } from '@/constants/Testimonials'; +import { stats } from '@/constants/Stats'; + +const ReviewCard = ({ + img, + name, + username, + body, +}: { + img: string; + name: string; + username: string; + body: string; +}) => { + return ( +
+ {/* Quote Icon */} + double-quotes + {/* Feedback Text */} +

{body}

+ + {/* User Info */} +
+ {name} +
+

+ {name} +

+

+ @{username} +

+
+
+
+ ); +}; + +export function Testimonials() { + // Split testimonials into two rows for smooth animation effect + const firstRow = testimonials.slice(0, Math.ceil(testimonials.length / 2)); + const secondRow = testimonials.slice(Math.ceil(testimonials.length / 2)); + + return ( +
+ {/* Heading Section with Hearts */} +
+ {/* Left Heart */} + Heart Left + +
+ {/* Left Apostrophe (Hidden Below 400px) */} + Apostrophe Left + + {/* Heading */} +

+ + Words of appreciation and +
admiration from others. +
+

+ + {/* Right Apostrophe (Flipped, Hidden Below 400px) */} + Apostrophe Right +
+ + {/* Right Heart */} + Heart Right +
+ + {/* Testimonials Section */} +
+ {/* First Row (left to right) */} + + {firstRow.map((review) => ( + + ))} + + + {/* Second Row (right to left) */} + + {secondRow.map((review) => ( + + ))} + + + {/* Gradient Fading Effect for Smooth UI */} +
+
+
+
+ ); +} diff --git a/src/components/Try.tsx b/src/components/Try.tsx index 07472443..b91f7ad8 100644 --- a/src/components/Try.tsx +++ b/src/components/Try.tsx @@ -50,7 +50,7 @@ const Try: React.FC = () => { return (
-
+

diff --git a/src/components/TryMore3D.tsx b/src/components/TryMore3D.tsx new file mode 100644 index 00000000..333545ec --- /dev/null +++ b/src/components/TryMore3D.tsx @@ -0,0 +1,107 @@ +import { Marquee } from '@/components/magicui/Marquee'; +import { + firstRow, + secondRow, + thirdRow, + fourthRow, +} from '@/constants/TryMore3D'; + +const ReviewCard = ({ + img, + name, + username, + body, +}: { + img: string; + name: string; + username: string; + body: string; +}) => { + return ( +
+
+ +
+
+ {name} +
+

{username}

+
+
+
{body}
+
+ ); +}; + +export function TryMore() { + return ( +
+
+ {/* Left Side Content */} +
+

+ Check out the
remaining hundreds{' '} +
of activities! +

+

+ Important: Please know that in order to install and try them, you need + to be running the Sugar Desktop Environment. If you don’t have that + already, please reconsider your other options to explore Sugar. Try + Sugar! +

+ +
+ + {/* Marquee Section */} +
+ + {firstRow.map((review) => ( + + ))} + + + {secondRow.map((review) => ( + + ))} + + + {thirdRow.map((review) => ( + + ))} + + + {fourthRow.map((review) => ( + + ))} + +
+
+
+ ); +} diff --git a/src/components/magicui/Marquee.tsx b/src/components/magicui/Marquee.tsx new file mode 100644 index 00000000..7a959d2a --- /dev/null +++ b/src/components/magicui/Marquee.tsx @@ -0,0 +1,73 @@ +import { cn } from '@/lib/utils'; +import { ComponentPropsWithoutRef } from 'react'; + +interface MarqueeProps extends ComponentPropsWithoutRef<'div'> { + /** + * Optional CSS class name to apply custom styles + */ + className?: string; + /** + * Whether to reverse the animation direction + * @default false + */ + reverse?: boolean; + /** + * Whether to pause the animation on hover + * @default false + */ + pauseOnHover?: boolean; + /** + * Content to be displayed in the marquee + */ + children: React.ReactNode; + /** + * Whether to animate vertically instead of horizontally + * @default false + */ + vertical?: boolean; + /** + * Number of times to repeat the content + * @default 4 + */ + repeat?: number; +} + +export function Marquee({ + className, + reverse = false, + pauseOnHover = false, + children, + vertical = false, + repeat = 4, + ...props +}: MarqueeProps) { + return ( +
+ {Array(repeat) + .fill(0) + .map((_, i) => ( +
+ {children} +
+ ))} +
+ ); +} diff --git a/src/constants/Stats.ts b/src/constants/Stats.ts index fefcf829..9a8e50ef 100644 --- a/src/constants/Stats.ts +++ b/src/constants/Stats.ts @@ -4,6 +4,9 @@ import studentMobile from '/assets/Stats/ProblemSolvingTasks.svg'; import activity from '/assets/Stats/ActivitiesDownloaded.svg'; import language from '/assets/Stats/Languages.svg'; import mentorsTeaching from '/assets/Stats/MentorsHelping.svg'; +import apostrophie from '/assets/Stats/quote-icon.svg'; +import leftHeart from '/assets/Stats/HeartLeft.svg'; +import rightHeart from '/assets/Stats/HeartRight.svg'; export const stats = { kidlaptop, @@ -12,4 +15,7 @@ export const stats = { activity, language, mentorsTeaching, + apostrophie, + leftHeart, + rightHeart, }; diff --git a/src/constants/Testimonials.ts b/src/constants/Testimonials.ts new file mode 100644 index 00000000..87e4704d --- /dev/null +++ b/src/constants/Testimonials.ts @@ -0,0 +1,38 @@ +export const testimonials = [ + { + name: 'Jack', + username: '@jack', + body: "I've never seen anything like this before. It's amazing. I love it.", + img: 'https://avatar.vercel.sh/jack', + }, + { + name: 'Jill', + username: '@jill', + body: "I don't know what to say. I'm speechless. This is amazing.", + img: 'https://avatar.vercel.sh/jill', + }, + { + name: 'John', + username: '@john', + body: "I'm at a loss for words. This is amazing. I love it.", + img: 'https://avatar.vercel.sh/john', + }, + { + name: 'Jane', + username: '@jane', + body: 'This is amazing. I love it.', + img: 'https://avatar.vercel.sh/jane', + }, + { + name: 'Jenny', + username: '@jenny', + body: 'I love it.', + img: 'https://avatar.vercel.sh/jenny', + }, + { + name: 'James', + username: '@james', + body: "I'm amazed. Love it!", + img: 'https://avatar.vercel.sh/james', + }, +]; diff --git a/src/constants/TryMore3D.ts b/src/constants/TryMore3D.ts new file mode 100644 index 00000000..77217991 --- /dev/null +++ b/src/constants/TryMore3D.ts @@ -0,0 +1,25 @@ +export const tryMoreReviews = [ + { + name: 'Jack', + username: '@jack', + body: "I've never seen anything like this before. It's amazing. I love it.", + img: 'https://avatar.vercel.sh/jack', + }, + { + name: 'Jill', + username: '@jill', + body: "I don't know what to say. I'm speechless. This is amazing.", + img: 'https://avatar.vercel.sh/jill', + }, + { + name: 'John', + username: '@john', + body: "I'm at a loss for words. This is amazing. I love it.", + img: 'https://avatar.vercel.sh/john', + }, +]; + +export const firstRow = tryMoreReviews.slice(0, tryMoreReviews.length / 2); +export const secondRow = tryMoreReviews.slice(tryMoreReviews.length / 2); +export const thirdRow = tryMoreReviews.slice(0, tryMoreReviews.length / 2); +export const fourthRow = tryMoreReviews.slice(tryMoreReviews.length / 2); diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 00000000..2819a830 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/src/pages/MainPage.tsx b/src/pages/MainPage.tsx index bf4810fd..27886c9d 100644 --- a/src/pages/MainPage.tsx +++ b/src/pages/MainPage.tsx @@ -3,6 +3,8 @@ import Footer from '../sections/Footer'; import Stats from '../components/Stats.tsx'; import Try from '../components/Try.tsx'; import Info from '../components/Info.tsx'; +import { Testimonials } from '@/components/Testimonials'; +import { TryMore } from '@/components/TryMore3D'; const MainPage = () => { return ( @@ -10,7 +12,9 @@ const MainPage = () => {
+ +