Initial commit

This commit is contained in:
vitalijmulika
2026-02-10 15:54:52 +02:00
commit a0b06ff55a
591 changed files with 77267 additions and 0 deletions

2
.env Normal file
View File

@@ -0,0 +1,2 @@
NEXT_PUBLIC_API_URL=http://localhost:3001
NEXT_PUBLIC_PROJECT_ID=a8319e29-08fe-4fed-ba1c-9451564d52d6

View File

@@ -0,0 +1,57 @@
name: Code Check
on:
workflow_dispatch:
inputs:
branch:
description: 'Branch to check'
required: true
default: 'main'
permissions:
contents: read
jobs:
check:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout branch
uses: actions/checkout@v3
with:
ref: ${{ gitea.event.inputs.branch }}
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 24
- name: Install dependencies
run: |
set -euo pipefail
npm ci --prefer-offline --no-audit 2>&1 | tee install.log
env:
NODE_OPTIONS: '--max-old-space-size=4096'
- name: TypeScript check
run: |
set -euo pipefail
npm run typecheck 2>&1 | tee build.log
- name: ESLint check
run: |
set -euo pipefail
npm run lint 2>&1 | tee build.log
- name: Upload build log on failure
if: failure()
uses: actions/upload-artifact@v3
with:
name: build-log
path: build.log
if-no-files-found: ignore
- name: Check completed
if: success()
run: echo "Typecheck and lint passed successfully"

40
.gitignore vendored Normal file
View File

@@ -0,0 +1,40 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
.idea/

36
README.md Normal file
View File

@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

116
THEME_PROVIDER_OPTIONS.txt Normal file
View File

@@ -0,0 +1,116 @@
================================================================================
THEME PROVIDER OPTIONS
================================================================================
PROPS (All Required except showBlurBottom)
-------------------------------------------
1. defaultButtonVariant
• "hover-magnetic"
• "hover-bubble"
• "expand-hover"
• "elastic-effect"
• "bounce-effect"
• "icon-arrow"
• "shift-hover"
• "text-stagger"
• "text-shift"
• "directional-hover"
• "slide-background"
2. defaultTextAnimation
• "entrance-slide"
• "reveal-blur"
• "background-highlight"
3. borderRadius
• "sharp"
• "rounded"
• "soft"
• "pill"
4. contentWidth
• "small"
• "smallMedium"
• "compact"
• "mediumSmall"
• "medium"
• "mediumLarge"
5. sizing
• "medium"
• "mediumLarge"
• "largeSmall"
• "large"
• "mediumSizeLargeTitles"
• "mediumLargeSizeLargeTitles"
• "largeSmallSizeLargeTitles"
• "largeSizeMediumTitles"
• "mediumLargeSizeMediumTitles"
• "largeSmallSizeMediumTitles"
6. background
• "none"
• "circleGradient"
• "aurora"
• "floatingGradient"
7. cardStyle
• "solid"
• "outline"
• "elevated"
• "gradient-mesh"
• "gradient-radial"
• "inset"
• "glass-elevated"
• "glass-depth"
• "gradient-bordered"
• "layered-gradient"
• "soft-shadow"
• "subtle-shadow"
8. primaryButtonStyle
• "gradient"
• "shadow"
• "flat"
• "radial-glow"
• "diagonal-gradient"
• "inset-glow"
• "double-inset"
• "primary-glow"
9. secondaryButtonStyle
• "glass"
• "solid"
• "layered"
• "radial-glow"
10. headingFontWeight
• "light"
• "normal"
• "medium"
• "semibold"
• "bold"
• "extrabold"
================================================================================
EXAMPLE USAGE:
<ThemeProvider
defaultButtonVariant="text-stagger"
defaultTextAnimation="entrance-slide"
borderRadius="pill"
contentWidth="medium"
sizing="medium"
background="aurora"
cardStyle="glass-elevated"
primaryButtonStyle="gradient"
secondaryButtonStyle="glass"
headingFontWeight="medium"
showBlurBottom={false}
>
{children}
</ThemeProvider>
================================================================================

484
colorThemes.css Normal file
View File

@@ -0,0 +1,484 @@
/* ============================================ */
/* LIGHT THEME VARIANTS */
/* ============================================ */
/* Light Theme - Minimal Dark Blue */
:root[data-theme="minimal-dark-blue"] {
--background: #ffffff;
--card: #f9f9f9;
--foreground: #000612e6;
--primary-cta: #15479c;
--secondary-cta: #f9f9f9;
--accent: #e2e2e2;
--background-accent: #c4c4c4;
}
/* Light Theme - Minimal Dark Green */
:root[data-theme="minimal-dark-green"] {
--background: #ffffff;
--card: #f9f9f9;
--foreground: #000f06e6;
--primary-cta: #0a7039;
--secondary-cta: #f9f9f9;
--accent: #e2e2e2;
--background-accent: #c4c4c4;
}
/* Light Theme - Minimal Light Red */
:root[data-theme="minimal-light-red"] {
--background: #ffffff;
--card: #f9f9f9;
--foreground: #120006e6;
--primary-cta: #e63946;
--secondary-cta: #f9f9f9;
--accent: #e2e2e2;
--background-accent: #c4c4c4;
}
/* Light Theme - Minimal Light Orange */
:root[data-theme="minimal-light-orange"] {
--background: #ffffff;
--card: #f9f9f9;
--foreground: #120a00e6;
--primary-cta: #ff8c42;
--secondary-cta: #f9f9f9;
--accent: #e2e2e2;
--background-accent: #c4c4c4;
}
/* Light Theme - Dark Blue */
:root[data-theme="dark-blue"] {
--background: #f5faff;
--card: #f1f8ff;
--foreground: #001122;
--primary-cta: #15479c;
--secondary-cta: #ffffff;
--accent: #a8cce8;
--background-accent: #7ba3cf;
}
/* Light Theme - Dark Green */
:root[data-theme="dark-green"] {
--background: #fafffb;
--card: #f7fffa;
--foreground: #001a0a;
--primary-cta: #0a7039;
--secondary-cta: #ffffff;
--accent: #a8d9be;
--background-accent: #6bbf8e;
}
/* Light Theme - Light Red */
:root[data-theme="light-red"] {
--background: #fffafa;
--card: #fff7f7;
--foreground: #1a0000;
--primary-cta: #e63946;
--secondary-cta: #ffffff;
--accent: #f5c4c7;
--background-accent: #f09199;
}
/* Light Theme - Light Purple */
:root[data-theme="light-purple"] {
--background: #fbfaff;
--card: #f7f5ff;
--foreground: #0f0022;
--primary-cta: #8b5cf6;
--secondary-cta: #ffffff;
--accent: #d8cef5;
--background-accent: #c4a8f9;
}
/* Light Theme - Warm Cream */
:root[data-theme="warm-cream"] {
--background: #f6f0e9;
--card: #efe7dd;
--foreground: #2b180a;
--primary-cta: #2b180a;
--secondary-cta: #efe7dd;
--accent: #94877c;
--background-accent: #afa094;
}
/* Light Theme - Gray Blue Accent */
:root[data-theme="gray-blue-accent"] {
--background: #f5f5f5;
--card: #ffffff;
--foreground: #1c1c1c;
--primary-cta: #1c1c1c;
--secondary-cta: #ffffff;
--accent: #15479c;
--background-accent: #a8cce8;
}
/* Light Theme - Gray Green Accent */
:root[data-theme="gray-green-accent"] {
--background: #f5f5f5;
--card: #ffffff;
--foreground: #1c1c1c;
--primary-cta: #1c1c1c;
--secondary-cta: #ffffff;
--accent: #159c49;
--background-accent: #a8e8ba;
}
/* Light Theme - Gray Red Accent */
:root[data-theme="gray-red-accent"] {
--background: #f5f5f5;
--card: #ffffff;
--foreground: #1c1c1c;
--primary-cta: #1c1c1c;
--secondary-cta: #ffffff;
--accent: #e63946;
--background-accent: #e8bea8;
}
/* Light Theme - Gray Purple Accent */
:root[data-theme="gray-purple-accent"] {
--background: #f5f5f5;
--card: #ffffff;
--foreground: #1c1c1c;
--primary-cta: #1c1c1c;
--secondary-cta: #ffffff;
--accent: #6139e6;
--background-accent: #b3a8e8;
}
/* Light Theme - Warm Beige */
:root[data-theme="warm-beige"] {
--background: #efebe5;
--card: #f7f2ea;
--foreground: #000000;
--primary-cta: #000000;
--secondary-cta: #ffffff;
--accent: #ffffff;
--background-accent: #e1b875;
}
/* Light Theme - Gray Teal Green */
:root[data-theme="gray-teal-green"] {
--background: #f5f5f5;
--card: #ffffff;
--foreground: #1c1c1c;
--primary-cta: #1f514c;
--secondary-cta: #ffffff;
--accent: #159c49;
--background-accent: #a8e8ba;
}
/* Light Theme - Gray Navy Blue */
:root[data-theme="gray-navy-blue"] {
--background: #f5f5f5;
--card: #ffffff;
--foreground: #1c1c1c;
--primary-cta: #1f3251;
--secondary-cta: #ffffff;
--accent: #15479c;
--background-accent: #a8cce8;
}
/* Light Theme - Gray Burgundy Red */
:root[data-theme="gray-burgundy-red"] {
--background: #f5f5f5;
--card: #ffffff;
--foreground: #1c1c1c;
--primary-cta: #511f1f;
--secondary-cta: #ffffff;
--accent: #e63946;
--background-accent: #e8bea8;
}
/* Light Theme - Gray Indigo Purple */
:root[data-theme="gray-indigo-purple"] {
--background: #f5f5f5;
--card: #ffffff;
--foreground: #1c1c1c;
--primary-cta: #341f51;
--secondary-cta: #ffffff;
--accent: #6139e6;
--background-accent: #b3a8e8;
}
/* Light Theme - Warm Gray Pink */
:root[data-theme="warmgray-pink"] {
--background: #f7f6f7;
--card: #ffffff;
--foreground: #1b0c25;
--primary-cta: #1b0c25;
--secondary-cta: #ffffff;
--accent: #ff93e4;
--background-accent: #e8a8c3;
}
/* Light Theme - Warm Gray Orange */
:root[data-theme="warmgray-orange"] {
--background: #f7f6f7;
--card: #ffffff;
--foreground: #25190c;
--primary-cta: #ff6207;
--secondary-cta: #ffffff;
--accent: #ffce93;
--background-accent: #e8cfa8;
}
/* Light Theme - Warm Gray Blue */
:root[data-theme="warmgray-blue"] {
--background: #f7f6f7;
--card: #ffffff;
--foreground: #0c1325;
--primary-cta: #0798ff;
--secondary-cta: #ffffff;
--accent: #93c7ff;
--background-accent: #a8cde8;
}
/* Light Theme - Warm Gray Indigo */
:root[data-theme="warmgray-indigo"] {
--background: #f7f6f7;
--card: #ffffff;
--foreground: #0c1325;
--primary-cta: #0b07ff;
--secondary-cta: #ffffff;
--accent: #93b7ff;
--background-accent: #a8bae8;
}
/* Light Theme - Lavender Peach */
:root[data-theme="lavender-peach"] {
--background: #e3deea;
--card: #ffffff;
--foreground: #27231f;
--primary-cta: #27231f;
--secondary-cta: #ffffff;
--accent: #c68a62;
--background-accent: #c68a62;
}
/* Light Theme - Lavender Blue */
:root[data-theme="lavender-blue"] {
--background: #e3deea;
--card: #ffffff;
--foreground: #1f2027;
--primary-cta: #1f2027;
--secondary-cta: #ffffff;
--accent: #627dc6;
--background-accent: #627dc6;
}
/* Light Theme - Warm Stone */
:root[data-theme="warm-stone"] {
--background: #f5f4ef;
--card: #dad6cd;
--foreground: #2a2928;
--primary-cta: #2a2928;
--secondary-cta: #ecebea;
--accent: #ffffff;
--background-accent: #c6b180;
}
/* Light Theme - Warm Sand */
:root[data-theme="warm-sand"] {
--background: #fcf6ec;
--card: #f3ede2;
--foreground: #2e2521;
--primary-cta: #2e2521;
--secondary-cta: #ffffff;
--accent: #b2a28b;
--background-accent: #b2a28b;
}
/* Light Theme - Warm Gray Green */
:root[data-theme="warmgray-green"] {
--background: #f7f6f7;
--card: #ffffff;
--foreground: #032419;
--primary-cta: #2bb889;
--secondary-cta: #ffffff;
--accent: #09b97e;
--background-accent: #a8e8c3;
}
/* Light Theme - Warm Gray Red */
:root[data-theme="warmgray-red"] {
--background: #f7f6f7;
--card: #ffffff;
--foreground: #250c0d;
--primary-cta: #b82b40;
--secondary-cta: #ffffff;
--accent: #b90941;
--background-accent: #e8a8b6;
}
/* Light Theme - Warm Gray Yellow */
:root[data-theme="warmgray-yellow"] {
--background: #f7f6f7;
--card: #ffffff;
--foreground: #251a0c;
--primary-cta: #f4c408;
--secondary-cta: #ffffff;
--accent: #f4ca26;
--background-accent: #e8daa8;
}
/* ============================================ */
/* DARK THEME VARIANTS */
/* ============================================ */
/* Dark Theme - Minimal */
:root[data-theme="dark"] {
--background: #0a0a0a;
--card: #1a1a1a;
--foreground: #ffffffe6;
--primary-cta: #e6e6e6;
--secondary-cta: #1a1a1a;
--accent: #737373;
--background-accent: #737373;
}
/* Dark Theme - Minimal Light Blue */
:root[data-theme="dark-minimal-light-blue"] {
--background: #0a0a0a;
--card: #1a1a1a;
--foreground: #f0f8ffe6;
--primary-cta: #cee7ff;
--secondary-cta: #1a1a1a;
--accent: #737373;
--background-accent: #737373;
}
/* Dark Theme - Minimal Light Green */
:root[data-theme="dark-minimal-light-green"] {
--background: #0a0a0a;
--card: #1a1a1a;
--foreground: #f5fffae6;
--primary-cta: #80da9b;
--secondary-cta: #1a1a1a;
--accent: #737373;
--background-accent: #737373;
}
/* Dark Theme - Minimal Light Red */
:root[data-theme="dark-minimal-light-red"] {
--background: #0a0a0a;
--card: #1a1a1a;
--foreground: #fff5f5e6;
--primary-cta: #ff7a7a;
--secondary-cta: #1a1a1a;
--accent: #737373;
--background-accent: #737373;
}
/* Dark Theme - Minimal Light Purple */
:root[data-theme="dark-minimal-light-purple"] {
--background: #0a0a0a;
--card: #1a1a1a;
--foreground: #f8f5ffe6;
--primary-cta: #c89bff;
--secondary-cta: #1a1a1a;
--accent: #737373;
--background-accent: #737373;
}
/* Dark Theme - Minimal Light Orange */
:root[data-theme="dark-minimal-light-orange"] {
--background: #0a0a0a;
--card: #1a1a1a;
--foreground: #fffaf5e6;
--primary-cta: #ffaa70;
--secondary-cta: #1a1a1a;
--accent: #737373;
--background-accent: #737373;
}
/* Dark Theme - Minimal Light Yellow */
:root[data-theme="dark-minimal-light-yellow"] {
--background: #0a0a0a;
--card: #1a1a1a;
--foreground: #fffffae6;
--primary-cta: #fde047;
--secondary-cta: #1a1a1a;
--accent: #737373;
--background-accent: #737373;
}
/* Dark Theme - Light Blue */
:root[data-theme="dark-light-blue"] {
--background: #010912;
--card: #152840;
--foreground: #e6f0ff;
--primary-cta: #cee7ff;
--secondary-cta: #0e1a29;
--accent: #3f5c79;
--background-accent: #004a93;
}
/* Dark Theme - Light Green */
:root[data-theme="dark-light-green"] {
--background: #000802;
--card: #0b1a0b;
--foreground: #e6ffe6;
--primary-cta: #80da9b;
--secondary-cta: #07170b;
--accent: #38714a;
--background-accent: #2c6541;
}
/* Dark Theme - Light Red */
:root[data-theme="dark-light-red"] {
--background: #080000;
--card: #1e0d0d;
--foreground: #ffe6e6;
--primary-cta: #ff7a7a;
--secondary-cta: #1e0909;
--accent: #7b4242;
--background-accent: #65292c;
}
/* Dark Theme - Dark Red */
:root[data-theme="dark-dark-red"] {
--background: #060000;
--card: #1d0d0d;
--foreground: #ffe6e6;
--primary-cta: #ff3d4a;
--secondary-cta: #1f0a0a;
--accent: #7b2d2d;
--background-accent: #b8111f;
}
/* Dark Theme - Light Purple */
:root[data-theme="dark-light-purple"] {
--background: #050012;
--card: #040121;
--foreground: #f0e6ff;
--primary-cta: #c89bff;
--secondary-cta: #1d123b;
--accent: #684f7b;
--background-accent: #65417c;
}
/* Dark Theme - Light Orange */
:root[data-theme="dark-light-orange"] {
--background: #080200;
--card: #1a0d0b;
--foreground: #ffe6d5;
--primary-cta: #ffaa70;
--secondary-cta: #170b07;
--accent: #7b5e4a;
--background-accent: #b8541e;
}
/* Dark Theme - Deep Blue */
:root[data-theme="dark-deep-blue"] {
--background: #020617;
--card: #0f172a;
--foreground: #e2e8f0;
--primary-cta: #c4d8f9;
--secondary-cta: #041633;
--accent: #2d30f3;
--background-accent: #1d4ed8;
}

393
colorThemes.json Normal file
View File

@@ -0,0 +1,393 @@
{
"lightTheme": {
"minimalDarkBlue": {
"--background": "#ffffff",
"--card": "#f9f9f9",
"--foreground": "#000612e6",
"--primary-cta": "#15479c",
"--secondary-cta": "#f9f9f9",
"--accent": "#e2e2e2",
"--background-accent": "#c4c4c4"
},
"minimalDarkGreen": {
"--background": "#ffffff",
"--card": "#f9f9f9",
"--foreground": "#000f06e6",
"--primary-cta": "#0a7039",
"--secondary-cta": "#f9f9f9",
"--accent": "#e2e2e2",
"--background-accent": "#c4c4c4"
},
"minimalLightRed": {
"--background": "#ffffff",
"--card": "#f9f9f9",
"--foreground": "#120006e6",
"--primary-cta": "#e63946",
"--secondary-cta": "#f9f9f9",
"--accent": "#e2e2e2",
"--background-accent": "#c4c4c4"
},
"minimalLightOrange": {
"--background": "#ffffff",
"--card": "#f9f9f9",
"--foreground": "#120a00e6",
"--primary-cta": "#ff8c42",
"--secondary-cta": "#f9f9f9",
"--accent": "#e2e2e2",
"--background-accent": "#c4c4c4"
},
"darkBlue": {
"--background": "#f5faff",
"--card": "#f1f8ff",
"--foreground": "#001122",
"--primary-cta": "#15479c",
"--secondary-cta": "#ffffff",
"--accent": "#a8cce8",
"--background-accent": "#7ba3cf"
},
"darkGreen": {
"--background": "#fafffb",
"--card": "#f7fffa",
"--foreground": "#001a0a",
"--primary-cta": "#0a7039",
"--secondary-cta": "#ffffff",
"--accent": "#a8d9be",
"--background-accent": "#6bbf8e"
},
"lightRed": {
"--background": "#fffafa",
"--card": "#fff7f7",
"--foreground": "#1a0000",
"--primary-cta": "#e63946",
"--secondary-cta": "#ffffff",
"--accent": "#f5c4c7",
"--background-accent": "#f09199"
},
"lightPurple": {
"--background": "#fbfaff",
"--card": "#f7f5ff",
"--foreground": "#0f0022",
"--primary-cta": "#8b5cf6",
"--secondary-cta": "#ffffff",
"--accent": "#d8cef5",
"--background-accent": "#c4a8f9"
},
"warmCream": {
"--background": "#f6f0e9",
"--card": "#efe7dd",
"--foreground": "#2b180a",
"--primary-cta": "#2b180a",
"--secondary-cta": "#efe7dd",
"--accent": "#94877c",
"--background-accent": "#afa094"
},
"grayBlueAccent": {
"--background": "#f5f5f5",
"--card": "#ffffff",
"--foreground": "#1c1c1c",
"--primary-cta": "#1c1c1c",
"--secondary-cta": "#ffffff",
"--accent": "#15479c",
"--background-accent": "#a8cce8"
},
"grayGreenAccent": {
"--background": "#f5f5f5",
"--card": "#ffffff",
"--foreground": "#1c1c1c",
"--primary-cta": "#1c1c1c",
"--secondary-cta": "#ffffff",
"--accent": "#159c49",
"--background-accent": "#a8e8ba"
},
"grayRedAccent": {
"--background": "#f5f5f5",
"--card": "#ffffff",
"--foreground": "#1c1c1c",
"--primary-cta": "#1c1c1c",
"--secondary-cta": "#ffffff",
"--accent": "#e63946",
"--background-accent": "#e8bea8"
},
"grayPurpleAccent": {
"--background": "#f5f5f5",
"--card": "#ffffff",
"--foreground": "#1c1c1c",
"--primary-cta": "#1c1c1c",
"--secondary-cta": "#ffffff",
"--accent": "#6139e6",
"--background-accent": "#b3a8e8"
},
"warmBeige": {
"--background": "#efebe5",
"--card": "#f7f2ea",
"--foreground": "#000000",
"--primary-cta": "#000000",
"--secondary-cta": "#ffffff",
"--accent": "#ffffff",
"--background-accent": "#e1b875"
},
"grayTealGreen": {
"--background": "#f5f5f5",
"--card": "#ffffff",
"--foreground": "#1c1c1c",
"--primary-cta": "#1f514c",
"--secondary-cta": "#ffffff",
"--accent": "#159c49",
"--background-accent": "#a8e8ba"
},
"grayNavyBlue": {
"--background": "#f5f5f5",
"--card": "#ffffff",
"--foreground": "#1c1c1c",
"--primary-cta": "#1f3251",
"--secondary-cta": "#ffffff",
"--accent": "#15479c",
"--background-accent": "#a8cce8"
},
"grayBurgundyRed": {
"--background": "#f5f5f5",
"--card": "#ffffff",
"--foreground": "#1c1c1c",
"--primary-cta": "#511f1f",
"--secondary-cta": "#ffffff",
"--accent": "#e63946",
"--background-accent": "#e8bea8"
},
"grayIndigoPurple": {
"--background": "#f5f5f5",
"--card": "#ffffff",
"--foreground": "#1c1c1c",
"--primary-cta": "#341f51",
"--secondary-cta": "#ffffff",
"--accent": "#6139e6",
"--background-accent": "#b3a8e8"
},
"warmgrayPink": {
"--background": "#f7f6f7",
"--card": "#ffffff",
"--foreground": "#1b0c25",
"--primary-cta": "#1b0c25",
"--secondary-cta": "#ffffff",
"--accent": "#ff93e4",
"--background-accent": "#e8a8c3"
},
"warmgrayOrange": {
"--background": "#f7f6f7",
"--card": "#ffffff",
"--foreground": "#25190c",
"--primary-cta": "#ff6207",
"--secondary-cta": "#ffffff",
"--accent": "#ffce93",
"--background-accent": "#e8cfa8"
},
"warmgrayBlue": {
"--background": "#f7f6f7",
"--card": "#ffffff",
"--foreground": "#0c1325",
"--primary-cta": "#0798ff",
"--secondary-cta": "#ffffff",
"--accent": "#93c7ff",
"--background-accent": "#a8cde8"
},
"warmgrayIndigo": {
"--background": "#f7f6f7",
"--card": "#ffffff",
"--foreground": "#0c1325",
"--primary-cta": "#0b07ff",
"--secondary-cta": "#ffffff",
"--accent": "#93b7ff",
"--background-accent": "#a8bae8"
},
"lavenderPeach": {
"--background": "#e3deea",
"--card": "#ffffff",
"--foreground": "#27231f",
"--primary-cta": "#27231f",
"--secondary-cta": "#ffffff",
"--accent": "#c68a62",
"--background-accent": "#c68a62"
},
"lavenderBlue": {
"--background": "#e3deea",
"--card": "#ffffff",
"--foreground": "#1f2027",
"--primary-cta": "#1f2027",
"--secondary-cta": "#ffffff",
"--accent": "#627dc6",
"--background-accent": "#627dc6"
},
"warmStone": {
"--background": "#f5f4ef",
"--card": "#dad6cd",
"--foreground": "#2a2928",
"--primary-cta": "#2a2928",
"--secondary-cta": "#ecebea",
"--accent": "#ffffff",
"--background-accent": "#c6b180"
},
"warmSand": {
"--background": "#fcf6ec",
"--card": "#f3ede2",
"--foreground": "#2e2521",
"--primary-cta": "#2e2521",
"--secondary-cta": "#ffffff",
"--accent": "#b2a28b",
"--background-accent": "#b2a28b"
},
"warmgrayGreen": {
"--background": "#f7f6f7",
"--card": "#ffffff",
"--foreground": "#032419",
"--primary-cta": "#2bb889",
"--secondary-cta": "#ffffff",
"--accent": "#09b97e",
"--background-accent": "#a8e8c3"
},
"warmgrayRed": {
"--background": "#f7f6f7",
"--card": "#ffffff",
"--foreground": "#250c0d",
"--primary-cta": "#b82b40",
"--secondary-cta": "#ffffff",
"--accent": "#b90941",
"--background-accent": "#e8a8b6"
},
"warmgrayYellow": {
"--background": "#f7f6f7",
"--card": "#ffffff",
"--foreground": "#251a0c",
"--primary-cta": "#f4c408",
"--secondary-cta": "#ffffff",
"--accent": "#f4ca26",
"--background-accent": "#e8daa8"
}
},
"darkTheme": {
"minimal": {
"--background": "#0a0a0a",
"--card": "#1a1a1a",
"--foreground": "#ffffffe6",
"--primary-cta": "#e6e6e6",
"--secondary-cta": "#1a1a1a",
"--accent": "#737373",
"--background-accent": "#737373"
},
"minimalLightBlue": {
"--background": "#0a0a0a",
"--card": "#1a1a1a",
"--foreground": "#f0f8ffe6",
"--primary-cta": "#cee7ff",
"--secondary-cta": "#1a1a1a",
"--accent": "#737373",
"--background-accent": "#737373"
},
"minimalLightGreen": {
"--background": "#0a0a0a",
"--card": "#1a1a1a",
"--foreground": "#f5fffae6",
"--primary-cta": "#80da9b",
"--secondary-cta": "#1a1a1a",
"--accent": "#737373",
"--background-accent": "#737373"
},
"minimalLightRed": {
"--background": "#0a0a0a",
"--card": "#1a1a1a",
"--foreground": "#fff5f5e6",
"--primary-cta": "#ff7a7a",
"--secondary-cta": "#1a1a1a",
"--accent": "#737373",
"--background-accent": "#737373"
},
"minimalLightPurple": {
"--background": "#0a0a0a",
"--card": "#1a1a1a",
"--foreground": "#f8f5ffe6",
"--primary-cta": "#c89bff",
"--secondary-cta": "#1a1a1a",
"--accent": "#737373",
"--background-accent": "#737373"
},
"minimalLightOrange": {
"--background": "#0a0a0a",
"--card": "#1a1a1a",
"--foreground": "#fffaf5e6",
"--primary-cta": "#ffaa70",
"--secondary-cta": "#1a1a1a",
"--accent": "#737373",
"--background-accent": "#737373"
},
"minimalLightYellow": {
"--background": "#0a0a0a",
"--card": "#1a1a1a",
"--foreground": "#fffffae6",
"--primary-cta": "#fde047",
"--secondary-cta": "#1a1a1a",
"--accent": "#737373",
"--background-accent": "#737373"
},
"lightBlue": {
"--background": "#010912",
"--card": "#152840",
"--foreground": "#e6f0ff",
"--primary-cta": "#cee7ff",
"--secondary-cta": "#0e1a29",
"--accent": "#3f5c79",
"--background-accent": "#004a93"
},
"lightGreen": {
"--background": "#000802",
"--card": "#0b1a0b",
"--foreground": "#e6ffe6",
"--primary-cta": "#80da9b",
"--secondary-cta": "#07170b",
"--accent": "#38714a",
"--background-accent": "#2c6541"
},
"lightRed": {
"--background": "#080000",
"--card": "#1e0d0d",
"--foreground": "#ffe6e6",
"--primary-cta": "#ff7a7a",
"--secondary-cta": "#1e0909",
"--accent": "#7b4242",
"--background-accent": "#65292c"
},
"darkRed": {
"--background": "#060000",
"--card": "#1d0d0d",
"--foreground": "#ffe6e6",
"--primary-cta": "#ff3d4a",
"--secondary-cta": "#1f0a0a",
"--accent": "#7b2d2d",
"--background-accent": "#b8111f"
},
"lightPurple": {
"--background": "#050012",
"--card": "#040121",
"--foreground": "#f0e6ff",
"--primary-cta": "#c89bff",
"--secondary-cta": "#1d123b",
"--accent": "#684f7b",
"--background-accent": "#65417c"
},
"lightOrange": {
"--background": "#080200",
"--card": "#1a0d0b",
"--foreground": "#ffe6d5",
"--primary-cta": "#ffaa70",
"--secondary-cta": "#170b07",
"--accent": "#7b5e4a",
"--background-accent": "#b8541e"
},
"deepBlue": {
"--background": "#020617",
"--card": "#0f172a",
"--foreground": "#e2e8f0",
"--primary-cta": "#c4d8f9",
"--secondary-cta": "#041633",
"--accent": "#2d30f3",
"--background-accent": "#1d4ed8"
}
}
}

500
docs/ACCESSIBILITY.md Normal file
View File

@@ -0,0 +1,500 @@
# Accessibility Standards
This document outlines accessibility (a11y) requirements for all components in the library, ensuring compatibility with screen readers and assistive technologies.
## Interactive Components
For buttons, links, and other interactive elements.
### Required Props
```tsx
interface ButtonProps {
text: string;
onClick?: () => void;
className?: string;
// Accessibility props
disabled?: boolean;
ariaLabel?: string;
type?: "button" | "submit" | "reset";
}
```
### Implementation Pattern
```tsx
const Button = ({
text,
onClick,
className = "",
disabled = false,
ariaLabel,
type = "button",
}: ButtonProps) => {
return (
<button
type={type}
onClick={onClick}
disabled={disabled}
aria-label={ariaLabel || text}
className={cls(
"base-button-styles",
"disabled:cursor-not-allowed disabled:opacity-50",
className
)}
>
{text}
</button>
);
};
```
### Key Points
**ariaLabel:**
- Optional prop with sensible fallback
- Falls back to `text` content for buttons
- Provides context for screen readers
**type:**
- Default: `"button"`
- Options: `"button" | "submit" | "reset"`
- Prevents accidental form submission
**disabled:**
- Default: `false`
- Includes visual disabled states:
- `disabled:cursor-not-allowed` - Shows not-allowed cursor
- `disabled:opacity-50` - Reduces opacity for visual feedback
## Media Components
### Images
**Required Props:**
```tsx
interface ImageProps {
imageSrc: string;
imageAlt?: string; // Empty string for decorative images
className?: string;
}
```
**Implementation:**
```tsx
const ImageComponent = ({
imageSrc,
imageAlt = "",
className = "",
}: ImageProps) => {
return (
<Image
src={imageSrc}
alt={imageAlt}
aria-hidden={imageAlt === ""}
className={className}
/>
);
};
```
**Key Points:**
- `imageAlt` - Alt text for images
- Provide descriptive alt text for meaningful images
- Use empty string (`""`) for decorative images
- `aria-hidden={true}` - When alt is empty, mark as decorative
- Screen readers will skip decorative images
### Videos
**Required Props:**
```tsx
interface VideoProps {
videoSrc: string;
videoAriaLabel?: string;
className?: string;
}
```
**Implementation:**
```tsx
const VideoComponent = ({
videoSrc,
videoAriaLabel = "Video content",
className = "",
}: VideoProps) => {
return (
<video
src={videoSrc}
aria-label={videoAriaLabel}
autoPlay
loop
muted
playsInline
className={className}
/>
);
};
```
**Key Points:**
- `videoAriaLabel` - Descriptive label for video element
- Default: Sensible fallback like "Video content" or "Hero video"
- Always include for screen reader context
### Media Content Pattern
For components supporting both images and videos:
```tsx
interface HeroProps {
imageSrc?: string;
imageAlt?: string;
videoSrc?: string;
videoAriaLabel?: string;
}
const Hero = ({
imageSrc,
imageAlt = "",
videoSrc,
videoAriaLabel = "Hero video",
}: HeroProps) => {
return (
<>
{videoSrc ? (
<video
src={videoSrc}
aria-label={videoAriaLabel}
autoPlay
loop
muted
playsInline
/>
) : (
imageSrc && (
<Image
src={imageSrc}
alt={imageAlt}
aria-hidden={imageAlt === ""}
/>
)
)}
</>
);
};
```
## Section Components
### Semantic HTML
Use semantic HTML elements for proper document structure:
```tsx
<section> // For sections of content
<header> // For page/section headers
<nav> // For navigation
<footer> // For page/section footers
<article> // For self-contained content
<aside> // For tangentially related content
<main> // For main content area
```
### Section Pattern
```tsx
interface SectionProps {
title: string;
description: string;
ariaLabel?: string;
className?: string;
}
const Section = ({
title,
description,
ariaLabel = "Section name",
className = "",
}: SectionProps) => {
return (
<section
aria-label={ariaLabel}
className={cls("w-full py-20", className)}
>
<div className="w-content-width mx-auto">
<h2>{title}</h2>
<p>{description}</p>
</div>
</section>
);
};
```
### Sensible Default aria-labels
Each section type should have a descriptive default:
```tsx
// Hero section
ariaLabel = "Hero section"
// About section
ariaLabel = "About section"
// Feature section
ariaLabel = "Features section"
// Testimonial section
ariaLabel = "Testimonials section"
// Footer
ariaLabel = "Footer"
// Navigation
ariaLabel = "Navigation"
```
### Heading Hierarchy
Maintain proper heading levels:
```tsx
<h1> // Page title (once per page)
<h2> // Section titles
<h3> // Subsection titles
<h4> // Card/component titles
```
**Example:**
```tsx
<section aria-label="Features section">
<h2>Our Features</h2> {/* Section title */}
<div>
<h3>Feature One</h3> {/* Feature title */}
<p>Description...</p>
</div>
</section>
```
## Form Components
### Input Fields
```tsx
interface InputProps {
label: string;
id: string;
type?: string;
required?: boolean;
ariaLabel?: string;
ariaDescribedBy?: string;
}
const Input = ({
label,
id,
type = "text",
required = false,
ariaLabel,
ariaDescribedBy,
}: InputProps) => {
return (
<div>
<label htmlFor={id}>
{label}
{required && <span aria-label="required">*</span>}
</label>
<input
id={id}
type={type}
required={required}
aria-label={ariaLabel || label}
aria-describedby={ariaDescribedBy}
/>
</div>
);
};
```
**Key Points:**
- Always associate `<label>` with input using `htmlFor` and `id`
- Mark required fields visually and semantically
- Use `aria-describedby` for error messages or hints
### Form Validation
```tsx
const [error, setError] = useState("");
<input
aria-invalid={!!error}
aria-describedby={error ? "error-message" : undefined}
/>
{error && (
<p id="error-message" role="alert">
{error}
</p>
)}
```
## Focus Management
### Focus Indicators
Never remove focus outlines without providing alternatives:
```tsx
// ❌ WRONG
className="outline-none"
// ✅ CORRECT - Custom focus indicator
className="focus:outline-none focus:ring-2 focus:ring-foreground/50"
```
### Focus Trap (for modals/dialogs)
When implementing modals or dialogs, ensure:
- Focus moves to modal when opened
- Tab/Shift+Tab cycles through modal elements only
- Focus returns to trigger element when closed
- Escape key closes modal
## Keyboard Navigation
### Interactive Elements
All interactive elements must be keyboard accessible:
```tsx
// Buttons and links work by default
<button onClick={handleClick}>Click me</button>
<a href="/page">Link</a>
// Custom interactive elements need tabIndex and keyboard handlers
<div
role="button"
tabIndex={0}
onClick={handleClick}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handleClick();
}
}}
>
Custom button
</div>
```
### Skip Links
For navigation-heavy pages, provide skip links:
```tsx
<a href="#main-content" className="sr-only focus:not-sr-only">
Skip to main content
</a>
```
## Screen Reader Only Content
Use the `sr-only` class for content that should only be read by screen readers:
```tsx
<span className="sr-only">Additional context for screen readers</span>
```
Tailwind's `sr-only` class:
```css
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
```
## ARIA Roles
Use ARIA roles when semantic HTML isn't sufficient:
```tsx
// Navigation
<nav role="navigation" aria-label="Main navigation">
// Button (for non-button elements)
<div role="button" tabIndex={0}>
// Alert/Status messages
<div role="alert">Error message</div>
<div role="status">Loading...</div>
// Presentation (decorative)
<div role="presentation">
// Dialog/Modal
<div role="dialog" aria-modal="true" aria-labelledby="dialog-title">
```
## Loading States
Provide feedback for loading states:
```tsx
const [isLoading, setIsLoading] = useState(false);
<button disabled={isLoading} aria-busy={isLoading}>
{isLoading ? (
<>
<span className="sr-only">Loading...</span>
<Spinner aria-hidden="true" />
</>
) : (
"Submit"
)}
</button>
```
## Accessibility Checklist
### Interactive Components
- [ ] Add `ariaLabel` prop (optional with sensible fallback)
- [ ] Add `type` prop for buttons (default: `"button"`)
- [ ] Add `disabled` prop with visual states
- [ ] Include disabled state styling (`disabled:cursor-not-allowed disabled:opacity-50`)
- [ ] Ensure keyboard accessibility (Enter/Space for custom elements)
- [ ] Provide custom focus indicators if removing default outline
### Media Components
- [ ] Images: Add `imageAlt` prop
- [ ] Images: Use `aria-hidden={true}` when alt is empty (decorative)
- [ ] Videos: Add `videoAriaLabel` prop with sensible default
- [ ] Provide meaningful default labels
### Section Components
- [ ] Use semantic HTML (`<section>`, `<header>`, `<nav>`, `<footer>`)
- [ ] Add `ariaLabel` prop with sensible default
- [ ] Follow proper heading hierarchy (h1 → h2 → h3)
- [ ] Use `w-full py-20` for section spacing (except hero/footer)
- [ ] Use `w-content-width mx-auto` for content wrapper
### Form Components
- [ ] Associate labels with inputs using `htmlFor` and `id`
- [ ] Mark required fields semantically
- [ ] Use `aria-invalid` for validation errors
- [ ] Use `aria-describedby` for error messages/hints
- [ ] Provide `role="alert"` for error messages
### General
- [ ] Test with keyboard navigation (Tab, Shift+Tab, Enter, Space, Escape)
- [ ] Test with screen reader (VoiceOver, NVDA, JAWS)
- [ ] Ensure sufficient color contrast (WCAG AA minimum)
- [ ] Provide focus indicators for all interactive elements
- [ ] Use semantic HTML before ARIA roles
- [ ] Include screen reader only text when needed (`sr-only`)

491
docs/CARDSTACK_SECTIONS.md Normal file
View File

@@ -0,0 +1,491 @@
# CardStack Section Pattern
This document covers the CardStack pattern used in Feature, Product, Pricing, Testimonial, Team, Blog, and Metrics section components.
## Required Type Imports
```tsx
// Centralized type definitions
import type { TextboxLayout, InvertedBackground } from "@/providers/themeProvider/config/constants";
import type { ButtonConfig, GridVariant, CardAnimationType, TitleSegment } from "@/components/cardStack/types";
```
**Key Types:**
- `TextboxLayout` - Layout options for section headers ("default" | "split" | "split-actions" | "split-description" | "inline-image")
- `InvertedBackground` - Background inversion options ("noInvert" | "invertDefault")
- `TitleSegment` - Type for inline image segments ({ type: "text" | "image", content/src, alt? })
- `ButtonConfig` - Button configuration interface
- `GridVariant` - Grid layout variants
- `CardAnimationType` - Card animation types
## Overview
CardStack is an intelligent layout component that automatically switches between grid, carousel, and timeline layouts based on item count and configuration.
**Mode Selection (Automatic):**
- **1-4 items**: Grid mode (displays as bento grid)
- **5+ items**: Carousel mode (auto-scrolling or button-controlled)
- **3-6 items with timeline variant**: Timeline layout (or carousel if 7+)
## Grid Variants
There are 9 bento grid layouts plus uniform layouts:
### Uniform Layouts
- `uniform-all-items-equal` - All items same size (default)
- `uniform-2-items` - Two equal columns
- `uniform-3-items` - Three equal columns
- `uniform-4-items` - Four equal columns
### Bento Layouts (Asymmetric)
- `two-columns-alternating-heights` - Alternating tall/short columns
- `asymmetric-60-wide-40-narrow` - 60% wide left, 40% narrow right
- `three-columns-all-equal-width` - Three equal columns
- `four-items-2x2-equal-grid` - Perfect 2x2 grid
- `one-large-right-three-stacked-left` - Left: 3 items, Right: 1 large
- `items-top-row-full-width-bottom` - Top: full width, Bottom: items
- `full-width-top-items-bottom-row` - Full width top, items below
- `one-large-left-three-stacked-right` - Left: 1 large, Right: 3 items
- `timeline` - Zigzag timeline layout
## Height Control Pattern
### uniformGridCustomHeightClasses Prop
All CardStack-based components should accept this optional prop to control item heights in both grid and carousel modes.
```tsx
interface SectionCardProps {
items: ItemType[];
gridVariant: GridVariant;
uniformGridCustomHeightClasses?: string;
carouselMode?: "auto" | "buttons";
// ... other props
}
```
### Default Values by Component Type
**Most components (Feature, Product, Pricing, Team, Metrics, Blog):**
```tsx
uniformGridCustomHeightClasses = "min-h-80 2xl:min-h-90"
```
**Testimonial components (need flexible heights):**
```tsx
uniformGridCustomHeightClasses = "min-h-none"
```
**Hero carousel components (no minimum):**
```tsx
uniformGridCustomHeightClasses = "min-h-0"
```
**Feature components (optimized for compact layout):**
```tsx
// Hardcoded in FeatureCardFour
uniformGridCustomHeightClasses = "min-h-0"
```
### Implementation Pattern
The prop flows: Section Component → CardStack → GridLayout/Carousel
```tsx
// In section component (e.g., ProductCardOne.tsx)
const ProductCardOne = ({
products,
gridVariant,
uniformGridCustomHeightClasses = "min-h-80 2xl:min-h-90",
// ... other props
}: ProductCardOneProps) => {
return (
<CardStack
gridVariant={gridVariant}
uniformGridCustomHeightClasses={uniformGridCustomHeightClasses}
// ... other props
>
{products.map((product) => (
<div className="card">...</div>
))}
</CardStack>
);
};
```
**Individual card elements must use `min-h-0`:**
```tsx
<div className={cls("card p-6 rounded-theme-capped h-full min-h-0")}>
{/* Product content */}
</div>
```
This prevents height conflicts and ensures proper flex behavior.
## Carousel Modes
### carouselMode Prop
```tsx
carouselMode?: "auto" | "buttons"
```
- **`"auto"`** - Auto-scrolling carousel (uses AutoCarousel with embla-carousel-auto-scroll)
- **`"buttons"`** - Button-controlled carousel (uses ButtonCarousel with prev/next buttons)
**Default is typically `"buttons"`** for better accessibility and user control.
## TextBox Integration
CardStack components integrate with TextBox for section headers.
### TextBox Layout Options
```tsx
import type { TextboxLayout } from "@/providers/themeProvider/config/constants";
textboxLayout: TextboxLayout // "default" | "split" | "split-actions" | "split-description" | "inline-image"
```
**Layout Modes:**
1. **`"default"`** - Title and description stacked vertically, centered or left-aligned
```
[Tag]
Title
Description
[Buttons]
```
2. **`"split"`** - Title and description on left (60%), buttons on right (40%)
```
[Tag]
Title | Description | [Buttons]
```
3. **`"split-actions"`** - Title and description on left, buttons on right (no description on right)
```
[Tag]
Title | [Buttons]
Description |
```
4. **`"split-description"`** - Title on left, description on right, buttons below
```
[Tag]
Title | Description
[Buttons]
```
5. **`"inline-image"`** - Centered heading with inline images between text segments, buttons below
```
Text [Image] Text [Image] Text
[Buttons]
```
**Special props for inline-image layout:**
```tsx
import type { TitleSegment } from "@/components/cardStack/types";
titleSegments?: TitleSegment[] // Array of text and image segments
titleImageWrapperClassName?: string // Styling for image wrapper
titleImageClassName?: string // Styling for the image itself
```
**Example usage:**
```tsx
<FeatureCardOne
titleSegments={[
{ type: "text", content: "Discover" },
{ type: "image", src: "/icon.png", alt: "Icon" },
{ type: "text", content: "powerful features" }
]}
textboxLayout="inline-image"
// ... other props
/>
```
**Inline Image Behavior:**
- Images are styled with `primary-button` background
- Automatic rotation alternation: 1st: -rotate-12, 2nd: rotate-12, etc.
- Square aspect ratio (1.1em height)
- Proper spacing with mx-1 margins
- Supports both local paths and external URLs
### TextBox Props in CardStack
```tsx
<CardStack
title="Our Products"
titleSegments={[
{ type: "text", content: "Our" },
{ type: "image", src: "/icon.png", alt: "Product Icon" },
{ type: "text", content: "Products" }
]} // Optional: use titleSegments for inline-image layout
description="Discover our latest offerings"
tag="Products"
tagIcon={Package}
buttons={[
{ text: "View All", href: "/products" }
]}
textboxLayout="split" // or "inline-image" with titleSegments
useInvertedBackground="noInvert" // "noInvert" | "invertDefault"
// TextBox className overrides
textBoxClassName=""
titleClassName=""
titleImageWrapperClassName="" // For inline-image layout
titleImageClassName="" // For inline-image layout
descriptionClassName=""
tagClassName=""
buttonContainerClassName=""
buttonClassName=""
buttonTextClassName=""
// ... other props
>
```
## Button System
### ButtonConfig Interface
```tsx
interface ButtonConfig {
text: string;
onClick?: () => void;
href?: string;
props?: Partial<ButtonPropsForVariant<CTAButtonVariant>>;
// NO variant property - controlled by ThemeProvider
}
```
### Button Rendering Logic
Buttons are rendered with automatic primary/secondary styling:
- **Index 0**: Primary button (`primary-button` class)
- **Index 1+**: Secondary button (`secondary-button` class)
**Maximum 2 buttons** per section (enforced in TextBox component).
```tsx
const buttons: ButtonConfig[] = [
{ text: "Get Started", href: "/signup" }, // Primary
{ text: "Learn More", onClick: () => {} } // Secondary
];
```
The `variant` is determined by ThemeProvider's `defaultButtonVariant` setting.
## Complete CardStack Section Example
```tsx
"use client";
import React, { memo } from "react";
import CardStack from "@/components/cardStack/CardStack";
import { cls } from "@/lib/utils";
import type { GridVariant, ButtonConfig } from "@/components/cardStack/types";
import type { LucideIcon } from "lucide-react";
type Product = {
title: string;
description: string;
price: string;
image: string;
};
interface ProductCardOneProps {
products: Product[];
carouselMode?: "auto" | "buttons";
gridVariant: GridVariant;
uniformGridCustomHeightClasses?: string;
title: string;
description: string;
tag?: string;
tagIcon?: LucideIcon;
buttons?: ButtonConfig[];
textboxLayout: "default" | "split" | "split-actions" | "split-description";
ariaLabel?: string;
// Main wrapper
className?: string;
// CardStack customization
cardStackClassName?: string;
// TextBox customization
textBoxClassName?: string;
titleClassName?: string;
descriptionClassName?: string;
tagClassName?: string;
buttonsWrapperClassName?: string;
// Card customization
cardClassName?: string;
cardTitleClassName?: string;
cardDescriptionClassName?: string;
cardPriceClassName?: string;
cardImageClassName?: string;
}
const ProductCardOne = ({
products,
carouselMode = "buttons",
gridVariant,
uniformGridCustomHeightClasses = "min-h-80 2xl:min-h-90",
title,
description,
tag,
tagIcon,
buttons,
textboxLayout,
ariaLabel = "Product section",
className = "",
cardStackClassName = "",
textBoxClassName = "",
titleClassName = "",
descriptionClassName = "",
tagClassName = "",
buttonsWrapperClassName = "",
cardClassName = "",
cardTitleClassName = "",
cardDescriptionClassName = "",
cardPriceClassName = "",
cardImageClassName = "",
}: ProductCardOneProps) => {
return (
<section
aria-label={ariaLabel}
className={cls("w-full py-20", className)}
>
<div className="w-content-width mx-auto">
<CardStack
mode={carouselMode}
gridVariant={gridVariant}
uniformGridCustomHeightClasses={uniformGridCustomHeightClasses}
title={title}
description={description}
tag={tag}
tagIcon={tagIcon}
buttons={buttons}
textboxLayout={textboxLayout}
className={cardStackClassName}
textBoxClassName={textBoxClassName}
titleClassName={titleClassName}
descriptionClassName={descriptionClassName}
tagClassName={tagClassName}
buttonsWrapperClassName={buttonsWrapperClassName}
>
{products.map((product, index) => (
<div
key={`${product.title}-${index}`}
className={cls(
"card p-6 rounded-theme-capped h-full min-h-0 flex flex-col",
cardClassName
)}
>
<img
src={product.image}
alt={product.title}
className={cls("w-full h-48 object-cover mb-4", cardImageClassName)}
/>
<h3 className={cls("text-xl font-semibold mb-2", cardTitleClassName)}>
{product.title}
</h3>
<p className={cls("text-foreground/75 flex-1", cardDescriptionClassName)}>
{product.description}
</p>
<p className={cls("text-2xl font-bold mt-4", cardPriceClassName)}>
{product.price}
</p>
</div>
))}
</CardStack>
</div>
</section>
);
};
ProductCardOne.displayName = "ProductCardOne";
export default memo(ProductCardOne);
```
## Animation Types
CardStack supports GSAP-powered scroll-triggered animations:
```tsx
animationType?: "none" | "opacity" | "slide-up" | "scale-rotate" | "blur-reveal"
```
**Animation Descriptions:**
- **`none`** - No animation
- **`opacity`** - Fade in
- **`slide-up`** - Slide up from below with stagger
- **`scale-rotate`** - Scale + rotate entrance with stagger
- **`blur-reveal`** - Blur to clear reveal with stagger
Each animation uses GSAP ScrollTrigger with staggered effect on children.
## Best Practices
### ✅ DO:
- Accept `uniformGridCustomHeightClasses` as optional prop with sensible default
- Use `min-h-0` on individual card elements for proper flex behavior
- Pass through all CardStack customization props (className overrides)
- Use appropriate default height for your component type
- Document the default value in registry propsSchema
- Provide className props for all card sub-elements
- Use `card` class for consistent card styling (theme-aware)
- Use `rounded-theme-capped` for card border radius
- Set `carouselMode` default to `"buttons"` for accessibility
### ❌ DO NOT:
- Hardcode height classes in CardStack (let it be controlled via prop)
- Remove the `uniformGridCustomHeightClasses` prop without specific reason
- Use different height classes for grid vs carousel (they should match)
- Forget to apply `min-h-0` on card wrapper divs
- Specify button `variant` in ButtonConfig (controlled by ThemeProvider)
- Create more than 2 buttons per section
- Use `lg:` or `xl:` breakpoints for layout changes
## CardStack Component Checklist
When creating a new CardStack-based section component:
### Props & Configuration
- [ ] Accept `uniformGridCustomHeightClasses` prop with appropriate default
- [ ] Accept `carouselMode` prop (default: `"buttons"`)
- [ ] Accept `gridVariant` as required prop (or hardcode if single variant)
- [ ] Accept `textboxLayout` for TextBox configuration
- [ ] Accept `animationType` for scroll animations (optional)
### CardStack Integration
- [ ] Pass `uniformGridCustomHeightClasses` to CardStack
- [ ] Pass all TextBox props (title, description, tag, tagIcon, buttons)
- [ ] Pass all TextBox className overrides
- [ ] Pass cardStackClassName for CardStack wrapper customization
### Card Implementation
- [ ] Apply `min-h-0` to individual card wrapper divs
- [ ] Use `card` class for card background/border styling
- [ ] Use `rounded-theme-capped` for border radius
- [ ] Provide className override props for all card sub-elements
- [ ] Use `h-full` on cards for consistent heights within grid
### Button System
- [ ] Use ButtonConfig type for buttons array
- [ ] Do NOT specify variant in ButtonConfig
- [ ] Maximum 2 buttons
- [ ] Let ThemeProvider control button variant
### Section Structure
- [ ] Use semantic `<section>` tag with aria-label
- [ ] Use `w-full py-20` on section
- [ ] Use `w-content-width mx-auto` wrapper
- [ ] Provide section className override
### Documentation
- [ ] Document `uniformGridCustomHeightClasses` default in registry
- [ ] Document all grid variants supported
- [ ] Document carousel mode options
- [ ] Include usage example with typical props

View File

@@ -0,0 +1,433 @@
# Component Implementation Standards
This document outlines the core implementation patterns for creating components in this library, optimized for AI website builders.
## Component Structure Template
Every component should follow this structure:
```tsx
"use client";
import React from "react";
import { cls } from "@/lib/utils";
interface ComponentProps {
// Required props first
text: string;
// Optional props with explicit types
onClick?: () => void;
className?: string;
disabled?: boolean;
ariaLabel?: string;
type?: "button" | "submit" | "reset";
}
const Component = ({
text,
onClick,
className = "",
disabled = false,
ariaLabel,
type = "button",
}: ComponentProps) => {
return (
<element
type={type}
onClick={onClick}
disabled={disabled}
aria-label={ariaLabel || text}
className={cls("base-classes", "disabled-states", className)}
>
{text}
</element>
);
};
Component.displayName = "Component";
export default React.memo(Component);
```
**Key Requirements:**
- `"use client"` directive when needed (interactive components, hooks)
- Named exports with `displayName` for debugging
- Wrap in `React.memo()` for performance optimization
- Use `cls()` utility for class composition (never plain string concatenation)
## Prop Structure & Defaults
### Required Props
Core content props should be **required** with no default values:
- Section components: `title`, `description`
- Button components: `text`
- Media components: `imageSrc` or `videoSrc` (when applicable)
### Optional Props with Defaults
**Standard className defaults:**
```tsx
className = "",
textClassName = "",
iconClassName = "",
containerClassName = "",
```
Empty string defaults prevent undefined checks and are standard practice.
**Common optional props:**
```tsx
disabled = false,
type = "button",
ariaLabel, // No default, falls back to sensible value in component
```
**Component-specific props:**
Document defaults clearly in both code and registry:
```tsx
strengthFactor = 20,
carouselMode = "buttons",
uniformGridCustomHeightClasses = "min-h-80 2xl:min-h-90",
```
## Naming Conventions
### Section Components (Hero, About, Feature, etc.)
**✅ CORRECT:**
```tsx
interface HeroProps {
title: string; // Primary heading
description: string; // Supporting text
buttons?: ButtonConfig[];
}
```
**❌ WRONG:**
```tsx
interface HeroProps {
heading: string; // Should be "title"
subtitle: string; // Should be "description"
text: string; // Ambiguous
}
```
### Button Components
**✅ CORRECT:**
```tsx
interface ButtonProps {
text: string; // Button label
onClick?: () => void;
}
```
**❌ WRONG:**
```tsx
interface ButtonProps {
title: string; // Should be "text"
label: string; // Should be "text"
}
```
### Button Config (for sections)
```tsx
interface ButtonConfig {
text: string; // Button label (not "title" or "label")
href?: string;
onClick?: () => void;
props?: Partial<ButtonPropsForVariant<CTAButtonVariant>>;
// NO variant property - controlled by ThemeProvider
}
```
**Consistency is critical:**
- All hero sections must use the same prop names
- All about sections must use the same prop names
- Registry documentation must match component prop names exactly
## Component Customizability
Provide className props for **all major elements** to allow full styling control:
```tsx
interface SectionProps {
title: string;
description: string;
// Main wrapper
className?: string;
// Inner container
containerClassName?: string;
// Content areas
textClassName?: string;
mediaWrapperClassName?: string;
imageClassName?: string;
}
const Section = ({
title,
description,
className = "",
containerClassName = "",
textClassName = "",
mediaWrapperClassName = "",
imageClassName = "",
}: SectionProps) => {
return (
<section className={cls("base-section-styles", className)}>
<div className={cls("base-container-styles", containerClassName)}>
<div className={cls("base-text-styles", textClassName)}>
{/* content */}
</div>
<div className={cls("base-media-wrapper-styles", mediaWrapperClassName)}>
<img className={cls("base-image-styles", imageClassName)} />
</div>
</div>
</section>
);
};
```
**Naming convention:**
- `className` - Main wrapper element
- `containerClassName` - Inner container
- `[element]ClassName` - Specific elements (e.g., `textClassName`, `imageClassName`)
## Component Composition & Base Styles
When composing higher-level components from base components, **set sensible base styles** while accepting className overrides:
```tsx
interface HeroProps {
title: string;
description: string;
titleClassName?: string;
descriptionClassName?: string;
textBoxClassName?: string;
}
const Hero = ({
title,
description,
titleClassName = "",
descriptionClassName = "",
textBoxClassName = "",
}: HeroProps) => {
return (
<section>
<TextBox
title={title}
description={description}
// Set base styles, allow overrides
className={cls("flex flex-col gap-3 md:gap-1", textBoxClassName)}
titleClassName={cls("text-6xl font-medium", titleClassName)}
descriptionClassName={cls("text-lg leading-[1.2]", descriptionClassName)}
center={true}
/>
</section>
);
};
```
**Key principles:**
- Base styles come first in `cls()`, overrides second
- This ensures good defaults while maintaining full customizability
- AI builders can use components without styling knowledge, but advanced users can override
- Use `cls()` utility for proper class merging (prevents Tailwind conflicts)
## Type Safety
### Use Explicit Prop Interfaces
```tsx
// ✅ CORRECT - Clear and explicit
interface ButtonProps {
text: string;
onClick?: () => void;
variant?: "primary" | "secondary";
}
// ❌ WRONG - Over-complicated
interface ButtonProps extends React.ComponentPropsWithoutRef<'button'> {
// ... harder for AI to understand
}
```
### Use Discriminated Unions for Variants
```tsx
type MediaProps =
| {
imageSrc: string;
imageAlt?: string;
videoSrc?: never;
}
| {
videoSrc: string;
videoAriaLabel?: string;
imageSrc?: never;
};
```
### Export Reusable Types
```tsx
export type ButtonConfig = {
text: string;
href?: string;
onClick?: () => void;
};
export type GridVariant =
| "uniform-all-items-equal"
| "two-columns-alternating-heights"
| "asymmetric-60-wide-40-narrow"
// ... etc
```
## Responsive Design
### Mobile-First Approach
**Default styles apply to mobile devices:**
```tsx
// ✅ CORRECT - Mobile until md breakpoint (768px)
<div className="flex-col md:flex-row">
<img className="w-full h-auto md:h-8 md:w-auto" />
</div>
// ❌ WRONG - Using lg: breakpoint
<div className="flex-col lg:flex-row">
<img className="w-full h-auto lg:h-8 lg:w-auto" />
</div>
```
**Breakpoint Rules:**
- **Mobile styles**: No prefix (default)
- **Desktop styles**: `md:` prefix only (768px breakpoint)
- **Never use**: `lg:`, `xl:`, `2xl:` breakpoints for layout changes
**Exceptions:** Only use larger breakpoints for minor tweaks:
```tsx
// Acceptable for minor adjustments
className="min-h-80 2xl:min-h-90"
```
## Content Width Pattern
All section content must follow this structure:
```tsx
<section aria-label={ariaLabel || "Section name"} className="w-full py-20">
<div className="w-content-width mx-auto">
{/* content */}
</div>
</section>
```
**Rules:**
- Section: `w-full py-20` (full width with vertical padding)
- Inner div: `w-content-width mx-auto` (centered content with max width)
- `w-content-width` is controlled by ThemeProvider (small/medium/large)
**Exceptions:**
- Heroes and footers do NOT use `py-20` (they have custom spacing)
- Full-bleed sections may skip inner wrapper
## Vertical Spacing
**Standard sections:**
```tsx
className="w-full py-20"
```
**Exceptions (NO py-20):**
- Hero sections (custom spacing)
- Footer sections (custom spacing)
- Full-bleed sections with background colors
## Text Constraints
For button text and short labels:
```tsx
{
"text": {
"required": true,
"example": "Get Started",
"minChars": 2,
"maxChars": 15
}
}
```
**Button text rules:**
- Minimum: 2 characters
- Maximum: 15 characters
- Single-line only (no multiline support)
## Section Structure Pattern
```tsx
<section
aria-label={ariaLabel || "Default section label"}
className={cls(
"relative py-20 w-full",
useInvertedBackground === "invertDefault" && "bg-foreground",
className
)}
>
<div className="w-content-width mx-auto">
<TextBox
title={title}
description={description}
tag={tag}
tagIcon={tagIcon}
buttons={buttons}
textboxLayout={textboxLayout}
useInvertedBackground={useInvertedBackground}
// ... className overrides
/>
{/* Section-specific content */}
</div>
</section>
```
**Key Pattern Notes:**
- `useInvertedBackground` is a required prop: `"noInvert" | "invertDefault"`
- `"invertDefault"` creates a full-width inverted section with `bg-foreground`
- `"noInvert"` is the standard section with no background
- Always use explicit string equality checks (not truthy/falsy)
- Text colors should check for `"invertDefault"` mode
## Implementation Checklist
### Core Requirements
- [ ] Add `"use client"` directive if needed (hooks, interactivity)
- [ ] Use explicit prop interfaces (no over-complicated types)
- [ ] Set appropriate defaults for optional props
- [ ] Add `displayName` for debugging
- [ ] Wrap in `React.memo()` for performance
- [ ] Use semantic HTML tags (`<section>`, `<button>`, etc.)
### Customizability
- [ ] Provide className props for all major elements
- [ ] Use `cls()` utility for class composition
- [ ] Set base styles with override capability
- [ ] Follow naming convention (className, containerClassName, [element]ClassName)
### Responsive Design
- [ ] Mobile-first styles (no prefix)
- [ ] Desktop styles with `md:` prefix only
- [ ] Avoid `lg:`, `xl:`, `2xl:` for layout changes
- [ ] Use `w-content-width mx-auto` pattern
### Naming Conventions
- [ ] Section components: Use `title` and `description`
- [ ] Button components: Use `text`
- [ ] Button configs: Use `text` (not variant - controlled by theme)
- [ ] Consistent naming across similar component types
### Structure
- [ ] Required props first in interface
- [ ] Optional props with defaults after
- [ ] Empty string defaults for className props
- [ ] Document default values clearly

View File

@@ -0,0 +1,499 @@
# Preview Page Standards
This document outlines how to create preview pages for components in `/app/components/`.
## Purpose
Preview pages allow developers and AI builders to:
- See components in isolation
- Test component behavior and styling
- Verify responsive design
- Experiment with different prop configurations
- Ensure smooth scrolling and theme integration
## File Structure
### Location Pattern
```
/app/components/
├── sections/
│ ├── hero/
│ │ ├── billboard/
│ │ │ └── page.tsx // Preview for HeroBillboard
│ │ ├── split/
│ │ │ └── page.tsx // Preview for HeroSplit
│ ├── feature/
│ │ ├── card-one/
│ │ │ └── page.tsx // Preview for FeatureCardOne
├── buttons/
│ ├── text-stagger/
│ │ └── page.tsx // Preview for ButtonTextStagger
└── page.tsx // Main components index
```
**Pattern:** `/app/components/[category]/[component-name]/page.tsx`
**Component name formatting:**
- Use kebab-case for folder names
- `HeroBillboard``hero/billboard/`
- `FeatureCardOne``feature/card-one/`
- `ButtonTextStagger``buttons/text-stagger/`
## Preview Page Template
### Basic Template (Non-Section Components)
```tsx
"use client";
import React from "react";
import ReactLenis from "lenis/react";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import ComponentName from "@/components/category/ComponentName";
export default function ComponentPreviewPage() {
return (
<ThemeProvider
defaultButtonVariant="text-stagger"
defaultTextAnimation="entrance-slide"
borderRadius="rounded"
contentWidth="medium"
sizing="medium"
background="plain"
cardStyle="glass-flat"
primaryButtonStyle="gradient"
secondaryButtonStyle="glass"
headingFontWeight="medium"
>
<ReactLenis root>
<ComponentName
// Add realistic props here
text="Example"
onClick={() => console.log("clicked")}
/>
</ReactLenis>
</ThemeProvider>
);
}
```
### Section Component Template
```tsx
"use client";
import React from "react";
import ReactLenis from "lenis/react";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import SectionName from "@/components/sections/category/SectionName";
export default function SectionPreviewPage() {
return (
<ThemeProvider
defaultButtonVariant="icon-arrow"
defaultTextAnimation="entrance-slide"
borderRadius="pill"
contentWidth="medium"
sizing="medium"
background="animatedGrid"
cardStyle="glass-flat"
primaryButtonStyle="gradient"
secondaryButtonStyle="glass"
headingFontWeight="medium"
>
<ReactLenis root>
<SectionName
title="Preview Section Title"
description="This is a preview of the section component with example content."
buttons={[
{ text: "Get Started", href: "#" },
{ text: "Learn More", onClick: () => console.log("Learn more") }
]}
// Add section-specific props
/>
</ReactLenis>
</ThemeProvider>
);
}
```
### CardStack Section Template
```tsx
"use client";
import React from "react";
import ReactLenis from "lenis/react";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import { Package, Zap, Shield, Sparkles } from "lucide-react";
import FeatureCardOne from "@/components/sections/feature/FeatureCardOne";
export default function FeatureCardOnePreviewPage() {
const features = [
{
icon: Package,
title: "Feature One",
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
},
{
icon: Zap,
title: "Feature Two",
description: "Sed do eiusmod tempor incididunt ut labore et dolore."
},
{
icon: Shield,
title: "Feature Three",
description: "Ut enim ad minim veniam, quis nostrud exercitation."
},
{
icon: Sparkles,
title: "Feature Four",
description: "Duis aute irure dolor in reprehenderit in voluptate."
}
];
return (
<ThemeProvider
defaultButtonVariant="icon-arrow"
defaultTextAnimation="entrance-slide"
borderRadius="rounded"
contentWidth="medium"
sizing="medium"
background="animatedGrid"
cardStyle="glass-flat"
primaryButtonStyle="gradient"
secondaryButtonStyle="glass"
headingFontWeight="medium"
>
<ReactLenis root>
<FeatureCardOne
features={features}
gridVariant="uniform-all-items-equal"
textboxLayout="default"
title="Our Features"
description="Discover what makes us unique"
tag="Features"
tagIcon={Sparkles}
buttons={[
{ text: "View All", href: "#" }
]}
/>
</ReactLenis>
</ThemeProvider>
);
}
```
## Critical Requirements
### Wrapper Order
**MUST follow this order:**
```tsx
<ThemeProvider>
<ReactLenis root>
<Component />
</ReactLenis>
</ThemeProvider>
```
**❌ WRONG:**
```tsx
<ReactLenis root>
<ThemeProvider>
<Component />
</ThemeProvider>
</ReactLenis>
```
ReactLenis must be **inside** ThemeProvider, not outside.
### "use client" Directive
All preview pages must include `"use client"` at the top:
```tsx
"use client";
import React from "react";
// ...
```
This is required because:
- ReactLenis uses client-side hooks
- ThemeProvider uses React Context
- Components may use interactive features
### ReactLenis Root Prop
Always include the `root` prop:
```tsx
<ReactLenis root>
{/* components */}
</ReactLenis>
```
This enables page-wide smooth scrolling.
## Theme Configuration
### Recommended Defaults
**For most previews:**
```tsx
<ThemeProvider
defaultButtonVariant="icon-arrow"
defaultTextAnimation="entrance-slide"
borderRadius="rounded"
contentWidth="medium"
sizing="medium"
background="animatedGrid"
cardStyle="glass-flat"
primaryButtonStyle="gradient"
secondaryButtonStyle="glass"
headingFontWeight="medium"
>
```
**For button previews:**
```tsx
<ThemeProvider
defaultButtonVariant="text-stagger" // Match button being previewed
defaultTextAnimation="entrance-slide"
borderRadius="pill"
contentWidth="medium"
sizing="medium"
background="plain"
cardStyle="glass-flat"
primaryButtonStyle="gradient"
secondaryButtonStyle="glass"
headingFontWeight="medium"
>
```
**For hero previews:**
```tsx
<ThemeProvider
defaultButtonVariant="icon-arrow"
defaultTextAnimation="entrance-slide"
borderRadius="rounded"
contentWidth="large" // Wider for heroes
sizing="large" // Larger sizing for heroes
background="aurora" // Visual background
cardStyle="glass-flat"
primaryButtonStyle="gradient"
secondaryButtonStyle="glass"
headingFontWeight="semibold" // Bolder for heroes
>
```
### When to Customize
Customize theme settings when:
- Testing different button variants
- Showcasing card styles
- Demonstrating responsive behavior
- Highlighting specific theme features
## Realistic Props
### Use Realistic Content
**✅ GOOD:**
```tsx
<HeroBillboard
title="Build Amazing Websites Faster"
description="Create stunning, responsive websites with our modern component library. Ship faster, iterate quicker."
buttons={[
{ text: "Get Started", href: "/signup" },
{ text: "View Demo", onClick: () => window.open("/demo") }
]}
/>
```
**❌ BAD:**
```tsx
<HeroBillboard
title="Test"
description="Test description"
buttons={[
{ text: "Click", href: "#" }
]}
/>
```
### Sample Data Patterns
**Features:**
```tsx
const features = [
{
icon: Package,
title: "Fast Shipping",
description: "Get your order delivered within 2-3 business days."
},
// ... more features
];
```
**Products:**
```tsx
const products = [
{
title: "Premium Headphones",
description: "Wireless noise-cancelling headphones with 30-hour battery life.",
price: "$299",
image: "/images/headphones.jpg"
},
// ... more products
];
```
**Testimonials:**
```tsx
const testimonials = [
{
name: "Sarah Johnson",
role: "CEO, TechCorp",
content: "This component library transformed our development workflow. Highly recommend!",
image: "/images/avatar-1.jpg",
rating: 5
},
// ... more testimonials
];
```
## Multiple Sections Example
Preview pages can show multiple components together:
```tsx
"use client";
import React from "react";
import ReactLenis from "lenis/react";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import HeroBillboard from "@/components/sections/hero/HeroBillboard";
import FeatureCardOne from "@/components/sections/feature/FeatureCardOne";
import Footer from "@/components/sections/footer/FooterBase";
export default function FullPagePreview() {
return (
<ThemeProvider
defaultButtonVariant="icon-arrow"
defaultTextAnimation="entrance-slide"
borderRadius="rounded"
contentWidth="medium"
sizing="medium"
background="animatedGrid"
cardStyle="glass-flat"
primaryButtonStyle="gradient"
secondaryButtonStyle="glass"
headingFontWeight="medium"
>
<ReactLenis root>
<HeroBillboard {...heroProps} />
<FeatureCardOne {...featureProps} />
<Footer {...footerProps} />
</ReactLenis>
</ThemeProvider>
);
}
```
## Preview Page Checklist
### File Setup
- [ ] Create in correct location: `/app/components/[category]/[component-name]/page.tsx`
- [ ] Use kebab-case for folder names
- [ ] Add `"use client"` directive at top
- [ ] Export default function with descriptive name
### Wrapper Configuration
- [ ] Wrap in ThemeProvider (outer)
- [ ] Wrap in ReactLenis with `root` prop (inner)
- [ ] Correct order: ThemeProvider > ReactLenis > Component
- [ ] Import both wrappers
### Component Props
- [ ] Use realistic, representative content
- [ ] Include all required props
- [ ] Test with typical prop combinations
- [ ] Use proper TypeScript types (no `any`)
### Theme Settings
- [ ] Configure appropriate theme settings for component type
- [ ] Use sensible defaults that showcase the component well
- [ ] Test with different theme configurations if needed
### Quality Checks
- [ ] Component renders without errors
- [ ] Smooth scrolling works
- [ ] Responsive design functions correctly
- [ ] Animations trigger properly
- [ ] No console warnings or errors
## Common Patterns
### Background for Preview
If the component needs a background color to be visible:
```tsx
<ReactLenis root>
<div className="min-h-screen bg-background">
<Component {...props} />
</div>
</ReactLenis>
```
### Centered Preview
For small components that need centering:
```tsx
<ReactLenis root>
<div className="min-h-screen flex items-center justify-center bg-background">
<Component {...props} />
</div>
</ReactLenis>
```
### Multiple Variants
Show multiple variants of the same component:
```tsx
<ReactLenis root>
<div className="min-h-screen bg-background py-20 space-y-20">
<ComponentName variant="primary" {...props} />
<ComponentName variant="secondary" {...props} />
<ComponentName variant="ghost" {...props} />
</div>
</ReactLenis>
```
## Best Practices
### ✅ DO:
- Use realistic, production-quality content
- Test responsive behavior
- Include all ThemeProvider configuration
- Use ReactLenis for smooth scrolling
- Follow naming conventions (kebab-case folders)
- Include required props only (let optional props use defaults)
- Test with different theme settings
### ❌ DO NOT:
- Use placeholder text like "Lorem ipsum" (use realistic content)
- Skip ThemeProvider or ReactLenis
- Put ReactLenis outside ThemeProvider
- Use hardcoded colors that break theming
- Create overly complex multi-component demos (keep focused)
- Forget "use client" directive
- Use incorrect folder structure

145
docs/README.md Normal file
View File

@@ -0,0 +1,145 @@
# Component Library Documentation
This directory contains focused documentation for building components in this AI-optimized component library.
## Documentation Files
### 📋 [COMPONENT_IMPLEMENTATION.md](./COMPONENT_IMPLEMENTATION.md)
**Core component implementation patterns**
Load when: Creating or modifying component code
Covers:
- Component structure template
- Prop structure & defaults
- Naming conventions
- Component customizability
- Type safety
- Responsive design
- Content width pattern
- Implementation checklist
---
### 🎴 [CARDSTACK_SECTIONS.md](./CARDSTACK_SECTIONS.md)
**CardStack-based section components**
Load when: Creating Feature, Product, Pricing, Testimonial, Team, Blog, or Metrics sections
Covers:
- CardStack pattern overview
- Grid variants (10+ layouts)
- Height control (`uniformGridCustomHeightClasses`)
- Carousel modes
- TextBox integration
- Button system
- Animation types
- Complete examples & checklist
---
### 🎨 [THEME_AND_STYLING.md](./THEME_AND_STYLING.md)
**Theme system and styling patterns**
Load when: Setting up themes, working with colors, or styling components
Covers:
- Theme Provider configuration
- Color theming (CSS variables)
- Inverted background pattern
- Content width pattern
- Card styling
- Border radius patterns
- Button styling classes
- Styling checklist
---
### ♿ [ACCESSIBILITY.md](./ACCESSIBILITY.md)
**Accessibility (a11y) standards**
Load when: Adding interactive elements, media, or sections
Covers:
- Interactive components (buttons, links)
- Media components (images, videos)
- Section components (semantic HTML)
- Form components
- Focus management
- Keyboard navigation
- ARIA roles
- Accessibility checklist
---
### 📚 [REGISTRY_STANDARDS.md](./REGISTRY_STANDARDS.md)
**Registry documentation rules**
Load when: Adding or updating component entries in `registry.json`
Covers:
- Registry structure
- Component entry format
- Field descriptions
- propsSchema rules
- Constraints format
- Usage examples
- What to include/exclude
- Validation checklist
---
### 📄 [PREVIEW_PAGE_STANDARDS.md](./PREVIEW_PAGE_STANDARDS.md)
**Preview page setup and patterns**
Load when: Creating preview pages in `/app/components/`
Covers:
- File structure & location
- Preview page templates
- Wrapper order (ThemeProvider > ReactLenis)
- Theme configuration
- Realistic props
- Multiple sections example
- Preview page checklist
---
## Quick Reference
### When creating a new component:
1. Load `COMPONENT_IMPLEMENTATION.md` for structure
2. Load `ACCESSIBILITY.md` for a11y requirements
3. Load `THEME_AND_STYLING.md` for styling patterns
4. Load `CARDSTACK_SECTIONS.md` if using CardStack
### When updating the registry:
1. Load `REGISTRY_STANDARDS.md` only
### When creating a preview page:
1. Load `PREVIEW_PAGE_STANDARDS.md` only
### When modifying themes:
1. Load `THEME_AND_STYLING.md` only
---
## Documentation Principles
These docs are optimized for:
- **AI builders** (Lovable, V0, Claude Code)
- **Focused context** (load only what you need)
- **Quick reference** (checklists and examples)
- **Consistency** (standardized patterns across all components)
Each file is:
- **Single-purpose** - covers one concern thoroughly
- **Self-contained** - minimal cross-references
- **Example-driven** - shows good/bad patterns
- **Checklist-equipped** - actionable validation steps
---
## Legacy Documentation
The original `COMPONENT_STANDARDS.md` file has been split into these focused documents. Refer to these new files for all component development.

487
docs/REGISTRY_STANDARDS.md Normal file
View File

@@ -0,0 +1,487 @@
# Registry Documentation Standards
This document outlines how to document components in `registry.json` for AI website builders.
## Registry Structure
The registry is organized into two main sections:
```json
{
"componentRegistry": {
"button": [...],
"text": [...],
"navbar": [...],
"layout": [...]
},
"sectionRegistry": {
"hero": [...],
"about": [...],
"feature": [...],
"testimonial": [...],
"pricing": [...],
"team": [...],
"product": [...],
"metrics": [...],
"blog": [...],
"footer": [...],
"contact": [...],
"faq": [...],
"socialProof": [...]
}
}
```
**componentRegistry** - Base/utility components (buttons, text, navbar, CardStack, etc.)
**sectionRegistry** - Section components (hero, about, feature, etc.)
## Component Entry Format
Every component entry must follow this structure:
```json
{
"import": "import ComponentName from '@/components/category/ComponentName';",
"name": "ComponentName",
"path": "@/components/category/ComponentName",
"description": "Brief one-line description of what the component is.",
"details": "Longer description of when to use it, behavior, and constraints.",
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Example text",
"minChars": 2,
"maxChars": 15
}
}
},
"propsSchema": {
"text": "string",
"onClick?": "() => void",
"className?": "string",
"disabled?": "boolean (default: false)",
"ariaLabel?": "string",
"type?": "'button' | 'submit' | 'reset' (default: 'button')"
},
"usage": "<ComponentName text=\"Example\" onClick={() => console.log('clicked')} />"
}
```
## Field Descriptions
### import
The exact import statement AI should use.
**Format:**
```json
"import": "import ComponentName from '@/components/category/ComponentName';"
```
**Examples:**
```json
"import": "import HeroBillboard from '@/components/sections/hero/HeroBillboard';"
"import": "import ButtonTextStagger from '@/components/button/text-stagger/ButtonTextStagger';"
"import": "import CardStack from '@/components/cardStack/CardStack';"
```
### name
Component name exactly as exported.
**Format:**
```json
"name": "ComponentName"
```
### path
File path without extension.
**Format:**
```json
"path": "@/components/category/ComponentName"
```
### description
One-line summary of what the component is. Focus on visual/behavioral characteristics.
**Format:** 1 sentence, under 100 characters
**Good Examples:**
```json
"description": "CTA button with character stagger animation on hover."
"description": "Full-width hero section with centered text and billboard layout."
"description": "Feature section with grid or carousel layout for feature cards."
```
**Bad Examples:**
```json
"description": "A really cool button component with lots of features and animations that can be used anywhere." // Too verbose
"description": "Button" // Too vague
```
### details
Longer description covering:
- When to use it
- Key behavior notes
- Important constraints
**Format:** 2-4 sentences
**Good Example:**
```json
"details": "Use for primary or secondary CTAs where subtle text motion adds emphasis. On hover, the label's characters animate in sequence (stagger). Includes background styling and supports all standard button props."
```
**Bad Example:**
```json
"details": "This is a button that you can click and it will do something when you click it. It has animations." // Too obvious, not helpful
```
### constraints
Defines text length constraints for string props.
**Format:**
```json
"constraints": {
"textRules": {
"propName": {
"required": true,
"example": "Example value",
"minChars": 2,
"maxChars": 15
}
}
}
```
**Common Patterns:**
**Button text:**
```json
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Get Started",
"minChars": 2,
"maxChars": 15
}
}
}
```
**Section titles and descriptions:**
```json
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Welcome to Our Platform",
"minChars": 5,
"maxChars": 60
},
"description": {
"required": true,
"example": "Build amazing websites with our component library",
"minChars": 10,
"maxChars": 200
}
}
}
```
### propsSchema
Documents all component props with types and defaults.
**Format Rules:**
**Required props:**
```json
"propName": "type"
```
**Optional props:**
```json
"propName?": "type"
```
**Optional props with defaults:**
```json
"propName?": "type (default: value)"
```
**Examples:**
**Simple types:**
```json
"text": "string",
"count": "number",
"enabled": "boolean"
```
**Functions:**
```json
"onClick?": "() => void",
"onChange?": "(value: string) => void",
"onSubmit?": "(data: FormData) => Promise<void>"
```
**Union types:**
```json
"type?": "'button' | 'submit' | 'reset' (default: 'button')",
"variant?": "'primary' | 'secondary' | 'ghost'",
"size?": "'sm' | 'md' | 'lg' (default: 'md')"
```
**Array types:**
```json
"items": "Array<{ title: string; description: string }>",
"buttons?": "ButtonConfig[]",
"features": "Feature[]"
```
**Complex types:**
```json
"gridVariant": "'uniform-all-items-equal' | 'two-columns-alternating-heights' | 'asymmetric-60-wide-40-narrow' | ...",
"icon?": "LucideIcon",
"image?": "string (URL or path)"
```
**With defaults:**
```json
"className?": "string",
"disabled?": "boolean (default: false)",
"carouselMode?": "'auto' | 'buttons' (default: 'buttons')",
"uniformGridCustomHeightClasses?": "string (default: 'min-h-80 2xl:min-h-90')"
```
### usage
Single-line example showing typical implementation.
**Format:** One line, realistic props, valid JSX
**Good Examples:**
**Button:**
```json
"usage": "<ButtonTextStagger text=\"Get Started\" onClick={() => console.log('clicked')} />"
```
**Section with minimal props:**
```json
"usage": "<HeroBillboard title=\"Welcome\" description=\"Start building today\" buttons={[{ text: 'Get Started', href: '/signup' }]} />"
```
**CardStack section:**
```json
"usage": "<FeatureCardOne features={featuresData} gridVariant=\"uniform-all-items-equal\" textboxLayout=\"default\" title=\"Features\" description=\"Our key features\" />"
```
**Bad Examples:**
```json
"usage": "<Component />" // Missing required props
"usage": "<Component\n prop1=\"value\"\n prop2=\"value\"\n/>" // Multi-line, hard to read
"usage": "Component({ text: 'Hi' })" // Not JSX
```
## What to Include
### ✅ DO Include:
**Default values in propsSchema** - Critical for AI to generate correct code
```json
"disabled?": "boolean (default: false)",
"type?": "'button' | 'submit' | 'reset' (default: 'button')"
```
**Usage examples** - Helps AI understand context
```json
"usage": "<ButtonTextStagger text=\"Click me\" onClick={() => alert('Hi')} />"
```
**Text constraints** - Min/max character limits
```json
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Get Started",
"minChars": 2,
"maxChars": 15
}
}
}
```
**Accurate descriptions** - Ensure description matches actual behavior
```json
"description": "CTA button with character stagger animation on hover.",
"details": "Use for primary or secondary CTAs where subtle text motion adds emphasis."
```
**Use case guidance** - When to use this vs alternatives
```json
"details": "Use for hero sections with centered content and billboard layout. Best for landing pages and marketing sites."
```
## What NOT to Include
### ❌ DO NOT Include:
**Metadata field** - Unnecessary complexity
```json
// Don't do this:
"metadata": {
"category": "button",
"version": "1.0.0",
"author": "..."
}
```
**Verbose descriptions** - Keep concise and obvious
```json
// Don't do this:
"description": "This is an amazing button component that you can use to create buttons with stagger animations that look really cool and modern and will make your website stand out from the competition."
```
**Dependencies** - AI builders can infer from imports
```json
// Don't do this:
"dependencies": ["lucide-react", "framer-motion"]
```
**Over-documentation** - If it's obvious from the name, skip it
```json
// Don't do this:
"details": "This is a button. You can click it. It accepts text to display on the button."
```
**Implementation details** - Focus on usage, not internals
```json
// Don't do this:
"details": "Uses GSAP ScrollTrigger with stagger: 0.1 and uses React.memo for performance and has displayName set to ButtonTextStagger."
```
## Complete Examples
### Button Component
```json
{
"import": "import ButtonTextStagger from '@/components/button/text-stagger/ButtonTextStagger';",
"name": "ButtonTextStagger",
"path": "@/components/button/text-stagger/ButtonTextStagger",
"description": "CTA button with character stagger animation on hover.",
"details": "Use for primary or secondary CTAs where subtle text motion adds emphasis. On hover, the label's characters animate in sequence (stagger). Includes background styling.",
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Get Started",
"minChars": 2,
"maxChars": 15
}
}
},
"propsSchema": {
"text": "string",
"onClick?": "() => void",
"href?": "string",
"className?": "string",
"textClassName?": "string",
"disabled?": "boolean (default: false)",
"ariaLabel?": "string",
"type?": "'button' | 'submit' | 'reset' (default: 'button')"
},
"usage": "<ButtonTextStagger text=\"Get Started\" onClick={() => console.log('clicked')} />"
}
```
### Section Component (CardStack-based)
```json
{
"import": "import FeatureCardOne from '@/components/sections/feature/FeatureCardOne';",
"name": "FeatureCardOne",
"path": "@/components/sections/feature/FeatureCardOne",
"description": "Feature section with grid or carousel layout for feature cards.",
"details": "Displays feature cards in a responsive grid (1-4 items) or carousel (5+ items). Supports TextBox header with multiple layout options. Each card includes icon, title, and description.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Our Features",
"minChars": 5,
"maxChars": 60
},
"description": {
"required": true,
"example": "Discover what makes us unique",
"minChars": 10,
"maxChars": 200
}
}
},
"propsSchema": {
"features": "Array<{ icon: LucideIcon; title: string; description: string }>",
"gridVariant": "'uniform-all-items-equal' | 'two-columns-alternating-heights' | 'asymmetric-60-wide-40-narrow' | ...",
"title": "string",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "ButtonConfig[]",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description'",
"carouselMode?": "'auto' | 'buttons' (default: 'buttons')",
"uniformGridCustomHeightClasses?": "string (default: 'min-h-80 2xl:min-h-90')",
"ariaLabel?": "string",
"className?": "string"
},
"usage": "<FeatureCardOne features={featuresData} gridVariant=\"uniform-all-items-equal\" textboxLayout=\"default\" title=\"Features\" description=\"Our key features\" />"
}
```
## Registry Validation Checklist
When adding a new component to the registry:
### Required Fields
- [ ] `import` - Exact import statement
- [ ] `name` - Component name
- [ ] `path` - File path without extension
- [ ] `description` - One-line summary
- [ ] `details` - When to use, behavior, constraints
- [ ] `propsSchema` - All props documented
- [ ] `usage` - Single-line example
### Constraints (if applicable)
- [ ] Add `textRules` for text props
- [ ] Set `minChars` and `maxChars`
- [ ] Provide realistic `example` values
- [ ] Mark `required: true` for required props
### propsSchema Format
- [ ] Required props: `"prop": "type"`
- [ ] Optional props: `"prop?": "type"`
- [ ] Defaults: `"prop?": "type (default: value)"`
- [ ] All types match component implementation
- [ ] Union types use single quotes inside double quotes
### Quality Checks
- [ ] Description is concise (under 100 chars)
- [ ] Details provide use case guidance
- [ ] Usage example is valid JSX
- [ ] Usage example shows realistic props
- [ ] Default values documented in propsSchema
- [ ] No over-documentation or verbose descriptions
- [ ] No unnecessary metadata or dependencies
### Consistency Checks
- [ ] Component name matches file name
- [ ] Path matches actual file location
- [ ] Import statement is correct
- [ ] Props match actual component interface
- [ ] Defaults in registry match component defaults
- [ ] Naming follows conventions (title/description for sections, text for buttons)

521
docs/THEME_AND_STYLING.md Normal file
View File

@@ -0,0 +1,521 @@
# Theme and Styling Standards
This document covers the centralized theme system, color theming, and styling patterns used throughout the component library.
## Theme Provider System
All sections and components use a centralized ThemeProvider to maintain consistent styling across the entire site.
### Location & Setup
**Import:**
```tsx
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
```
**Usage:** Wrap the entire app/page (not individual sections) in a **single** ThemeProvider:
```tsx
export default function Page() {
return (
<ThemeProvider
defaultButtonVariant="text-stagger"
defaultTextAnimation="entrance-slide"
borderRadius="rounded"
contentWidth="medium"
sizing="medium"
background="animatedGrid"
cardStyle="glass-flat"
primaryButtonStyle="gradient"
secondaryButtonStyle="glass"
headingFontWeight="medium"
>
<HeroBillboard {...props} />
<FeatureSection {...props} />
<Footer {...props} />
</ThemeProvider>
);
}
```
### Theme Configuration Options
#### defaultButtonVariant
Controls the button style for ALL buttons in sections.
**Options:**
- `"text-stagger"` - Character stagger animation on hover (default)
- `"shift-hover"` - Text shifts on hover
- `"icon-arrow"` - Text + right arrow icon
- `"hover-magnetic"` - Cursor-tracking magnetic effect
- `"hover-bubble"` - Expanding circle on hover
- `"expand-hover"` - Width expansion on hover
#### defaultTextAnimation
Controls the text animation type for ALL text in sections.
**Options:**
- `"entrance-slide"` - Slide up from below (default)
- `"reveal-blur"` - Blur to clear reveal
- `"background-highlight"` - Background highlight effect
#### borderRadius
Controls border radius for buttons and cards.
**Options:**
- `"rounded"` - Standard rounded corners
- `"pill"` - Fully rounded (pill shape)
- `"sharp"` - No border radius
#### contentWidth
Controls the max width of section content.
**Options:**
- `"small"` - Narrow content width
- `"medium"` - Standard content width (default)
- `"large"` - Wide content width
Maps to `w-content-width` CSS class.
#### sizing
Controls spacing and size scale throughout components.
**Options:**
- `"small"` - Compact spacing
- `"medium"` - Standard spacing (default)
- `"large"` - Generous spacing
#### background
Default background pattern for the page.
**Options:**
- `"plain"` - Solid background color
- `"animatedGrid"` - Animated grid pattern
- `"aurora"` - Aurora gradient effect
- `"dotGrid"` - Dot grid pattern
- And more...
#### cardStyle
Visual style for all card components.
**Options:**
- `"glass-flat"` - Flat glass effect (default)
- `"glass-depth"` - Glass with depth/shadow
- `"glass-outline"` - Outlined glass
- `"solid-accent-light"` - Solid light accent
- `"outline"` - Simple outline
- `"elevated"` - Elevated shadow effect
- `"frosted"` - Frosted glass
- And more...
#### primaryButtonStyle
Style for primary buttons (first button in array).
**Options:**
- `"gradient"` - Gradient background
- `"solid"` - Solid color background
- `"glass"` - Glass effect
- `"outline"` - Outlined button
#### secondaryButtonStyle
Style for secondary buttons (second+ button in array).
**Options:**
- `"glass"` - Glass effect (default)
- `"outline"` - Outlined button
- `"solid"` - Solid color background
- `"gradient"` - Gradient background
#### headingFontWeight
Font weight for all headings.
**Options:**
- `"normal"` - Regular weight
- `"medium"` - Medium weight (default)
- `"semibold"` - Semi-bold weight
- `"bold"` - Bold weight
### Using Theme in Components
#### useTheme Hook
```tsx
import { useTheme } from "@/providers/themeProvider/ThemeProvider";
const Component = () => {
const theme = useTheme();
// Access theme properties:
// - theme.defaultButtonVariant
// - theme.defaultTextAnimation
// - theme.borderRadius
// - theme.cardStyle
// - theme.contentWidth
// - theme.sizing
// - theme.background
// - theme.primaryButtonStyle
// - theme.secondaryButtonStyle
// - theme.headingFontWeight
return <div>{/* component */}</div>;
};
```
#### TextBox Component Example
TextBox automatically applies theme defaults:
```tsx
const TextBox = ({ type, buttons, ...props }: TextBoxProps) => {
const theme = useTheme();
// Use default text animation from theme if not specified
const animationType = type || theme.defaultTextAnimation;
// Button variant comes from theme
const variant = theme.defaultButtonVariant;
// ...
};
```
### Important Rules
**DO NOT:**
- Specify button `variant` in section button configs (controlled by ThemeProvider)
- Wrap individual sections in ThemeProvider (use ONE provider per site/page)
- Override theme defaults unless explicitly required by component design
**DO:**
- Wrap the entire app/page in a single ThemeProvider
- Let all sections inherit theme defaults automatically
- Use `useTheme()` hook to access theme configuration
- Document when components don't follow theme defaults (with clear reason)
## Color & Theming
### CSS Custom Properties
**Always use CSS custom properties for colors** to ensure theme consistency:
```tsx
// ✅ CORRECT - Uses theme variables
<div className="bg-background text-foreground">
<button className="bg-foreground text-background">Click me</button>
</div>
// ❌ WRONG - Hardcoded colors break theming
<div className="bg-white text-black">
<button className="bg-black text-white">Click me</button>
</div>
```
### Standard Color Variables
**Background & Text:**
- `bg-background` - Main background color
- `text-foreground` - Main text color
- `bg-foreground` - Inverse background (for buttons, accents)
- `text-background` - Inverse text (for text on dark backgrounds)
**Cards & Surfaces:**
- `card` - Card/surface background with border (theme-aware)
- Maps to different styles based on `theme.cardStyle`
**Buttons:**
- `primary-button` - Primary button styling (index 0)
- `secondary-button` - Secondary button styling (index 1+)
**Opacity Modifiers:**
```tsx
text-foreground/75 // 75% opacity
text-background/50 // 50% opacity
bg-foreground/10 // 10% opacity
```
### When to Use Theme Colors
**Always prefer theme variables:**
- Backgrounds, text, borders, shadows
- Ensures proper dark mode support
- Allows theme customization
- Maintains visual consistency
**Only use hardcoded colors:**
- Very specific one-off cases with clear justification
- Decorative elements that shouldn't change with theme
- Must be documented in component comments
## Inverted Background Pattern
Section components support three modes for background styling, allowing flexible visual contrast and card-style layouts.
### Three Background Modes
**`"noInvert"`** - Standard background (default page background color)
- No background color applied to section
- Text uses standard `text-foreground` color
- Full-width section
**`"invertDefault"`** - Full-width inverted background
- Section gets `bg-foreground` background
- Text uses `text-background` color for contrast
- Full-width section with inverted colors
### Implementation Pattern
```tsx
import { cls } from "@/lib/utils";
import { useTheme } from "@/providers/themeProvider/ThemeProvider";
interface SectionProps {
title: string;
description: string;
useInvertedBackground: "noInvert" | "invertDefault"; // Required
// ... other props
}
const Section = ({
title,
description,
useInvertedBackground,
className = "",
// ... other props
}: SectionProps) => {
const theme = useTheme();
return (
<section
className={cls(
"relative py-20 w-full",
useInvertedBackground === "invertDefault" && "bg-foreground",
className
)}
>
<div className="w-content-width mx-auto">
<h1 className={cls(
"text-6xl font-medium",
useInvertedBackground === "invertDefault" && "text-background",
titleClassName
)}>
{title}
</h1>
<p className={cls(
"text-lg",
useInvertedBackground === "invertDefault"
? "text-background/75"
: "text-foreground/75",
descriptionClassName
)}>
{description}
</p>
</div>
</section>
);
};
```
### Key Points
1. **Required Prop**: `useInvertedBackground` should be a required string union type (no `?`), forcing explicit choice
2. **Two Modes**: `"noInvert"`, `"invertDefault"`
3. **Section Width**: Always `w-full`
4. **Background Color**:
- `"invertDefault"``bg-foreground`
- `"noInvert"` → no background
5. **Text Colors**: Apply `text-background` or `text-background/75` for `"invertDefault"` mode
6. **Relative Positioning**: Section needs `relative` class for proper z-index stacking
7. **Conditional Logic**: Use explicit string equality checks (not truthy/falsy)
### Section className Pattern
**Standard pattern for all sections:**
```tsx
<section
className={cls(
"relative py-20 w-full",
useInvertedBackground === "invertDefault" && "bg-foreground",
className
)}
>
```
### Text Color Pattern
**For text elements:**
```tsx
// Single check for invert mode:
useInvertedBackground === "invertDefault" && "text-background"
// Ternary for opacity variants:
useInvertedBackground === "invertDefault"
? "text-background/75"
: "text-foreground/75"
```
### For Components with Cards (Advanced)
When a section contains cards with light backgrounds, use the `shouldUseInvertedText` utility:
```tsx
import { cls, shouldUseInvertedText } from "@/lib/utils";
import { useTheme } from "@/providers/themeProvider/ThemeProvider";
const SectionWithCards = ({
useInvertedBackground,
// ... other props
}: SectionProps) => {
const theme = useTheme();
const shouldUseLightText = shouldUseInvertedText(
useInvertedBackground,
theme.cardStyle
);
return (
<section
className={cls(
"relative py-20 w-full",
useInvertedBackground === "invertDefault" && "bg-foreground",
className
)}
>
{/* For elements inside cards or with card backgrounds */}
<h3 className={cls(
"text-xl",
shouldUseLightText && "text-background",
bulletTitleClassName
)}>
{point.title}
</h3>
</section>
);
};
```
**What it does:**
The `shouldUseInvertedText` utility checks if:
- `useInvertedBackground` is `"invertDefault"` AND
- Current `cardStyle` is a "light" style (e.g., `glass-elevated`, `outline`, etc.)
This ensures text inside cards remains readable regardless of theme configuration.
### Width Classes Explained
**`w-content-width`** - Content container width
- Controlled by `theme.contentWidth` (small/medium/large)
- Used for inner content wrapper in all sections
## Content Width Pattern
All section content must use the `w-content-width` class:
```tsx
<section className="w-full py-20">
<div className="w-content-width mx-auto">
{/* content */}
</div>
</section>
```
**What it does:**
- Controlled by `theme.contentWidth` (small/medium/large)
- Automatically adjusts max-width based on theme setting
- Centers content with `mx-auto`
## Section Spacing
**Standard sections:**
```tsx
className="w-full py-20"
```
Vertical padding of `py-20` (5rem = 80px) on top and bottom.
**Exceptions (NO py-20):**
- Hero sections (custom spacing based on design)
- Footer sections (custom spacing)
- Full-bleed sections with background colors/images
## Card Styling Pattern
Use the `card` class for all card components:
```tsx
<div className={cls("card p-6 rounded-theme-capped h-full min-h-0", cardClassName)}>
{/* card content */}
</div>
```
**Classes explained:**
- `card` - Theme-aware background/border (maps to `theme.cardStyle`)
- `p-6` - Standard padding (1.5rem = 24px)
- `rounded-theme-capped` - Border radius from theme (respects `theme.borderRadius`)
- `h-full` - Fill parent height (for grid layouts)
- `min-h-0` - Prevent height conflicts (important for flex layouts)
## Border Radius Pattern
**For cards:**
```tsx
className="rounded-theme-capped"
```
**For buttons:**
```tsx
className="rounded-theme"
```
Both respect `theme.borderRadius` setting (rounded/pill/sharp).
## Button Styling Classes
**Primary button (first in array):**
```tsx
className="primary-button"
```
**Secondary button (second+ in array):**
```tsx
className="secondary-button"
```
These classes are theme-aware and map to:
- `theme.primaryButtonStyle` (gradient/solid/glass/outline)
- `theme.secondaryButtonStyle` (glass/outline/solid/gradient)
## Styling Checklist
### Color Usage
- [ ] Use `bg-background` and `text-foreground` for main colors
- [ ] Use `bg-foreground` and `text-background` for inverted sections
- [ ] Use `card` class for card backgrounds
- [ ] Use `primary-button` and `secondary-button` for buttons
- [ ] Avoid hardcoded colors (white, black, gray-X) unless justified
### Theme Integration
- [ ] Wrap app/page in single ThemeProvider
- [ ] Use `useTheme()` hook when needed
- [ ] Don't specify button variants in ButtonConfig
- [ ] Let TextBox inherit default text animation
- [ ] Use `w-content-width mx-auto` for content
### Inverted Background (if applicable)
- [ ] Accept `useInvertedBackground` as required string union: `"noInvert" | "invertDefault"`
- [ ] Add `relative` class to section
- [ ] Implement two-mode section className pattern (invertDefault with bg-foreground, noInvert standard)
- [ ] Apply `text-background` to text for `"invertDefault"` mode (not `"noInvert"`)
- [ ] Use explicit string equality checks (not truthy/falsy)
- [ ] Use `shouldUseInvertedText` for card content if needed
### Card Styling
- [ ] Use `card` class for theme-aware background
- [ ] Use `rounded-theme-capped` for border radius
- [ ] Include `min-h-0` for flex compatibility
- [ ] Provide `cardClassName` override prop
### Spacing
- [ ] Use `py-20` on sections (except hero/footer)
- [ ] Use `w-content-width mx-auto` wrapper
- [ ] Follow theme spacing guidelines

55
eslint.config.mjs Normal file
View File

@@ -0,0 +1,55 @@
import tseslint from "typescript-eslint";
import reactPlugin from "eslint-plugin-react";
import reactHooksPlugin from "eslint-plugin-react-hooks";
import nextPlugin from "@next/eslint-plugin-next";
export default tseslint.config(
...tseslint.configs.recommended,
{
files: ["**/*.{js,jsx,ts,tsx}"],
rules: {
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/no-unused-expressions": "warn",
"@typescript-eslint/no-explicit-any": "off",
},
},
{
files: ["src/app/*.{js,jsx,ts,tsx}"],
plugins: {
react: reactPlugin,
"react-hooks": reactHooksPlugin,
"@next/next": nextPlugin,
},
languageOptions: {
ecmaVersion: "latest",
sourceType: "module",
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
settings: {
react: {
version: "detect",
},
},
rules: {
...reactPlugin.configs["jsx-runtime"].rules,
...reactHooksPlugin.configs.recommended.rules,
...nextPlugin.configs.recommended.rules,
...nextPlugin.configs["core-web-vitals"].rules,
"react/no-unescaped-entities": "off",
"@typescript-eslint/no-explicit-any": "off",
},
},
{
ignores: [
"node_modules/**",
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
],
}
);

301
fontThemes.json Normal file
View File

@@ -0,0 +1,301 @@
{
"singleFonts": {
"interTight": {
"name": "Inter Tight",
"import": "import { Inter_Tight } from \"next/font/google\";",
"initialization": "const interTight = Inter_Tight({\n variable: \"--font-inter-tight\",\n subsets: [\"latin\"],\n weight: [\"100\", \"200\", \"300\", \"400\", \"500\", \"600\", \"700\", \"800\", \"900\"],\n});",
"className": "${interTight.variable}",
"cssVariable": "font-family: var(--font-inter-tight), sans-serif;"
},
"inter": {
"name": "Inter",
"import": "import { Inter } from \"next/font/google\";",
"initialization": "const inter = Inter({\n variable: \"--font-inter\",\n subsets: [\"latin\"],\n});",
"className": "${inter.variable}",
"cssVariable": "font-family: var(--font-inter), sans-serif;"
},
"poppins": {
"name": "Poppins",
"import": "import { Poppins } from \"next/font/google\";",
"initialization": "const poppins = Poppins({\n variable: \"--font-poppins\",\n subsets: [\"latin\"],\n weight: [\"100\", \"200\", \"300\", \"400\", \"500\", \"600\", \"700\", \"800\", \"900\"],\n});",
"className": "${poppins.variable}",
"cssVariable": "font-family: var(--font-poppins), sans-serif;"
},
"montserrat": {
"name": "Montserrat",
"import": "import { Montserrat } from \"next/font/google\";",
"initialization": "const montserrat = Montserrat({\n variable: \"--font-montserrat\",\n subsets: [\"latin\"],\n});",
"className": "${montserrat.variable}",
"cssVariable": "font-family: var(--font-montserrat), sans-serif;"
},
"roboto": {
"name": "Roboto",
"import": "import { Roboto } from \"next/font/google\";",
"initialization": "const roboto = Roboto({\n variable: \"--font-roboto\",\n subsets: [\"latin\"],\n weight: [\"100\", \"300\", \"400\", \"500\", \"700\", \"900\"],\n});",
"className": "${roboto.variable}",
"cssVariable": "font-family: var(--font-roboto), sans-serif;"
},
"openSans": {
"name": "Open Sans",
"import": "import { Open_Sans } from \"next/font/google\";",
"initialization": "const openSans = Open_Sans({\n variable: \"--font-open-sans\",\n subsets: [\"latin\"],\n});",
"className": "${openSans.variable}",
"cssVariable": "font-family: var(--font-open-sans), sans-serif;"
},
"lato": {
"name": "Lato",
"import": "import { Lato } from \"next/font/google\";",
"initialization": "const lato = Lato({\n variable: \"--font-lato\",\n subsets: [\"latin\"],\n weight: [\"100\", \"300\", \"400\", \"700\", \"900\"],\n});",
"className": "${lato.variable}",
"cssVariable": "font-family: var(--font-lato), sans-serif;"
},
"workSans": {
"name": "Work Sans",
"import": "import { Work_Sans } from \"next/font/google\";",
"initialization": "const workSans = Work_Sans({\n variable: \"--font-work-sans\",\n subsets: [\"latin\"],\n});",
"className": "${workSans.variable}",
"cssVariable": "font-family: var(--font-work-sans), sans-serif;"
},
"dmSans": {
"name": "DM Sans",
"import": "import { DM_Sans } from \"next/font/google\";",
"initialization": "const dmSans = DM_Sans({\n variable: \"--font-dm-sans\",\n subsets: [\"latin\"],\n});",
"className": "${dmSans.variable}",
"cssVariable": "font-family: var(--font-dm-sans), sans-serif;"
},
"plusJakartaSans": {
"name": "Plus Jakarta Sans",
"import": "import { Plus_Jakarta_Sans } from \"next/font/google\";",
"initialization": "const plusJakartaSans = Plus_Jakarta_Sans({\n variable: \"--font-plus-jakarta-sans\",\n subsets: [\"latin\"],\n});",
"className": "${plusJakartaSans.variable}",
"cssVariable": "font-family: var(--font-plus-jakarta-sans), sans-serif;"
},
"manrope": {
"name": "Manrope",
"import": "import { Manrope } from \"next/font/google\";",
"initialization": "const manrope = Manrope({\n variable: \"--font-manrope\",\n subsets: [\"latin\"],\n});",
"className": "${manrope.variable}",
"cssVariable": "font-family: var(--font-manrope), sans-serif;"
},
"rubik": {
"name": "Rubik",
"import": "import { Rubik } from \"next/font/google\";",
"initialization": "const rubik = Rubik({\n variable: \"--font-rubik\",\n subsets: [\"latin\"],\n});",
"className": "${rubik.variable}",
"cssVariable": "font-family: var(--font-rubik), sans-serif;"
},
"sourceSans3": {
"name": "Source Sans 3",
"import": "import { Source_Sans_3 } from \"next/font/google\";",
"initialization": "const sourceSans3 = Source_Sans_3({\n variable: \"--font-source-sans-3\",\n subsets: [\"latin\"],\n});",
"className": "${sourceSans3.variable}",
"cssVariable": "font-family: var(--font-source-sans-3), sans-serif;"
},
"cormorantGaramond": {
"name": "Cormorant Garamond",
"import": "import { Cormorant_Garamond } from \"next/font/google\";",
"initialization": "const cormorantGaramond = Cormorant_Garamond({\n variable: \"--font-cormorant-garamond\",\n subsets: [\"latin\"],\n weight: [\"300\", \"400\", \"500\", \"600\", \"700\"],\n});",
"className": "${cormorantGaramond.variable}",
"cssVariable": "font-family: var(--font-cormorant-garamond), serif;",
"category": "serif"
},
"lora": {
"name": "Lora",
"import": "import { Lora } from \"next/font/google\";",
"initialization": "const lora = Lora({\n variable: \"--font-lora\",\n subsets: [\"latin\"],\n});",
"className": "${lora.variable}",
"cssVariable": "font-family: var(--font-lora), serif;",
"category": "serif"
},
"publicSans": {
"name": "Public Sans",
"import": "import { Public_Sans } from \"next/font/google\";",
"initialization": "const publicSans = Public_Sans({\n variable: \"--font-public-sans\",\n subsets: [\"latin\"],\n});",
"className": "${publicSans.variable}",
"cssVariable": "font-family: var(--font-public-sans), sans-serif;"
},
"notoSans": {
"name": "Noto Sans",
"import": "import { Noto_Sans } from \"next/font/google\";",
"initialization": "const notoSans = Noto_Sans({\n variable: \"--font-noto-sans\",\n subsets: [\"latin\"],\n});",
"className": "${notoSans.variable}",
"cssVariable": "font-family: var(--font-noto-sans), sans-serif;"
},
"mulish": {
"name": "Mulish",
"import": "import { Mulish } from \"next/font/google\";",
"initialization": "const mulish = Mulish({\n variable: \"--font-mulish\",\n subsets: [\"latin\"],\n});",
"className": "${mulish.variable}",
"cssVariable": "font-family: var(--font-mulish), sans-serif;"
},
"ibmPlexSans": {
"name": "IBM Plex Sans",
"import": "import { IBM_Plex_Sans } from \"next/font/google\";",
"initialization": "const ibmPlexSans = IBM_Plex_Sans({\n variable: \"--font-ibm-plex-sans\",\n subsets: [\"latin\"],\n weight: [\"100\", \"200\", \"300\", \"400\", \"500\", \"600\", \"700\"],\n});",
"className": "${ibmPlexSans.variable}",
"cssVariable": "font-family: var(--font-ibm-plex-sans), sans-serif;"
}
},
"fontPairings": {
"interOpenSans": {
"name": "Inter + Open Sans",
"description": "Neutral headings with friendly body. Clean and approachable.",
"headingFont": "inter",
"bodyFont": "openSans",
"imports": "import { Inter } from \"next/font/google\";\nimport { Open_Sans } from \"next/font/google\";",
"initializations": "const inter = Inter({\n variable: \"--font-inter\",\n subsets: [\"latin\"],\n});\n\nconst openSans = Open_Sans({\n variable: \"--font-open-sans\",\n subsets: [\"latin\"],\n});",
"classNames": "${inter.variable} ${openSans.variable}",
"globalsCss": {
"instructions": "Update the font-family property within the existing CSS rules in globals.css (@layer base section)",
"bodyRule": "body {\n /* ... existing properties ... */\n font-family: var(--font-open-sans), sans-serif;\n}",
"headingsRule": "h1, h2, h3, h4, h5, h6 {\n font-family: var(--font-inter), sans-serif;\n}",
"bodyFontFamily": "var(--font-open-sans), sans-serif",
"headingsFontFamily": "var(--font-inter), sans-serif"
}
},
"dmSansInter": {
"name": "DM Sans + Inter",
"description": "Modern geometric headings with neutral body. Contemporary and clean.",
"headingFont": "dmSans",
"bodyFont": "inter",
"imports": "import { DM_Sans } from \"next/font/google\";\nimport { Inter } from \"next/font/google\";",
"initializations": "const dmSans = DM_Sans({\n variable: \"--font-dm-sans\",\n subsets: [\"latin\"],\n});\n\nconst inter = Inter({\n variable: \"--font-inter\",\n subsets: [\"latin\"],\n});",
"classNames": "${dmSans.variable} ${inter.variable}",
"globalsCss": {
"instructions": "Update the font-family property within the existing CSS rules in globals.css (@layer base section)",
"bodyRule": "body {\n /* ... existing properties ... */\n font-family: var(--font-inter), sans-serif;\n}",
"headingsRule": "h1, h2, h3, h4, h5, h6 {\n font-family: var(--font-dm-sans), sans-serif;\n}",
"bodyFontFamily": "var(--font-inter), sans-serif",
"headingsFontFamily": "var(--font-dm-sans), sans-serif"
}
},
"workSansSourceSans3": {
"name": "Work Sans + Source Sans 3",
"description": "Versatile headings with modern body. Professional and balanced.",
"headingFont": "workSans",
"bodyFont": "sourceSans3",
"imports": "import { Work_Sans } from \"next/font/google\";\nimport { Source_Sans_3 } from \"next/font/google\";",
"initializations": "const workSans = Work_Sans({\n variable: \"--font-work-sans\",\n subsets: [\"latin\"],\n});\n\nconst sourceSans3 = Source_Sans_3({\n variable: \"--font-source-sans-3\",\n subsets: [\"latin\"],\n});",
"classNames": "${workSans.variable} ${sourceSans3.variable}",
"globalsCss": {
"instructions": "Update the font-family property within the existing CSS rules in globals.css (@layer base section)",
"bodyRule": "body {\n /* ... existing properties ... */\n font-family: var(--font-source-sans-3), sans-serif;\n}",
"headingsRule": "h1, h2, h3, h4, h5, h6 {\n font-family: var(--font-work-sans), sans-serif;\n}",
"bodyFontFamily": "var(--font-source-sans-3), sans-serif",
"headingsFontFamily": "var(--font-work-sans), sans-serif"
}
},
"manropeDmSans": {
"name": "Manrope + DM Sans",
"description": "Geometric headings with clean body. Modern and professional.",
"headingFont": "manrope",
"bodyFont": "dmSans",
"imports": "import { Manrope } from \"next/font/google\";\nimport { DM_Sans } from \"next/font/google\";",
"initializations": "const manrope = Manrope({\n variable: \"--font-manrope\",\n subsets: [\"latin\"],\n});\n\nconst dmSans = DM_Sans({\n variable: \"--font-dm-sans\",\n subsets: [\"latin\"],\n});",
"classNames": "${manrope.variable} ${dmSans.variable}",
"globalsCss": {
"instructions": "Update the font-family property within the existing CSS rules in globals.css (@layer base section)",
"bodyRule": "body {\n /* ... existing properties ... */\n font-family: var(--font-dm-sans), sans-serif;\n}",
"headingsRule": "h1, h2, h3, h4, h5, h6 {\n font-family: var(--font-manrope), sans-serif;\n}",
"bodyFontFamily": "var(--font-dm-sans), sans-serif",
"headingsFontFamily": "var(--font-manrope), sans-serif"
}
},
"publicSansInter": {
"name": "Public Sans + Inter",
"description": "Government-inspired headings with neutral body. Professional and trustworthy.",
"headingFont": "publicSans",
"bodyFont": "inter",
"imports": "import { Public_Sans } from \"next/font/google\";\nimport { Inter } from \"next/font/google\";",
"initializations": "const publicSans = Public_Sans({\n variable: \"--font-public-sans\",\n subsets: [\"latin\"],\n});\n\nconst inter = Inter({\n variable: \"--font-inter\",\n subsets: [\"latin\"],\n});",
"classNames": "${publicSans.variable} ${inter.variable}",
"globalsCss": {
"instructions": "Update the font-family property within the existing CSS rules in globals.css (@layer base section)",
"bodyRule": "body {\n /* ... existing properties ... */\n font-family: var(--font-inter), sans-serif;\n}",
"headingsRule": "h1, h2, h3, h4, h5, h6 {\n font-family: var(--font-public-sans), sans-serif;\n}",
"bodyFontFamily": "var(--font-inter), sans-serif",
"headingsFontFamily": "var(--font-public-sans), sans-serif"
}
},
"notoSansInter": {
"name": "Noto Sans + Inter",
"description": "Universal headings with neutral body. Global and accessible.",
"headingFont": "notoSans",
"bodyFont": "inter",
"imports": "import { Noto_Sans } from \"next/font/google\";\nimport { Inter } from \"next/font/google\";",
"initializations": "const notoSans = Noto_Sans({\n variable: \"--font-noto-sans\",\n subsets: [\"latin\"],\n});\n\nconst inter = Inter({\n variable: \"--font-inter\",\n subsets: [\"latin\"],\n});",
"classNames": "${notoSans.variable} ${inter.variable}",
"globalsCss": {
"instructions": "Update the font-family property within the existing CSS rules in globals.css (@layer base section)",
"bodyRule": "body {\n /* ... existing properties ... */\n font-family: var(--font-inter), sans-serif;\n}",
"headingsRule": "h1, h2, h3, h4, h5, h6 {\n font-family: var(--font-noto-sans), sans-serif;\n}",
"bodyFontFamily": "var(--font-inter), sans-serif",
"headingsFontFamily": "var(--font-noto-sans), sans-serif"
}
},
"openSansWorkSans": {
"name": "Open Sans + Work Sans",
"description": "Friendly headings with versatile body. Approachable and balanced.",
"headingFont": "openSans",
"bodyFont": "workSans",
"imports": "import { Open_Sans } from \"next/font/google\";\nimport { Work_Sans } from \"next/font/google\";",
"initializations": "const openSans = Open_Sans({\n variable: \"--font-open-sans\",\n subsets: [\"latin\"],\n});\n\nconst workSans = Work_Sans({\n variable: \"--font-work-sans\",\n subsets: [\"latin\"],\n});",
"classNames": "${openSans.variable} ${workSans.variable}",
"globalsCss": {
"instructions": "Update the font-family property within the existing CSS rules in globals.css (@layer base section)",
"bodyRule": "body {\n /* ... existing properties ... */\n font-family: var(--font-work-sans), sans-serif;\n}",
"headingsRule": "h1, h2, h3, h4, h5, h6 {\n font-family: var(--font-open-sans), sans-serif;\n}",
"bodyFontFamily": "var(--font-work-sans), sans-serif",
"headingsFontFamily": "var(--font-open-sans), sans-serif"
}
},
"mulishInter": {
"name": "Mulish + Inter",
"description": "Minimal headings with neutral body. Clean and modern.",
"headingFont": "mulish",
"bodyFont": "inter",
"imports": "import { Mulish } from \"next/font/google\";\nimport { Inter } from \"next/font/google\";",
"initializations": "const mulish = Mulish({\n variable: \"--font-mulish\",\n subsets: [\"latin\"],\n});\n\nconst inter = Inter({\n variable: \"--font-inter\",\n subsets: [\"latin\"],\n});",
"classNames": "${mulish.variable} ${inter.variable}",
"globalsCss": {
"instructions": "Update the font-family property within the existing CSS rules in globals.css (@layer base section)",
"bodyRule": "body {\n /* ... existing properties ... */\n font-family: var(--font-inter), sans-serif;\n}",
"headingsRule": "h1, h2, h3, h4, h5, h6 {\n font-family: var(--font-mulish), sans-serif;\n}",
"bodyFontFamily": "var(--font-inter), sans-serif",
"headingsFontFamily": "var(--font-mulish), sans-serif"
}
},
"plusJakartaSansInter": {
"name": "Plus Jakarta Sans + Inter",
"description": "Friendly rounded headings with neutral body. Approachable and modern.",
"headingFont": "plusJakartaSans",
"bodyFont": "inter",
"imports": "import { Plus_Jakarta_Sans } from \"next/font/google\";\nimport { Inter } from \"next/font/google\";",
"initializations": "const plusJakartaSans = Plus_Jakarta_Sans({\n variable: \"--font-plus-jakarta-sans\",\n subsets: [\"latin\"],\n});\n\nconst inter = Inter({\n variable: \"--font-inter\",\n subsets: [\"latin\"],\n});",
"classNames": "${plusJakartaSans.variable} ${inter.variable}",
"globalsCss": {
"instructions": "Update the font-family property within the existing CSS rules in globals.css (@layer base section)",
"bodyRule": "body {\n /* ... existing properties ... */\n font-family: var(--font-inter), sans-serif;\n}",
"headingsRule": "h1, h2, h3, h4, h5, h6 {\n font-family: var(--font-plus-jakarta-sans), sans-serif;\n}",
"bodyFontFamily": "var(--font-inter), sans-serif",
"headingsFontFamily": "var(--font-plus-jakarta-sans), sans-serif"
}
},
"montserratInter": {
"name": "Montserrat + Inter",
"description": "Geometric sans-serif headings with neutral body. Popular and reliable.",
"headingFont": "montserrat",
"bodyFont": "inter",
"imports": "import { Montserrat } from \"next/font/google\";\nimport { Inter } from \"next/font/google\";",
"initializations": "const montserrat = Montserrat({\n variable: \"--font-montserrat\",\n subsets: [\"latin\"],\n});\n\nconst inter = Inter({\n variable: \"--font-inter\",\n subsets: [\"latin\"],\n});",
"classNames": "${montserrat.variable} ${inter.variable}",
"globalsCss": {
"instructions": "Update the font-family property within the existing CSS rules in globals.css (@layer base section)",
"bodyRule": "body {\n /* ... existing properties ... */\n font-family: var(--font-inter), sans-serif;\n}",
"headingsRule": "h1, h2, h3, h4, h5, h6 {\n font-family: var(--font-montserrat), sans-serif;\n}",
"bodyFontFamily": "var(--font-inter), sans-serif",
"headingsFontFamily": "var(--font-montserrat), sans-serif"
}
}
}
}

26
next.config.ts Normal file
View File

@@ -0,0 +1,26 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
devIndicators: false,
experimental: {
serverComponentsHmrCache: false,
},
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'webuild-dev.s3.eu-north-1.amazonaws.com',
},
{
protocol: 'https',
hostname: 'img.b2bpic.net',
},
{
protocol: 'https',
hostname: 'freepik.com',
},
],
}
};
export default nextConfig;

8299
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

46
package.json Normal file
View File

@@ -0,0 +1,46 @@
{
"name": "webild-components-2",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build --turbopack",
"typecheck": "tsc --noEmit",
"lint": "eslint . --ext .ts,.tsx",
"start": "next start"
},
"dependencies": {
"@gsap/react": "^2.1.2",
"@react-three/drei": "^10.7.7",
"@react-three/fiber": "^9.4.0",
"@tsparticles/engine": "^3.9.1",
"@tsparticles/react": "^3.0.0",
"@tsparticles/slim": "^3.9.1",
"clsx": "^2.1.1",
"cobe": "^0.6.5",
"embla-carousel-auto-scroll": "^8.6.0",
"embla-carousel-react": "^8.6.0",
"gsap": "^3.13.0",
"lenis": "^1.3.15",
"lucide-react": "^0.555.0",
"motion-number": "^1.0.0",
"next": "16.0.7",
"react": "19.2.1",
"react-dom": "19.2.1",
"react-fast-marquee": "^1.6.5",
"recharts": "^3.6.0",
"tailwind-merge": "^3.4.0",
"three": "^0.181.2"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "16.0.7",
"tailwindcss": "^4",
"typescript": "^5"
}
}

5
postcss.config.mjs Normal file
View File

@@ -0,0 +1,5 @@
const config = {
plugins: ["@tailwindcss/postcss"],
};
export default config;

BIN
public/audio/click.mp3 Normal file

Binary file not shown.

BIN
public/base/bg-texture.avif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

52
public/brand/logo-dot.svg Normal file
View File

@@ -0,0 +1,52 @@
<svg width="7" height="7" viewBox="0 0 7 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_f_1295_3221)">
<ellipse cx="3.59341" cy="3.53052" rx="1.8861" ry="1.90568" transform="rotate(25.4025 3.59341 3.53052)" fill="url(#paint0_linear_1295_3221)"/>
</g>
<g filter="url(#filter1_f_1295_3221)">
<circle cx="3.69632" cy="3.86088" r="1.65146" transform="rotate(25.4025 3.69632 3.86088)" fill="url(#paint1_linear_1295_3221)"/>
</g>
<g filter="url(#filter2_f_1295_3221)">
<circle cx="3.69633" cy="3.86069" r="1.65146" transform="rotate(-169.598 3.69633 3.86069)" fill="url(#paint2_linear_1295_3221)"/>
</g>
<g filter="url(#filter3_f_1295_3221)">
<circle cx="3.74882" cy="3.91343" r="1.65146" transform="rotate(-169.598 3.74882 3.91343)" fill="url(#paint3_linear_1295_3221)"/>
</g>
<defs>
<filter id="filter0_f_1295_3221" x="1.25185" y="1.17653" width="4.68307" height="4.70798" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0" result="effect1_foregroundBlur_1295_3221"/>
</filter>
<filter id="filter1_f_1295_3221" x="0.569126" y="0.733676" width="6.25433" height="6.25433" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0" result="effect1_foregroundBlur_1295_3221"/>
</filter>
<filter id="filter2_f_1295_3221" x="1.16377" y="1.3282" width="5.06515" height="5.06478" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.0330293" result="effect1_foregroundBlur_1295_3221"/>
</filter>
<filter id="filter3_f_1295_3221" x="0.687796" y="0.852469" width="6.12209" height="6.12172" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.704625" result="effect1_foregroundBlur_1295_3221"/>
</filter>
<linearGradient id="paint0_linear_1295_3221" x1="3.68116" y1="3.8564" x2="5.08951" y2="5.37639" gradientUnits="userSpaceOnUse">
<stop stop-color="#0F3DA6"/>
<stop offset="0.951923" stop-color="#3A9AFF" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint1_linear_1295_3221" x1="2.5674" y1="3.78948" x2="3.91229" y2="5.46656" gradientUnits="userSpaceOnUse">
<stop offset="0.00961538" stop-color="#0D50E8"/>
<stop offset="0.951923" stop-color="#3A9AFF" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint2_linear_1295_3221" x1="5.38038" y1="5.11694" x2="2.76523" y2="1.84712" gradientUnits="userSpaceOnUse">
<stop stop-color="#0F3DA6" stop-opacity="0"/>
<stop offset="1" stop-color="#59ABFF"/>
</linearGradient>
<linearGradient id="paint3_linear_1295_3221" x1="5.43287" y1="5.16968" x2="4.3403" y2="2.57182" gradientUnits="userSpaceOnUse">
<stop stop-color="#0F3DA6" stop-opacity="0"/>
<stop offset="1" stop-color="#59ABFF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

74
public/brand/logo.svg Normal file
View File

@@ -0,0 +1,74 @@
<svg width="67" height="21" viewBox="0 0 67 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M26.4375 7.16162C28.1869 7.16171 29.6159 7.78044 30.6064 8.88428C31.5956 9.98684 32.1387 11.5637 32.1387 13.4653V14.4478H23.374V14.4917C23.3742 15.5488 23.6921 16.4168 24.249 17.019C24.8052 17.6203 25.6093 17.9673 26.6025 17.9673C28.0159 17.9672 29.0384 17.2571 29.3633 16.228L29.3877 16.1509H32.0156L31.9961 16.2778C31.6314 18.6096 29.4248 20.2515 26.543 20.2515C24.6949 20.2514 23.2009 19.6255 22.1699 18.4937C21.1401 17.3628 20.5822 15.7381 20.582 13.7603C20.582 11.7937 21.1488 10.1435 22.168 8.98389C23.1888 7.82281 24.6569 7.16165 26.4375 7.16162ZM36.1025 9.28955C36.8971 7.97245 38.2815 7.18506 39.9678 7.18506C41.5623 7.18515 42.8859 7.81845 43.8086 8.95557C44.7294 10.0905 45.2441 11.7187 45.2441 13.7007C45.2441 15.6882 44.7324 17.3191 43.8115 18.4556C42.8887 19.5944 41.5621 20.2279 39.9561 20.228C38.2187 20.228 36.8448 19.4336 36.0312 18.1226V20.0151H33.334V2.77295H36.1025V9.28955ZM67 20.0151H64.3027V18.1284C63.5158 19.417 62.1356 20.228 60.4141 20.228C58.8134 20.228 57.4778 19.588 56.5449 18.4468C55.614 17.3077 55.0899 15.677 55.0898 13.7007C55.0898 11.7241 55.6138 10.0956 56.542 8.95947C57.4719 7.82125 58.8017 7.18506 60.3906 7.18506C62.0846 7.18514 63.4609 7.98063 64.2207 9.2251V2.77295H67V20.0151ZM2.99902 2.85791L6.0918 15.9497L9.62793 2.85498L9.64941 2.77295H12.2715L12.2939 2.85498L15.8398 15.9507L18.9336 2.85791L18.9541 2.77295H21.9336L21.8955 2.91162L17.2949 19.9341L17.2734 20.0151H14.6172L14.5938 19.9351L10.9609 7.26416L7.33887 19.9351L7.31641 20.0151H4.64746L4.62598 19.9341L0.0371094 2.91162L0 2.77295H2.97949L2.99902 2.85791ZM53.9062 20.0151H51.1377V2.77295H53.9062V20.0151ZM49.0352 19.9839H46.2666V7.354H49.0352V19.9839ZM60.9092 17.9536C60.9674 17.9566 61.0263 17.9585 61.0859 17.9585V17.9575L60.9092 17.9536ZM60.6924 17.9351C60.7503 17.9417 60.8088 17.947 60.8682 17.9507C60.8088 17.947 60.7503 17.9417 60.6924 17.9351ZM60.4434 17.8979C60.5109 17.911 60.5797 17.9212 60.6494 17.9302C60.5797 17.9212 60.5109 17.911 60.4434 17.8979ZM39.2715 9.55225C38.3397 9.55229 37.5483 9.96027 36.9873 10.6792C36.4249 11.4002 36.0908 12.4394 36.0908 13.7007C36.0909 14.9739 36.425 16.0131 36.9873 16.731C37.548 17.4465 38.3393 17.8491 39.2715 17.8491C40.2407 17.8491 41.0189 17.4568 41.5576 16.7495C42.0989 16.0387 42.4052 15 42.4053 13.7007C42.4053 12.4132 42.0991 11.3737 41.5576 10.6597C41.0186 9.94925 40.2402 9.5523 39.2715 9.55225ZM61.0869 9.55225C60.1117 9.55225 59.3237 9.94972 58.7773 10.6606C58.2287 11.3747 57.917 12.4136 57.917 13.7007C57.917 14.9937 58.2288 16.0322 58.7773 16.7446C59.3236 17.454 60.1115 17.8491 61.0869 17.8491C62.0312 17.849 62.8158 17.449 63.3672 16.7358C63.9205 16.0199 64.2441 14.9807 64.2441 13.7007C64.2441 12.4325 63.9207 11.3935 63.3672 10.6743C62.8155 9.95775 62.0308 9.55241 61.0869 9.55225ZM41.2676 17.2271C41.3209 17.1788 41.3736 17.1293 41.4238 17.0767L41.4307 17.0688C41.3782 17.1242 41.3235 17.1766 41.2676 17.2271ZM57.8643 14.6216C57.8776 14.7252 57.8932 14.8268 57.9111 14.9263C57.8933 14.8268 57.8775 14.7252 57.8643 14.6216ZM57.8066 13.7007C57.8067 14.0028 57.8244 14.2919 57.8574 14.5669C57.8424 14.4409 57.8305 14.312 57.8223 14.1802L57.8076 13.7007C57.8076 13.6621 57.809 13.6237 57.8096 13.5854C57.809 13.6237 57.8066 13.6621 57.8066 13.7007ZM45.1035 14.5063C45.1121 14.3932 45.1182 14.2786 45.123 14.1626C45.1182 14.2786 45.112 14.3932 45.1035 14.5063ZM45.1338 13.7007C45.1338 13.8433 45.1302 13.9839 45.125 14.1226C45.1257 14.1037 45.1283 14.0849 45.1289 14.0659L45.1348 13.7007C45.1348 13.5487 45.1312 13.399 45.125 13.2515L45.1338 13.7007ZM57.8242 13.2104C57.8213 13.2551 57.8185 13.3 57.8164 13.3452C57.8185 13.3 57.8213 13.2551 57.8242 13.2104ZM57.8555 12.8501C57.8514 12.8844 57.8483 12.9189 57.8447 12.9536C57.8483 12.9189 57.8514 12.8844 57.8555 12.8501ZM57.9346 12.3618C57.9223 12.423 57.909 12.4846 57.8984 12.5474C57.909 12.4846 57.9223 12.423 57.9346 12.3618ZM26.4375 9.43506C24.7618 9.43512 23.5679 10.68 23.3984 12.4468H29.3623C29.3129 11.5693 29.0132 10.8288 28.5244 10.3032C28.0155 9.75613 27.2989 9.43515 26.4375 9.43506ZM57.999 12.0737C57.9868 12.1214 57.975 12.1695 57.9639 12.2183C57.975 12.1695 57.9868 12.1214 57.999 12.0737ZM58.1367 11.6313C58.1073 11.7129 58.0784 11.7959 58.0527 11.8813C58.0784 11.7959 58.1073 11.7129 58.1367 11.6313ZM58.2197 11.4146C58.204 11.4519 58.1887 11.4896 58.1738 11.5278C58.1887 11.4896 58.204 11.4519 58.2197 11.4146ZM58.3633 11.1089C58.3476 11.1388 58.3324 11.1691 58.3174 11.1997C58.3324 11.1691 58.3476 11.1388 58.3633 11.1089ZM58.9629 10.2827C58.8665 10.3786 58.7757 10.4823 58.6904 10.5933L58.7998 10.4595C58.8524 10.3981 58.9065 10.3388 58.9629 10.2827ZM59.5752 9.81885C59.3611 9.93932 59.164 10.0873 58.9854 10.2612C59.0426 10.2054 59.1021 10.1525 59.1631 10.1021C59.2493 10.0308 59.3391 9.96501 59.4326 9.90479C59.4793 9.87472 59.5268 9.84615 59.5752 9.81885ZM26.2725 9.32861C26.327 9.326 26.382 9.32471 26.4375 9.32471L26.5312 9.32666C26.5002 9.32581 26.4689 9.32373 26.4375 9.32373C26.382 9.32373 26.3269 9.32601 26.2725 9.32861Z" fill="black"/>
<mask id="mask0_1119_6721" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="2" width="67" height="19">
<path d="M26.4375 7.16162C28.1869 7.16171 29.6159 7.78044 30.6064 8.88428C31.5956 9.98684 32.1387 11.5637 32.1387 13.4653V14.4478H23.374V14.4917C23.3742 15.5488 23.6921 16.4168 24.249 17.019C24.8052 17.6203 25.6093 17.9673 26.6025 17.9673C28.0159 17.9672 29.0384 17.2571 29.3633 16.228L29.3877 16.1509H32.0156L31.9961 16.2778C31.6314 18.6096 29.4248 20.2515 26.543 20.2515C24.6949 20.2514 23.2009 19.6255 22.1699 18.4937C21.1401 17.3628 20.5822 15.7381 20.582 13.7603C20.582 11.7937 21.1488 10.1435 22.168 8.98389C23.1888 7.82281 24.6569 7.16165 26.4375 7.16162ZM36.1025 9.28955C36.8971 7.97245 38.2815 7.18506 39.9678 7.18506C41.5623 7.18515 42.8859 7.81845 43.8086 8.95557C44.7294 10.0905 45.2441 11.7187 45.2441 13.7007C45.2441 15.6882 44.7324 17.3191 43.8115 18.4556C42.8887 19.5944 41.5621 20.2279 39.9561 20.228C38.2187 20.228 36.8448 19.4336 36.0312 18.1226V20.0151H33.334V2.77295H36.1025V9.28955ZM67 20.0151H64.3027V18.1284C63.5158 19.417 62.1356 20.228 60.4141 20.228C58.8134 20.228 57.4778 19.588 56.5449 18.4468C55.614 17.3077 55.0899 15.677 55.0898 13.7007C55.0898 11.7241 55.6138 10.0956 56.542 8.95947C57.4719 7.82125 58.8017 7.18506 60.3906 7.18506C62.0846 7.18514 63.4609 7.98063 64.2207 9.2251V2.77295H67V20.0151ZM2.99902 2.85791L6.0918 15.9497L9.62793 2.85498L9.64941 2.77295H12.2715L12.2939 2.85498L15.8398 15.9507L18.9336 2.85791L18.9541 2.77295H21.9336L21.8955 2.91162L17.2949 19.9341L17.2734 20.0151H14.6172L14.5938 19.9351L10.9609 7.26416L7.33887 19.9351L7.31641 20.0151H4.64746L4.62598 19.9341L0.0371094 2.91162L0 2.77295H2.97949L2.99902 2.85791ZM53.9062 20.0151H51.1377V2.77295H53.9062V20.0151ZM49.0352 19.9839H46.2666V7.354H49.0352V19.9839ZM60.9092 17.9536C60.9674 17.9566 61.0263 17.9585 61.0859 17.9585V17.9575L60.9092 17.9536ZM60.6924 17.9351C60.7503 17.9417 60.8088 17.947 60.8682 17.9507C60.8088 17.947 60.7503 17.9417 60.6924 17.9351ZM60.4434 17.8979C60.5109 17.911 60.5797 17.9212 60.6494 17.9302C60.5797 17.9212 60.5109 17.911 60.4434 17.8979ZM39.2715 9.55225C38.3397 9.55229 37.5483 9.96027 36.9873 10.6792C36.4249 11.4002 36.0908 12.4394 36.0908 13.7007C36.0909 14.9739 36.425 16.0131 36.9873 16.731C37.548 17.4465 38.3393 17.8491 39.2715 17.8491C40.2407 17.8491 41.0189 17.4568 41.5576 16.7495C42.0989 16.0387 42.4052 15 42.4053 13.7007C42.4053 12.4132 42.0991 11.3737 41.5576 10.6597C41.0186 9.94925 40.2402 9.5523 39.2715 9.55225ZM61.0869 9.55225C60.1117 9.55225 59.3237 9.94972 58.7773 10.6606C58.2287 11.3747 57.917 12.4136 57.917 13.7007C57.917 14.9937 58.2288 16.0322 58.7773 16.7446C59.3236 17.454 60.1115 17.8491 61.0869 17.8491C62.0312 17.849 62.8158 17.449 63.3672 16.7358C63.9205 16.0199 64.2441 14.9807 64.2441 13.7007C64.2441 12.4325 63.9207 11.3935 63.3672 10.6743C62.8155 9.95775 62.0308 9.55241 61.0869 9.55225ZM41.2676 17.2271C41.3209 17.1788 41.3736 17.1293 41.4238 17.0767L41.4307 17.0688C41.3782 17.1242 41.3235 17.1766 41.2676 17.2271ZM57.8643 14.6216C57.8776 14.7252 57.8932 14.8268 57.9111 14.9263C57.8933 14.8268 57.8775 14.7252 57.8643 14.6216ZM57.8066 13.7007C57.8067 14.0028 57.8244 14.2919 57.8574 14.5669C57.8424 14.4409 57.8305 14.312 57.8223 14.1802L57.8076 13.7007C57.8076 13.6621 57.809 13.6237 57.8096 13.5854C57.809 13.6237 57.8066 13.6621 57.8066 13.7007ZM45.1035 14.5063C45.1121 14.3932 45.1182 14.2786 45.123 14.1626C45.1182 14.2786 45.112 14.3932 45.1035 14.5063ZM45.1338 13.7007C45.1338 13.8433 45.1302 13.9839 45.125 14.1226C45.1257 14.1037 45.1283 14.0849 45.1289 14.0659L45.1348 13.7007C45.1348 13.5487 45.1312 13.399 45.125 13.2515L45.1338 13.7007ZM57.8242 13.2104C57.8213 13.2551 57.8185 13.3 57.8164 13.3452C57.8185 13.3 57.8213 13.2551 57.8242 13.2104ZM57.8555 12.8501C57.8514 12.8844 57.8483 12.9189 57.8447 12.9536C57.8483 12.9189 57.8514 12.8844 57.8555 12.8501ZM57.9346 12.3618C57.9223 12.423 57.909 12.4846 57.8984 12.5474C57.909 12.4846 57.9223 12.423 57.9346 12.3618ZM26.4375 9.43506C24.7618 9.43512 23.5679 10.68 23.3984 12.4468H29.3623C29.3129 11.5693 29.0132 10.8288 28.5244 10.3032C28.0155 9.75613 27.2989 9.43515 26.4375 9.43506ZM57.999 12.0737C57.9868 12.1214 57.975 12.1695 57.9639 12.2183C57.975 12.1695 57.9868 12.1214 57.999 12.0737ZM58.1367 11.6313C58.1073 11.7129 58.0784 11.7959 58.0527 11.8813C58.0784 11.7959 58.1073 11.7129 58.1367 11.6313ZM58.2197 11.4146C58.204 11.4519 58.1887 11.4896 58.1738 11.5278C58.1887 11.4896 58.204 11.4519 58.2197 11.4146ZM58.3633 11.1089C58.3476 11.1388 58.3324 11.1691 58.3174 11.1997C58.3324 11.1691 58.3476 11.1388 58.3633 11.1089ZM58.9629 10.2827C58.8665 10.3786 58.7757 10.4823 58.6904 10.5933L58.7998 10.4595C58.8524 10.3981 58.9065 10.3388 58.9629 10.2827ZM59.5752 9.81885C59.3611 9.93932 59.164 10.0873 58.9854 10.2612C59.0426 10.2054 59.1021 10.1525 59.1631 10.1021C59.2493 10.0308 59.3391 9.96501 59.4326 9.90479C59.4793 9.87472 59.5268 9.84615 59.5752 9.81885ZM26.2725 9.32861C26.327 9.326 26.382 9.32471 26.4375 9.32471L26.5312 9.32666C26.5002 9.32581 26.4689 9.32373 26.4375 9.32373C26.382 9.32373 26.3269 9.32601 26.2725 9.32861Z" fill="black"/>
</mask>
<g mask="url(#mask0_1119_6721)">
<g opacity="0.17" filter="url(#filter0_f_1119_6721)">
<path d="M36.1377 2.6198H32.5596L42.4684 -6.4082L54.7993 -5.08703L62.8915 -1.34371L55.57 3.39048C54.469 3.18864 52.1459 2.90606 51.6615 3.39048C51.056 3.99602 51.056 5.64749 50.8908 6.91361C50.7587 7.92651 49.8082 7.84944 49.3495 7.68429L46.4319 8.12468L45.5511 12.4185C45.3125 12.2533 44.6813 11.5707 44.0648 10.1615C43.2941 8.39993 42.3032 7.84944 40.7068 7.68429C39.4297 7.55217 36.78 8.47332 36.1377 8.78527V2.6198Z" fill="#0597FF"/>
</g>
<g filter="url(#filter1_f_1119_6721)">
<path d="M36.1377 2.6198H32.5596L42.4684 -6.4082L54.7993 -5.08703L62.8915 -1.34371L55.57 3.39048C54.469 3.18864 52.1459 2.90606 51.6615 3.39048C51.056 3.99602 51.056 5.64749 50.8908 6.91361C50.7587 7.92651 49.8082 7.84944 49.3495 7.68429L46.4319 8.12468L45.5511 12.4185C45.3125 12.2533 44.6813 11.5707 44.0648 10.1615C43.2941 8.39993 42.3032 7.84944 40.7068 7.68429C39.4297 7.55217 36.78 8.47332 36.1377 8.78527V2.6198Z" fill="#0597FF"/>
</g>
</g>
<g filter="url(#filter2_f_1119_6721)">
<ellipse cx="47.5933" cy="3.27857" rx="1.8861" ry="1.90568" transform="rotate(25.4025 47.5933 3.27857)" fill="url(#paint0_linear_1119_6721)"/>
</g>
<g filter="url(#filter3_f_1119_6721)">
<circle cx="47.6964" cy="3.60892" r="1.65146" transform="rotate(25.4025 47.6964 3.60892)" fill="url(#paint1_linear_1119_6721)"/>
</g>
<g filter="url(#filter4_f_1119_6721)">
<circle cx="47.6963" cy="3.60874" r="1.65146" transform="rotate(-169.598 47.6963 3.60874)" fill="url(#paint2_linear_1119_6721)"/>
</g>
<g filter="url(#filter5_f_1119_6721)">
<circle cx="47.7491" cy="3.66147" r="1.65146" transform="rotate(-169.598 47.7491 3.66147)" fill="url(#paint3_linear_1119_6721)"/>
</g>
<defs>
<filter id="filter0_f_1119_6721" x="31.2494" y="-7.71836" width="32.9524" height="21.447" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.655081" result="effect1_foregroundBlur_1119_6721"/>
</filter>
<filter id="filter1_f_1119_6721" x="27.1648" y="-11.803" width="41.1216" height="29.6162" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="2.69739" result="effect1_foregroundBlur_1119_6721"/>
</filter>
<filter id="filter2_f_1119_6721" x="45.2517" y="0.924576" width="4.68307" height="4.70798" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0" result="effect1_foregroundBlur_1119_6721"/>
</filter>
<filter id="filter3_f_1119_6721" x="44.5691" y="0.481723" width="6.25433" height="6.25433" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0" result="effect1_foregroundBlur_1119_6721"/>
</filter>
<filter id="filter4_f_1119_6721" x="45.1637" y="1.07625" width="5.06527" height="5.06478" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.0330293" result="effect1_foregroundBlur_1119_6721"/>
</filter>
<filter id="filter5_f_1119_6721" x="44.6879" y="0.600516" width="6.12221" height="6.12172" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="0.704625" result="effect1_foregroundBlur_1119_6721"/>
</filter>
<linearGradient id="paint0_linear_1119_6721" x1="47.681" y1="3.60445" x2="49.0894" y2="5.12444" gradientUnits="userSpaceOnUse">
<stop stop-color="#0F3DA6"/>
<stop offset="0.951923" stop-color="#3A9AFF" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint1_linear_1119_6721" x1="46.5675" y1="3.53753" x2="47.9124" y2="5.21461" gradientUnits="userSpaceOnUse">
<stop offset="0.00961538" stop-color="#0D50E8"/>
<stop offset="0.951923" stop-color="#3A9AFF" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint2_linear_1119_6721" x1="49.3804" y1="4.86499" x2="46.7652" y2="1.59517" gradientUnits="userSpaceOnUse">
<stop stop-color="#0F3DA6" stop-opacity="0"/>
<stop offset="1" stop-color="#59ABFF"/>
</linearGradient>
<linearGradient id="paint3_linear_1119_6721" x1="49.4331" y1="4.91773" x2="48.3405" y2="2.31986" gradientUnits="userSpaceOnUse">
<stop stop-color="#0F3DA6" stop-opacity="0"/>
<stop offset="1" stop-color="#59ABFF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,58 @@
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 67 21" width="67" height="21">
<defs>
<clipPath clipPathUnits="userSpaceOnUse" id="cp1">
<path d="m26.44 7.16c1.75 0 3.18 0.62 4.17 1.72 0.99 1.11 1.53 2.68 1.53 4.59v0.98h-8.77v0.04c0 1.06 0.32 1.93 0.88 2.53 0.56 0.6 1.36 0.95 2.35 0.95 1.42 0 2.44-0.71 2.76-1.74l0.03-0.08h2.63l-0.02 0.13c-0.37 2.33-2.58 3.97-5.46 3.97-1.85 0-3.34-0.62-4.37-1.76-1.03-1.13-1.59-2.75-1.59-4.73 0-1.97 0.57-3.62 1.59-4.78 1.02-1.16 2.49-1.82 4.27-1.82zm9.66 2.13c0.8-1.32 2.18-2.1 3.87-2.1 1.59 0 2.92 0.63 3.84 1.77 0.92 1.13 1.43 2.76 1.43 4.74 0 1.99-0.51 3.62-1.43 4.76-0.92 1.13-2.25 1.77-3.85 1.77-1.74 0-3.12-0.8-3.93-2.11v1.9h-2.7v-17.25h2.77zm30.9 10.73h-2.7v-1.89c-0.78 1.29-2.16 2.1-3.89 2.1-1.6 0-2.93-0.64-3.87-1.78-0.93-1.14-1.45-2.77-1.45-4.75 0-1.97 0.52-3.6 1.45-4.74 0.93-1.14 2.26-1.77 3.85-1.77 1.69 0 3.07 0.79 3.83 2.04v-6.45h2.78zm-64-17.16l3.09 13.09 3.54-13.09 0.02-0.09h2.62l0.02 0.09 3.55 13.09 3.09-13.09 0.02-0.09h2.98l-0.03 0.14-4.61 17.03-0.02 0.08h-2.65l-0.03-0.08-3.63-12.67-3.62 12.67-0.02 0.08h-2.67l-0.02-0.08-4.59-17.03-0.04-0.14h2.98zm50.91 17.16h-2.77v-17.24h2.77zm-4.87-0.03h-2.77v-12.63h2.77zm11.87-2.03q0.09 0 0.18 0zm-21.64-8.4c-0.93 0-1.72 0.41-2.29 1.13-0.56 0.72-0.89 1.76-0.89 3.02 0 1.27 0.33 2.31 0.89 3.03 0.57 0.71 1.36 1.12 2.29 1.12 0.97 0 1.75-0.4 2.28-1.1 0.55-0.71 0.85-1.75 0.85-3.05 0-1.29-0.3-2.33-0.85-3.04-0.53-0.71-1.31-1.11-2.28-1.11zm21.81 0c-0.97 0-1.76 0.4-2.31 1.11-0.54 0.71-0.86 1.75-0.86 3.04 0 1.29 0.32 2.33 0.86 3.04 0.55 0.71 1.34 1.11 2.31 1.11 0.95 0 1.73-0.4 2.28-1.12 0.56-0.71 0.88-1.75 0.88-3.03 0-1.27-0.32-2.31-0.88-3.03-0.55-0.71-1.33-1.12-2.28-1.12zm-19.79 7.65q-0.01 0.01-0.03 0.03 0.02-0.02 0.03-0.03zm0.13-0.13h0.01q-0.07 0.07-0.14 0.13 0.07-0.06 0.13-0.13zm16.38-3.37q0 0.45 0.05 0.87-0.02-0.19-0.03-0.39l-0.02-0.48q0.01-0.06 0.01-0.12-0.01 0.06-0.01 0.12zm-12.67 0q0 0.04 0 0.09v-0.09q0-0.23-0.01-0.45zm0 0.36v-0.15q0 0.11-0.01 0.21 0.01-0.03 0.01-0.06zm0-0.15q0-0.06 0-0.12zm-18.69-4.47c-1.68 0-2.87 1.24-3.04 3.01h5.96c-0.05-0.88-0.35-1.62-0.84-2.15-0.5-0.54-1.22-0.86-2.08-0.86zm32.25 1.15l0.11-0.13q0.08-0.09 0.16-0.17-0.14 0.14-0.27 0.3zm0.89-0.77q-0.31 0.17-0.56 0.41 0.07-0.07 0.14-0.13 0.13-0.1 0.27-0.19 0.07-0.05 0.15-0.09zm-0.56 0.41q-0.02 0.02-0.03 0.03 0.01-0.01 0.03-0.03zm-32.75-0.9q0 0 0 0 0 0 0 0zm0.17 0h0.09q-0.05 0-0.09-0.01-0.09 0.01-0.17 0.01 0.08 0 0.17 0zm34.25 8.61q0.09 0.01 0.18 0.01-0.09 0-0.18-0.01zm-0.25-0.04q0.11 0.02 0.21 0.03-0.1-0.01-0.21-0.03zm-2.58-3.28q0.02 0.16 0.05 0.31-0.03-0.15-0.05-0.31zm-12.76-0.11q0.02-0.17 0.02-0.35 0 0.18-0.02 0.35zm12.72-1.3q0 0.07 0 0.14 0-0.07 0-0.14zm0.04-0.36q-0.01 0.05-0.02 0.1 0.01-0.05 0.02-0.1zm0.07-0.49q-0.01 0.09-0.03 0.19 0.02-0.1 0.03-0.19zm0.07-0.29q-0.02 0.08-0.04 0.15 0.02-0.07 0.04-0.15zm0.14-0.44q-0.05 0.12-0.09 0.25 0.04-0.13 0.09-0.25zm0.08-0.21q-0.02 0.05-0.05 0.11 0.03-0.06 0.05-0.11zm0.14-0.31q-0.02 0.04-0.04 0.09 0.02-0.05 0.04-0.09z"/>
</clipPath>
<filter x="-50%" y="-50%" width="200%" height="200%" id="f1"> <feGaussianBlur stdDeviation=".7"/> </filter>
<filter x="-50%" y="-50%" width="200%" height="200%" id="f2"> <feGaussianBlur stdDeviation="2.7"/> </filter>
<linearGradient id="g1" x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(.62,1.977,-1.976,.62,47.533,3.611)">
<stop offset="0" stop-color="#0f3da6" stop-opacity="1"/>
<stop offset=".952" stop-color="#3a9aff" stop-opacity="0"/>
</linearGradient>
<linearGradient id="g2" x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(.495,2.092,-2.092,.495,46.707,3.06)">
<stop offset=".01" stop-color="#0d50e8" stop-opacity="1"/>
<stop offset=".952" stop-color="#3a9aff" stop-opacity="0"/>
</linearGradient>
<filter x="-50%" y="-50%" width="200%" height="200%" id="f3"> <feGaussianBlur stdDeviation="0"/> </filter>
<linearGradient id="g3" x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.982,3.688,-3.688,1.982,46.267,2.069)">
<stop offset="0" stop-color="#0f3da6" stop-opacity="0"/>
<stop offset="1" stop-color="#59abff" stop-opacity="1"/>
</linearGradient>
<linearGradient id="g4" x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(.606,2.752,-2.752,.606,46.32,2.122)">
<stop offset="0" stop-color="#0f3da6" stop-opacity="0"/>
<stop offset="1" stop-color="#59abff" stop-opacity="1"/>
</linearGradient>
</defs>
<style>
.s0 { fill: #ffffff }
.s1 { filter: url(#f1);fill: #0597ff }
.s2 { filter: url(#f2);fill: #0597ff }
.s3 { fill: url(#g1) }
.s4 { fill: url(#g2) }
.s5 { filter: url(#f3);fill: url(#g3) }
.s6 { filter: url(#f1);fill: url(#g4) }
</style>
<path class="s0" d="m26.44 7.16c1.75 0 3.18 0.62 4.17 1.72 0.99 1.11 1.53 2.68 1.53 4.59v0.98h-8.77v0.04c0 1.06 0.32 1.93 0.88 2.53 0.56 0.6 1.36 0.95 2.35 0.95 1.42 0 2.44-0.71 2.76-1.74l0.03-0.08h2.63l-0.02 0.13c-0.37 2.33-2.58 3.97-5.46 3.97-1.85 0-3.34-0.62-4.37-1.76-1.03-1.13-1.59-2.75-1.59-4.73 0-1.97 0.57-3.62 1.59-4.78 1.02-1.16 2.49-1.82 4.27-1.82zm9.66 2.13c0.8-1.32 2.18-2.1 3.87-2.1 1.59 0 2.92 0.63 3.84 1.77 0.92 1.13 1.43 2.76 1.43 4.74 0 1.99-0.51 3.62-1.43 4.76-0.92 1.13-2.25 1.77-3.85 1.77-1.74 0-3.12-0.8-3.93-2.11v1.9h-2.7v-17.25h2.77zm30.9 10.73h-2.7v-1.89c-0.78 1.29-2.16 2.1-3.89 2.1-1.6 0-2.93-0.64-3.87-1.78-0.93-1.14-1.45-2.77-1.45-4.75 0-1.97 0.52-3.6 1.45-4.74 0.93-1.14 2.26-1.77 3.85-1.77 1.69 0 3.07 0.79 3.83 2.04v-6.45h2.78zm-64-17.16l3.09 13.09 3.54-13.09 0.02-0.09h2.62l0.02 0.09 3.55 13.09 3.09-13.09 0.02-0.09h2.98l-0.03 0.14-4.61 17.03-0.02 0.08h-2.65l-0.03-0.08-3.63-12.67-3.62 12.67-0.02 0.08h-2.67l-0.02-0.08-4.59-17.03-0.04-0.14h2.98zm50.91 17.16h-2.77v-17.24h2.77zm-4.87-0.03h-2.77v-12.63h2.77zm11.87-2.03q0.09 0 0.18 0zm-0.22-0.02q0.09 0.01 0.18 0.02-0.09-0.01-0.18-0.02zm-0.25-0.03q0.1 0.02 0.21 0.03-0.11-0.01-0.21-0.03zm-21.17-8.35c-0.93 0-1.72 0.41-2.29 1.13-0.56 0.72-0.89 1.76-0.89 3.02 0 1.27 0.33 2.31 0.89 3.03 0.57 0.71 1.36 1.12 2.29 1.12 0.97 0 1.75-0.4 2.28-1.1 0.55-0.71 0.85-1.75 0.85-3.05 0-1.29-0.3-2.33-0.85-3.04-0.53-0.71-1.31-1.11-2.28-1.11zm21.81 0c-0.97 0-1.76 0.4-2.31 1.11-0.54 0.71-0.86 1.75-0.86 3.04 0 1.29 0.32 2.33 0.86 3.04 0.55 0.71 1.34 1.11 2.31 1.11 0.95 0 1.73-0.4 2.28-1.12 0.56-0.71 0.88-1.75 0.88-3.03 0-1.27-0.32-2.31-0.88-3.03-0.55-0.71-1.33-1.12-2.28-1.12zm-19.82 7.68q0.09-0.08 0.16-0.16h0.01q-0.08 0.08-0.17 0.16zm16.6-2.61q0.02 0.16 0.05 0.3-0.03-0.14-0.05-0.3zm-0.06-0.92q0 0.45 0.05 0.87-0.02-0.19-0.03-0.39l-0.02-0.48q0.01-0.06 0.01-0.12-0.01 0.06-0.01 0.12zm-12.7 0.8q0.01-0.17 0.02-0.34-0.01 0.17-0.02 0.34zm0.03-0.8q0 0.21-0.01 0.42 0-0.03 0.01-0.06v-0.36q0-0.23-0.01-0.45zm12.69-0.49q0 0.07-0.01 0.13 0.01-0.06 0.01-0.13zm0.03-0.36q0 0.05-0.01 0.1 0.01-0.05 0.01-0.1zm0.08-0.49q-0.02 0.09-0.03 0.19 0.01-0.1 0.03-0.19zm-31.49-2.93c-1.68 0-2.87 1.25-3.04 3.02h5.96c-0.05-0.88-0.35-1.62-0.84-2.15-0.51-0.54-1.22-0.87-2.08-0.87zm31.56 2.64q-0.02 0.07-0.04 0.15 0.02-0.08 0.04-0.15zm0.14-0.44q-0.05 0.12-0.09 0.25 0.04-0.13 0.09-0.25zm0.08-0.22q-0.03 0.06-0.05 0.12 0.02-0.06 0.05-0.12zm0.14-0.3q-0.02 0.04-0.04 0.09 0.02-0.05 0.04-0.09zm0.6-0.83q-0.14 0.15-0.27 0.31l0.11-0.13q0.08-0.09 0.16-0.18zm0.61-0.46q-0.32 0.18-0.59 0.44 0.09-0.08 0.18-0.16 0.13-0.11 0.27-0.2 0.07-0.04 0.14-0.08zm-33.3-0.49q0.08-0.01 0.17-0.01l0.09 0.01q-0.05-0.01-0.09-0.01-0.09 0-0.17 0.01z"/>
<g id="Clip-Path" clip-path="url(#cp1)">
<g>
<g style="opacity: .17">
<path class="s1" d="m36.14 2.62h-3.58l9.91-9.03 12.33 1.32 8.09 3.75-7.32 4.73c-1.1-0.2-3.42-0.48-3.91 0-0.6 0.61-0.6 2.26-0.77 3.52-0.13 1.02-1.08 0.94-1.54 0.77l-2.92 0.44-0.88 4.3c-0.24-0.17-0.87-0.85-1.49-2.26-0.77-1.76-1.76-2.31-3.35-2.48-1.28-0.13-3.93 0.79-4.57 1.11z"/>
</g>
<g>
<path class="s2" d="m36.14 2.62h-3.58l9.91-9.03 12.33 1.32 8.09 3.75-7.32 4.73c-1.1-0.2-3.42-0.48-3.91 0-0.6 0.61-0.6 2.26-0.77 3.52-0.13 1.02-1.08 0.94-1.54 0.77l-2.92 0.44-0.88 4.3c-0.24-0.17-0.87-0.85-1.49-2.26-0.77-1.76-1.76-2.31-3.35-2.48-1.28-0.13-3.93 0.79-4.57 1.11z"/>
</g>
</g>
</g>
<g>
<path fill-rule="evenodd" class="s3" d="m46.78 5c-0.95-0.45-1.34-1.58-0.89-2.53 0.45-0.95 1.58-1.36 2.52-0.91 0.94 0.44 1.34 1.58 0.89 2.53-0.46 0.95-1.58 1.36-2.52 0.91z"/>
</g>
<g>
<path fill-rule="evenodd" class="s4" d="m46.99 5.1c-0.83-0.39-1.18-1.37-0.79-2.2 0.4-0.82 1.38-1.17 2.2-0.78 0.83 0.39 1.18 1.37 0.79 2.2-0.39 0.82-1.38 1.17-2.2 0.78z"/>
</g>
<g>
<path fill-rule="evenodd" class="s5" d="m47.99 1.98c0.9 0.17 1.5 1.03 1.33 1.93-0.16 0.9-1.02 1.49-1.92 1.32-0.9-0.16-1.49-1.02-1.33-1.92 0.17-0.9 1.03-1.49 1.92-1.33z"/>
</g>
<g>
<path fill-rule="evenodd" class="s6" d="m48.05 2.04c0.9 0.16 1.49 1.02 1.32 1.92-0.16 0.9-1.02 1.49-1.92 1.33-0.9-0.17-1.49-1.03-1.33-1.93 0.17-0.89 1.03-1.49 1.93-1.32z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
public/images/noise.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

10676
registry.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
{
"name": "AboutMetric",
"description": "About section with centered animated title and metric cards in a responsive grid.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "At Berco Inc. we redefine innovation by empowering businesses to reach their full potential",
"minChars": 20,
"maxChars": 300
}
},
"metricRules": {
"minMetrics": 2,
"maxMetrics": 4,
"structure": {
"icon": "LucideIcon - Icon component from lucide-react (required)",
"label": "string - Descriptive label for the metric (required, e.g., 'Conversions', 'Partnered Brands')",
"value": "string - Metric value to display (required, e.g., '7,000+', '2018', '30+', '100M+')"
},
"note": "Provide 2-4 metrics for optimal layout. Grid automatically adjusts columns based on metric count (2 metrics = 2 cols, 3 metrics = 3 cols, 4 metrics = 4 cols). Import icons from lucide-react."
}
},
"propsSchema": {
"title": "string",
"metrics": "Array<{ icon: LucideIcon, label: string, value: string }>",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"ariaLabel?": "string (default: 'About metrics section')",
"className?": "string"
},
"usageExample": "// Wrap in ThemeProvider\nimport { TrendingUp, ShoppingCart, Users, Globe } from 'lucide-react';\n\n<ThemeProvider defaultButtonVariant=\"icon-arrow\" defaultTextAnimation=\"reveal-blur\" borderRadius=\"soft\" background=\"aurora\" cardStyle=\"glass-elevated\" primaryButtonStyle=\"gradient\" secondaryButtonStyle=\"glass\">\n <AboutMetric \n title=\"At Berco Inc. we redefine innovation by empowering businesses to reach their full potential\" \n useInvertedBackground={\"noInvert\"}\n metrics={[\n { icon: TrendingUp, label: 'Conversions', value: '7,000+' },\n { icon: ShoppingCart, label: 'Ecommerce Since', value: '2018' },\n { icon: Users, label: 'Partnered Brands', value: '30+' },\n { icon: Globe, label: 'Global Impressions Generated Annually', value: '100M+' }\n ]} \n />\n</ThemeProvider>",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Use for about pages",
"Use for company information",
"Use for statistics displays",
"Use for achievement showcases",
"Requires metrics[]"
],
"dont": [
"Do not use more than 4 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,21 @@
{
"name": "AnimatedAuroraBackground",
"description": "Aurora borealis effect with animated repeating gradients and mix-blend-difference.",
"constraints": {},
"propsSchema": {
"className?": "string",
"showRadialGradient?": "boolean (default: true)",
"invertColors": "boolean (REQUIRED - true for light backgrounds, false for dark backgrounds)"
},
"usageExample": "<AnimatedAuroraBackground invertColors={true} showRadialGradient={true} />",
"do": [
"Use for feature showcases",
"Use for capability displays"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,24 @@
{
"name": "AnimatedGridBackground",
"description": "Grid pattern with animated pulsing squares using Framer Motion.",
"constraints": {},
"propsSchema": {
"squareSize?": "number (default: 100)",
"numSquares?": "number (default: 50)",
"maxOpacity?": "number (default: 0.15)",
"className?": "string"
},
"usageExample": "<AnimatedGridBackground squareSize={100} numSquares={50} maxOpacity={0.15} />",
"do": [
"Use for feature showcases",
"Use for capability displays"
],
"dont": [
"Do not use more than 4 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,20 @@
{
"name": "AuroraBackground",
"description": "Aurora borealis-style background with multiple rotated gradient bars and blur effect.",
"constraints": {},
"propsSchema": {
"className?": "string"
},
"usageExample": "<AuroraBackground />",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,33 @@
{
"name": "AvatarGroup",
"description": "Displays a group of user avatars with overlapping layout and optional text label.",
"constraints": {
"textRules": {
"text": {
"required": false,
"example": "Join 1,000+ members",
"minChars": 2,
"maxChars": 50
}
}
},
"propsSchema": {
"avatars": "Array<{ src: string, alt: string }> - User avatar images",
"text?": "string",
"maxVisible?": "number (default: 5)",
"className?": "string",
"ariaLabel?": "string (default: 'User avatars')"
},
"usageExample": "<AvatarGroup avatars={[{ src: '/avatar1.jpg', alt: 'User 1' }, { src: '/avatar2.jpg', alt: 'User 2' }]} text=\"Join 1,000+ members\" />",
"do": [
"Use for social proof",
"Use for customer reviews",
"Requires avatars[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,27 @@
{
"name": "BentoGlobe",
"description": "Interactive 3D rotating globe component using COBE library with theme-aware colors and customizable markers.",
"constraints": {
"globeRules": {
"config": {
"required": false,
"note": "Optional COBEOptions object to customize globe appearance. Default config uses theme colors: baseColor and glowColor use --card, markerColor uses --primary-cta. Can override: phi (rotation), theta (tilt), dark (darkness 0-1), diffuse (lighting), mapSamples, mapBrightness, markers (array of {location: [lat, lng], size: number}), and more. See COBE documentation for full options."
}
}
},
"propsSchema": {
"className?": "string",
"config?": "COBEOptions - Custom globe configuration (see COBE docs)"
},
"usageExample": "<Globe className=\"w-full h-full\" config={{ markers: [{ location: [40.7128, -74.006], size: 0.1 }] }} />",
"do": [
"Use for feature showcases",
"Use for capability displays"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,64 @@
{
"name": "BlogCardOne",
"description": "Blog section with card grid/carousel layout featuring image, category, title, excerpt, and author info.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Latest Articles",
"minChars": 2,
"maxChars": 50
},
"description": {
"required": true,
"example": "Insights and updates from our team",
"minChars": 5,
"maxChars": 250
},
"tag": {
"required": false,
"example": "Blog",
"minChars": 2,
"maxChars": 30
}
},
"blogRules": {
"blogs": {
"required": true,
"minItems": 1,
"example": "[{\"id\": \"1\", \"category\": \"Design\", \"title\": \"UX review presentations\", \"excerpt\": \"How to create compelling presentations\", \"imageSrc\": \"/blog-1.jpg\", \"authorName\": \"John Doe\", \"authorAvatar\": \"/avatar-1.jpg\", \"date\": \"20 Jan 2025\"}]",
"note": "Array of blog items. Each item requires id, category, title, excerpt, imageSrc, authorName, authorAvatar, and date."
}
}
},
"propsSchema": {
"blogs": "Array<{ id: string, category: string, title: string, excerpt: string, imageSrc: string, imageAlt?: string, authorName: string, authorAvatar: string, date: string, onBlogClick?: () => void }> - Blog card items",
"carouselMode?": "'auto' | 'buttons' (default: 'buttons')",
"uniformGridCustomHeightClasses?": "string",
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' (required - controls GSAP scroll animations with stagger effect)",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"ariaLabel?": "string (default: 'Blog section')",
"className?": "string"
},
"usageExample": "<BlogCardOne blogs={[{id: '1', category: 'Design', title: 'UX review presentations', excerpt: 'How to create compelling presentations that wow your audience', imageSrc: '/blog-1.jpg', authorName: 'Olivia Rhye', authorAvatar: '/avatar-1.jpg', date: '20 Jan 2025', onBlogClick: () => console.log('clicked')}]} title=\"Latest Articles\" description=\"Stay updated with our latest insights\" textboxLayout=\"default\" useInvertedBackground={\"noInvert\"} animationType=\"slide-up\" carouselMode=\"buttons\" />",
"do": [
"Use for blog listings",
"Use for article grids",
"Requires blogs[]",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,67 @@
{
"name": "BlogCardThree",
"description": "Blog section with vertical card layout featuring tag, title, description, and media with overlay button.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Featured Articles",
"minChars": 2,
"maxChars": 50
},
"description": {
"required": true,
"example": "Explore our latest insights",
"minChars": 5,
"maxChars": 250
},
"tag": {
"required": false,
"example": "Blog",
"minChars": 2,
"maxChars": 30
}
},
"blogRules": {
"blogs": {
"required": true,
"minItems": 1,
"example": "[{\"id\": \"1\", \"category\": \"Software Development\", \"title\": \"Redefining Digital Performance\", \"excerpt\": \"Optimizing speed and scalability\", \"imageSrc\": \"/blog-1.jpg\"}]",
"note": "Array of blog items. Each item requires id, category, title, excerpt, and imageSrc."
}
}
},
"propsSchema": {
"blogs": "Array<{ id: string, category: string, title: string, excerpt: string, imageSrc?: string, imageAlt?: string, authorName?: string, authorAvatar?: string, date?: string, onBlogClick?: () => void }> - Blog card items",
"carouselMode?": "'auto' | 'buttons' (default: 'buttons')",
"uniformGridCustomHeightClasses?": "string (default: 'min-h-none')",
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' (required - controls GSAP scroll animations with stagger effect)",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"ariaLabel?": "string (default: 'Blog section')",
"className?": "string"
},
"usageExample": "<BlogCardThree blogs={[{id: '1', category: 'Software Development', title: 'Redefining Digital Performance at Scale', excerpt: 'Optimizing speed, scalability, and user experience.', imageSrc: '/blog-1.jpg', onBlogClick: () => console.log('clicked')}]} title=\"Featured Articles\" description=\"Explore our latest insights\" textboxLayout=\"default\" useInvertedBackground={\"noInvert\"} animationType=\"slide-up\" />",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays",
"Use for blog listings",
"Use for article grids",
"Requires blogs[]",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,64 @@
{
"name": "BlogCardTwo",
"description": "Blog section with card grid/carousel layout featuring image, author/date, title, excerpt, and multiple tags.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Latest Articles",
"minChars": 2,
"maxChars": 50
},
"description": {
"required": true,
"example": "Insights and updates from our team",
"minChars": 5,
"maxChars": 250
},
"tag": {
"required": false,
"example": "Blog",
"minChars": 2,
"maxChars": 30
}
},
"blogRules": {
"blogs": {
"required": true,
"minItems": 1,
"example": "[{\"id\": \"1\", \"category\": [\"Design\", \"Research\"], \"title\": \"UX review presentations\", \"excerpt\": \"How to create compelling presentations\", \"imageSrc\": \"/blog-1.jpg\", \"authorName\": \"Olivia Rhye\", \"date\": \"20 Jan 2025\"}]",
"note": "Array of blog items. Each item requires id, category (string | string[]), title, excerpt, imageSrc, authorName, and date."
}
}
},
"propsSchema": {
"blogs": "Array<{ id: string, category: string | string[], title: string, excerpt: string, imageSrc: string, imageAlt?: string, authorName: string, authorAvatar?: string, date: string, onBlogClick?: () => void }> - Blog card items",
"carouselMode?": "'auto' | 'buttons' (default: 'buttons')",
"uniformGridCustomHeightClasses?": "string",
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' (required - controls GSAP scroll animations with stagger effect)",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"ariaLabel?": "string (default: 'Blog section')",
"className?": "string"
},
"usageExample": "<BlogCardTwo blogs={[{id: '1', category: ['Design', 'Research', 'Presentation'], title: 'UX review presentations', excerpt: 'How to create compelling presentations that wow your audience', imageSrc: '/blog-1.jpg', authorName: 'Olivia Rhye', date: '20 Jan 2025', onBlogClick: () => console.log('clicked')}]} title=\"Latest Articles\" description=\"Stay updated with our latest insights\" textboxLayout=\"default\" useInvertedBackground={\"noInvert\"} animationType=\"slide-up\" carouselMode=\"buttons\" />",
"do": [
"Use for blog listings",
"Use for article grids",
"Requires blogs[]",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,19 @@
{
"name": "BlurBottomBackground",
"description": "Backdrop blur effect positioned at the bottom of the page with linear gradient mask.",
"constraints": {},
"propsSchema": {
"className?": "string"
},
"usageExample": "<BlurBottomBackground />",
"do": [
"Use for feature showcases",
"Use for capability displays"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,34 @@
{
"name": "ButtonBounceEffect",
"description": "CTA button with bouncing character animation on hover.",
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Get Started",
"minChars": 2,
"maxChars": 25
}
}
},
"propsSchema": {
"text": "string",
"onClick?": "() => void",
"href?": "string - External URLs open in new tab, internal values scroll to section",
"scrollToSection?": "boolean",
"className?": "string",
"disabled?": "boolean (default: false)",
"ariaLabel?": "string",
"type?": "'button' | 'submit' | 'reset' (default: 'button')"
},
"usageExample": "<ButtonBounceEffect text=\"Get Started\" href=\"contact\" />",
"do": [
"Use for general use"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,34 @@
{
"name": "ButtonDirectionalHover",
"description": "CTA button with a circle that expands from the mouse entry point on hover.",
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Get Started",
"minChars": 2,
"maxChars": 25
}
}
},
"propsSchema": {
"text": "string",
"onClick?": "() => void",
"href?": "string - External URLs open in new tab, internal values scroll to section",
"scrollToSection?": "boolean",
"className?": "string",
"disabled?": "boolean (default: false)",
"ariaLabel?": "string",
"type?": "'button' | 'submit' | 'reset' (default: 'button')"
},
"usageExample": "<ButtonDirectionalHover text=\"Get Started\" href=\"contact\" />",
"do": [
"Use for general use"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,34 @@
{
"name": "ButtonElasticEffect",
"description": "CTA button with elastic scale animation on hover.",
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Get Started",
"minChars": 2,
"maxChars": 25
}
}
},
"propsSchema": {
"text": "string",
"onClick?": "() => void",
"href?": "string - External URLs open in new tab, internal values scroll to section",
"scrollToSection?": "boolean",
"className?": "string",
"disabled?": "boolean (default: false)",
"ariaLabel?": "string",
"type?": "'button' | 'submit' | 'reset' (default: 'button')"
},
"usageExample": "<ButtonElasticEffect text=\"Get Started\" href=\"contact\" />",
"do": [
"Use for general use"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,34 @@
{
"name": "ButtonExpandHover",
"description": "CTA button with expanding background animation from right to left on hover, with a fixed arrow icon.",
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Get Started",
"minChars": 2,
"maxChars": 25
}
}
},
"propsSchema": {
"text": "string",
"onClick?": "() => void",
"href?": "string - External URLs open in new tab, internal values scroll to section",
"scrollToSection?": "boolean",
"className?": "string",
"disabled?": "boolean (default: false)",
"ariaLabel?": "string",
"type?": "'button' | 'submit' | 'reset' (default: 'button')"
},
"usageExample": "<ButtonExpandHover text=\"Get Started\" href=\"contact\" />",
"do": [
"Use for general use"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,34 @@
{
"name": "ButtonHoverBubble",
"description": "CTA button with expanding bubble animation where an arrow icon slides out and the text expands on hover.",
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Contact Us",
"minChars": 2,
"maxChars": 25
}
}
},
"propsSchema": {
"text": "string",
"onClick?": "() => void",
"href?": "string - External URLs open in new tab, internal values scroll to section",
"scrollToSection?": "boolean",
"className?": "string",
"disabled?": "boolean (default: false)",
"ariaLabel?": "string",
"type?": "'button' | 'submit' | 'reset' (default: 'button')"
},
"usageExample": "<ButtonHoverBubble text=\"Contact Us\" href=\"contact\" />",
"do": [
"Use for general use"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,35 @@
{
"name": "ButtonHoverMagnetic",
"description": "CTA button that subtly follows the cursor with a magnetic hover effect.",
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Button",
"minChars": 2,
"maxChars": 25
}
}
},
"propsSchema": {
"text": "string",
"onClick?": "() => void",
"href?": "string - External URLs open in new tab, internal values scroll to section",
"scrollToSection?": "boolean",
"className?": "string",
"strengthFactor?": "number (default: 20)",
"disabled?": "boolean (default: false)",
"ariaLabel?": "string",
"type?": "'button' | 'submit' | 'reset' (default: 'button')"
},
"usageExample": "<ButtonHoverMagnetic text=\"Button\" href=\"contact\" />",
"do": [
"Use for general use"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,34 @@
{
"name": "ButtonIconArrow",
"description": "Button with a trailing arrow icon that transforms on hover.",
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Button",
"minChars": 2,
"maxChars": 25
}
}
},
"propsSchema": {
"text": "string",
"onClick?": "() => void",
"href?": "string - External URLs open in new tab, internal values scroll to section",
"scrollToSection?": "boolean",
"className?": "string",
"disabled?": "boolean (default: false)",
"ariaLabel?": "string",
"type?": "'button' | 'submit' | 'reset' (default: 'button')"
},
"usageExample": "<ButtonIconArrow text=\"Continue\" href=\"next-section\" />",
"do": [
"Use for general use"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,36 @@
{
"name": "ButtonShiftHover",
"description": "CTA button where the label nudges upward on hover and a trailing dot fills from outline to solid.",
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Get Started",
"minChars": 2,
"maxChars": 25
}
}
},
"propsSchema": {
"text": "string",
"onClick?": "() => void",
"href?": "string - External URLs open in new tab, internal values scroll to section",
"scrollToSection?": "boolean",
"className?": "string",
"disabled?": "boolean (default: false)",
"ariaLabel?": "string",
"type?": "'button' | 'submit' | 'reset' (default: 'button')"
},
"usageExample": "<ButtonShiftHover text=\"Get Started\" href=\"pricing\" />",
"do": [
"Use for general use"
],
"dont": [
"Do not use multiple items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,34 @@
{
"name": "ButtonTextShift",
"description": "CTA button with synchronized character shift animation on hover.",
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Get Started",
"minChars": 2,
"maxChars": 25
}
}
},
"propsSchema": {
"text": "string",
"onClick?": "() => void",
"href?": "string - External URLs open in new tab, internal values scroll to section",
"scrollToSection?": "boolean",
"className?": "string",
"disabled?": "boolean (default: false)",
"ariaLabel?": "string",
"type?": "'button' | 'submit' | 'reset' (default: 'button')"
},
"usageExample": "<ButtonTextShift text=\"Get Started\" href=\"contact\" />",
"do": [
"Use for general use"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,34 @@
{
"name": "ButtonTextStagger",
"description": "CTA button with character stagger animation on hover.",
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Get Started",
"minChars": 2,
"maxChars": 25
}
}
},
"propsSchema": {
"text": "string",
"onClick?": "() => void",
"href?": "string - External URLs open in new tab, internal values scroll to section",
"scrollToSection?": "boolean",
"className?": "string",
"disabled?": "boolean (default: false)",
"ariaLabel?": "string",
"type?": "'button' | 'submit' | 'reset' (default: 'button')"
},
"usageExample": "<ButtonTextStagger text=\"Get Started\" href=\"https://example.com\" />",
"do": [
"Use for general use"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,34 @@
{
"name": "ButtonTextUnderline",
"description": "Text-only button where an underline animates in on hover.",
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Learn more",
"minChars": 2,
"maxChars": 25
}
}
},
"propsSchema": {
"text": "string",
"onClick?": "() => void",
"href?": "string - External URLs open in new tab, internal values scroll to section",
"scrollToSection?": "boolean",
"className?": "string",
"disabled?": "boolean (default: false)",
"ariaLabel?": "string",
"type?": "'button' | 'submit' | 'reset' (default: 'button')"
},
"usageExample": "<ButtonTextUnderline text=\"Learn more\" href=\"about\" />",
"do": [
"Use for general use"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,55 @@
{
"name": "CardStack",
"description": "Adaptive layout component that displays children in a grid, timeline, or carousel based on item count and variant.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Features",
"minChars": 2,
"maxChars": 50
},
"description": {
"required": true,
"example": "Discover our products",
"minChars": 5,
"maxChars": 300
},
"tag": {
"required": false,
"example": "New",
"minChars": 2,
"maxChars": 30
}
}
},
"propsSchema": {
"children": "React.ReactNode",
"mode?": "'auto' | 'buttons' (default: 'buttons')",
"gridVariant?": "'uniform-all-items-equal' | 'bento-grid' | 'bento-grid-inverted' | 'two-columns-alternating-heights' | 'asymmetric-60-wide-40-narrow' | 'three-columns-all-equal-width' | 'four-items-2x2-equal-grid' | 'one-large-right-three-stacked-left' | 'items-top-row-full-width-bottom' | 'full-width-top-items-bottom-row' | 'one-large-left-three-stacked-right' | 'timeline' (default: 'uniform-all-items-equal')",
"uniformGridCustomHeightClasses?": "string (default: varies by usage)",
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' | 'depth-3d' (required - controls GSAP scroll animations with stagger effect)",
"title?": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description?": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
"useInvertedBackground?": "'noInvert' | 'invertDefault'",
"ariaLabel?": "string (default: 'Card stack')",
"className?": "string"
},
"usageExample": "<CardStack title=\"Features\" buttons={[{ text: 'View All', href: 'features' }]} animationType=\"slide-up\" textboxLayout=\"default\">{/* Card components */}</CardStack>",
"do": [
"Use for general use",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,20 @@
{
"name": "CircleGradientBackground",
"description": "Two large gradient circles positioned diagonally in corners.",
"constraints": {},
"propsSchema": {
"diagonal?": "'primary' | 'secondary' (default: 'primary')",
"className?": "string"
},
"usageExample": "<CircleGradientBackground diagonal=\"primary\" />",
"do": [
"Use for feature showcases",
"Use for capability displays"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,73 @@
{
"name": "ContactCenter",
"description": "Centered contact section with tag, animated title and description, email signup form, and terms text.",
"constraints": {
"textRules": {
"tag": {
"required": true,
"example": "Newsletter",
"minChars": 2,
"maxChars": 20
},
"title": {
"required": true,
"example": "Medium length heading goes here",
"minChars": 4,
"maxChars": 50
},
"description": {
"required": true,
"example": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique.",
"minChars": 20,
"maxChars": 200
},
"inputPlaceholder": {
"required": false,
"default": "Enter your email",
"example": "Your email address",
"minChars": 5,
"maxChars": 30
},
"buttonText": {
"required": false,
"default": "Sign Up",
"example": "Subscribe",
"minChars": 2,
"maxChars": 15
},
"termsText": {
"required": false,
"default": "By clicking Sign Up you're confirming that you agree with our Terms and Conditions.",
"example": "We respect your privacy. Unsubscribe at any time.",
"minChars": 10,
"maxChars": 150
}
}
},
"propsSchema": {
"tag": "string",
"title": "string",
"description": "string",
"tagIcon?": "LucideIcon",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"inputPlaceholder?": "string (default: 'Enter your email')",
"buttonText?": "string (default: 'Sign Up')",
"termsText?": "string (default: 'By clicking Sign Up you're confirming that you agree with our Terms and Conditions.')",
"onSubmit?": "(email: string) => void",
"ariaLabel?": "string (default: 'Contact section')",
"className?": "string"
},
"usageExample": "// Wrap in ThemeProvider\n<ThemeProvider defaultButtonVariant=\"text-stagger\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"rounded\" background=\"aurora\" cardStyle=\"glass-elevated\" primaryButtonStyle=\"gradient\" secondaryButtonStyle=\"glass\">\n <ContactCenter tag=\"Newsletter\" title=\"Stay updated with our latest news\" description=\"Subscribe to our newsletter for weekly updates and exclusive content.\" useInvertedBackground={\"noInvert\"} onSubmit={(email) => console.log(email)} />\n</ThemeProvider>",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Use for contact pages",
"Use for lead generation"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,70 @@
{
"name": "ContactFaq",
"description": "Split-panel contact section with CTA card on left and FAQ accordions on right.",
"constraints": {
"textRules": {
"ctaTitle": {
"required": true,
"example": "Book an intro call",
"minChars": 2,
"maxChars": 50
},
"ctaDescription": {
"required": true,
"example": "Let's get started with a brief intro call.",
"minChars": 5,
"maxChars": 100
}
},
"faqRules": {
"id": {
"required": true,
"example": "1",
"minChars": 1,
"maxChars": 20
},
"title": {
"required": true,
"example": "What's included in the subscription?",
"minChars": 5,
"maxChars": 100
},
"content": {
"required": true,
"example": "Your subscription covers end-to-end digital design services...",
"minChars": 10,
"maxChars": 500,
"note": "Supports HTML content"
}
}
},
"propsSchema": {
"faqs": "Array<{ id: string, title: string, content: string }>",
"ctaTitle": "string",
"ctaDescription": "string",
"ctaButton": "{text: string, onClick?: () => void, href?: string}",
"ctaIcon": "LucideIcon (required)",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' (required - controls GSAP scroll animations with stagger effect on panels)",
"accordionAnimationType?": "'smooth' | 'instant' (default: 'smooth')",
"showCard?": "boolean (default: true - controls accordion card styling)",
"ariaLabel?": "string (default: 'Contact and FAQ section')",
"className?": "string"
},
"usageExample": "<ContactFaq faqs={[{ id: '1', title: \"What's included?\", content: 'Your subscription covers...' }]} ctaTitle=\"Book an intro call\" ctaDescription=\"Let's get started with a brief intro call.\" ctaButton={{ text: 'Book a Free Call', href: '#contact' }} ctaIcon={Phone} useInvertedBackground=\"noInvert\" animationType=\"slide-up\" />",
"do": [
"Use for contact pages",
"Use for lead generation",
"Use for help pages",
"Use for support sections",
"Requires faqs[]"
],
"dont": [
"Do not use more than 4 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,74 @@
{
"name": "ContactForm",
"description": "Complete contact form component with tag, animated title and description, email signup form, and terms text.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Join our newsletter",
"minChars": 4,
"maxChars": 60
},
"description": {
"required": true,
"example": "Get the latest updates and exclusive content delivered to your inbox",
"minChars": 10,
"maxChars": 200
},
"tag": {
"required": true,
"example": "Newsletter",
"minChars": 2,
"maxChars": 30
},
"inputPlaceholder": {
"required": false,
"default": "Enter your email",
"example": "Your email address",
"minChars": 5,
"maxChars": 50
},
"buttonText": {
"required": false,
"default": "Sign Up",
"example": "Subscribe",
"minChars": 2,
"maxChars": 15
},
"termsText": {
"required": false,
"default": "By clicking Sign Up you're confirming that you agree with our Terms and Conditions.",
"example": "We respect your privacy. Unsubscribe anytime.",
"minChars": 10,
"maxChars": 200
}
}
},
"propsSchema": {
"title": "string (required)",
"description": "string (required)",
"tag": "string (required)",
"tagIcon?": "LucideIcon",
"inputPlaceholder?": "string (default: 'Enter your email')",
"buttonText?": "string (default: 'Sign Up')",
"termsText?": "string (default: 'By clicking Sign Up you're confirming that you agree with our Terms and Conditions.')",
"onSubmit?": "(email: string) => void",
"useInvertedBackground": "'noInvert' | 'invertDefault' (required)",
"centered?": "boolean (default: false)",
"className?": "string"
},
"usageExample": "<ContactForm title=\"Join our newsletter\" description=\"Get updates\" tag=\"Newsletter\" useInvertedBackground=\"noInvert\" onSubmit={(email) => console.log(email)} />",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays",
"Use for contact pages",
"Use for lead generation"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,78 @@
{
"name": "ContactSplit",
"description": "Split layout contact section with tag, animated title and description on one side, media content on the other, and email signup form.",
"constraints": {
"textRules": {
"tag": {
"required": true,
"example": "Newsletter",
"minChars": 2,
"maxChars": 20
},
"title": {
"required": true,
"example": "Medium length heading goes here",
"minChars": 4,
"maxChars": 50
},
"description": {
"required": true,
"example": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique.",
"minChars": 20,
"maxChars": 200
},
"inputPlaceholder": {
"required": false,
"default": "Enter your email",
"example": "Your email address",
"minChars": 5,
"maxChars": 30
},
"buttonText": {
"required": false,
"default": "Sign Up",
"example": "Subscribe",
"minChars": 2,
"maxChars": 15
},
"termsText": {
"required": false,
"default": "By clicking Sign Up you're confirming that you agree with our Terms and Conditions.",
"example": "We respect your privacy. Unsubscribe at any time.",
"minChars": 10,
"maxChars": 150
}
}
},
"propsSchema": {
"tag": "string",
"title": "string",
"description": "string",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"imageSrc?": "string",
"videoSrc?": "string",
"imageAlt?": "string (default: '')",
"videoAriaLabel?": "string (default: 'Contact section video')",
"mediaPosition?": "'left' | 'right' (default: 'right')",
"tagIcon?": "LucideIcon",
"inputPlaceholder?": "string (default: 'Enter your email')",
"buttonText?": "string (default: 'Sign Up')",
"termsText?": "string (default: 'By clicking Sign Up you're confirming that you agree with our Terms and Conditions.')",
"onSubmit?": "(email: string) => void",
"ariaLabel?": "string (default: 'Contact section')",
"className?": "string"
},
"usageExample": "// Wrap in ThemeProvider\n<ThemeProvider defaultButtonVariant=\"text-stagger\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"rounded\" background=\"aurora\" cardStyle=\"glass-elevated\" primaryButtonStyle=\"gradient\" secondaryButtonStyle=\"glass\">\n <ContactSplit tag=\"Newsletter\" title=\"Stay updated\" description=\"Subscribe to our newsletter for weekly updates and exclusive content.\" useInvertedBackground={\"noInvert\"} imageSrc=\"/placeholders/placeholder-16-9.svg\" onSubmit={(email) => console.log(email)} />\n</ThemeProvider>",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Use for contact pages",
"Use for lead generation"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,57 @@
{
"name": "ContactSplitForm",
"description": "Split layout contact form with animated title and description, dynamic input fields, optional textarea, submit button, and media content.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Medium length heading goes here",
"minChars": 4,
"maxChars": 50
},
"description": {
"required": true,
"example": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique.",
"minChars": 20,
"maxChars": 200
},
"buttonText": {
"required": false,
"default": "Submit",
"example": "Send Message",
"minChars": 2,
"maxChars": 15
}
}
},
"propsSchema": {
"title": "string",
"description": "string",
"inputs": "Array<{ name: string, type: string, placeholder: string, required?: boolean, className?: string }> - Form input fields (min 2 required)",
"textarea?": "{ name: string, placeholder: string, rows?: number, required?: boolean, className?: string } - Optional textarea field",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"imageSrc?": "string",
"videoSrc?": "string",
"imageAlt?": "string (default: '')",
"videoAriaLabel?": "string (default: 'Contact section video')",
"mediaPosition?": "'left' | 'right' (default: 'right')",
"buttonText?": "string (default: 'Submit')",
"onSubmit?": "(data: Record<string, string>) => void",
"ariaLabel?": "string (default: 'Contact section')",
"className?": "string"
},
"usageExample": "// Wrap in ThemeProvider\n<ThemeProvider defaultButtonVariant=\"text-stagger\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"rounded\" background=\"aurora\" cardStyle=\"glass-elevated\" primaryButtonStyle=\"gradient\" secondaryButtonStyle=\"glass\">\n <ContactSplitForm title=\"Get in touch\" description=\"We'd love to hear from you. Send us a message.\" inputs={[{ name: 'name', type: 'text', placeholder: 'Name', required: true }, { name: 'email', type: 'email', placeholder: 'Email', required: true }]} textarea={{ name: 'message', placeholder: 'Type your message...', rows: 5, required: true }} useInvertedBackground={\"noInvert\"} imageSrc=\"/placeholders/placeholder-16-9.svg\" onSubmit={(data) => console.log(data)} />\n</ThemeProvider>",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Use for contact pages",
"Use for lead generation",
"Requires inputs[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,48 @@
{
"name": "ContactText",
"description": "Centered contact section with animated text and action buttons in a card container.",
"constraints": {
"textRules": {
"text": {
"required": true,
"example": "Ready to start your next project? Let's create something amazing together.",
"minChars": 10,
"maxChars": 200
},
"animationType": {
"required": false,
"default": "entrance-slide",
"options": [
"entrance-slide",
"reveal-blur",
"background-highlight"
],
"note": "GSAP scroll-triggered animation type for text"
}
},
"buttonRules": {
"maxButtons": 2,
"note": "Supports up to 2 buttons with px-8 spacing. Buttons use theme.defaultButtonVariant."
}
},
"propsSchema": {
"text": "string",
"animationType?": "'entrance-slide' | 'reveal-blur' | 'background-highlight' (default: 'entrance-slide')",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"ariaLabel?": "string (default: 'Contact section')",
"className?": "string"
},
"usageExample": "<ContactText text=\"Ready to start your next project? Let's create something amazing together.\" animationType=\"entrance-slide\" buttons={[{ text: 'Get in Touch', href: '/contact' }, { text: 'View Portfolio', href: '/portfolio' }]} useInvertedBackground=\"noInvert\" />",
"do": [
"Use for contact pages",
"Use for lead generation",
"Requires buttons?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,23 @@
{
"name": "DotGridBackground",
"description": "Dot pattern background with radial gradient dots and optional 3D perspective effect.",
"constraints": {},
"propsSchema": {
"size?": "'small' | 'medium' | 'large' (default: 'medium')",
"perspectiveThreeD?": "boolean (default: false)",
"className?": "string"
},
"usageExample": "<DotGridBackground size=\"medium\" perspectiveThreeD={false} />",
"do": [
"Use for feature showcases",
"Use for capability displays"
],
"dont": [
"Do not use more than 4 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,27 @@
{
"name": "DownwardRaysBackground",
"description": "Atmospheric light rays emanating from top center directly downward with blur and radial gradient effects, with optional grid overlay.",
"constraints": {},
"propsSchema": {
"animated": "boolean - Required. When true, rays animate with pulsing opacity. When false, rays display static opacity.",
"showGrid": "boolean - Required. When true, displays a grid overlay fading from top center. When false, no grid is shown.",
"className?": "string",
"containerClassName?": "string"
},
"usageExample": "<DownwardRaysBackground animated={true} showGrid={false} />",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays",
"Use for statistics displays",
"Use for achievement showcases"
],
"dont": [
"Do not use more than 4 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,39 @@
{
"name": "EmailSignupForm",
"description": "Compact email signup form with inline input and submit button in card container.",
"constraints": {
"textRules": {
"inputPlaceholder": {
"required": false,
"default": "Enter your email",
"example": "Your email address",
"minChars": 5,
"maxChars": 50
},
"buttonText": {
"required": false,
"default": "Sign Up",
"example": "Subscribe",
"minChars": 2,
"maxChars": 15
}
}
},
"propsSchema": {
"inputPlaceholder?": "string (default: 'Enter your email')",
"buttonText?": "string (default: 'Sign Up')",
"onSubmit?": "(email: string) => void",
"className?": "string"
},
"usageExample": "<EmailSignupForm inputPlaceholder=\"Your email\" buttonText=\"Subscribe\" onSubmit={(email) => console.log(email)} />",
"do": [
"Use for feature showcases",
"Use for capability displays"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,72 @@
{
"name": "FaqBase",
"description": "FAQ section with accordion items and optional header.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Frequently Asked Questions",
"minChars": 2,
"maxChars": 50
},
"description": {
"required": true,
"example": "Find answers to common questions about our products and services",
"minChars": 5,
"maxChars": 250
},
"tag": {
"required": false,
"example": "Help",
"minChars": 2,
"maxChars": 30
}
},
"faqRules": {
"faqs": {
"required": true,
"minItems": 1,
"example": "[{\"id\": \"1\", \"title\": \"What is your return policy?\", \"content\": \"We offer a 30-day money-back guarantee.\"}]",
"note": "Array of FAQ items. Each item requires unique id, title (question), and content (answer with HTML support)."
},
"animationType": {
"required": false,
"default": "smooth",
"options": [
"smooth",
"instant"
],
"note": "Animation type for accordion open/close. 'smooth' uses height transition, 'instant' shows/hides immediately."
}
}
},
"propsSchema": {
"faqs": "Array<{ id: string, title: string, content: string }> - FAQ items",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"animationType?": "'smooth' | 'instant' (default: 'smooth')",
"showCard?": "boolean (default: true)",
"ariaLabel?": "string (default: 'FAQ section')",
"className?": "string"
},
"usageExample": "<FaqBase faqs={[{id: '1', title: 'What is your return policy?', content: 'We offer a 30-day money-back guarantee on all our products.'}, {id: '2', title: 'How long does shipping take?', content: 'Standard shipping typically takes 5-7 business days.'}]} title=\"Frequently Asked Questions\" description=\"Find answers to common questions\" textboxLayout=\"default\" useInvertedBackground={\"noInvert\"} />",
"do": [
"Use for help pages",
"Use for support sections",
"Requires faqs[]",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,71 @@
{
"name": "FaqDouble",
"description": "FAQ section with two-column accordion layout and optional header.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Frequently Asked Questions",
"minChars": 2,
"maxChars": 50
},
"description": {
"required": true,
"example": "Find answers to common questions about our products and services",
"minChars": 5,
"maxChars": 250
},
"tag": {
"required": false,
"example": "Help",
"minChars": 2,
"maxChars": 30
}
},
"faqRules": {
"faqs": {
"required": true,
"minItems": 1,
"example": "[{\"id\": \"1\", \"title\": \"What is your return policy?\", \"content\": \"We offer a 30-day money-back guarantee.\"}]",
"note": "Array of FAQ items. Each item requires unique id, title (question), and content (answer with HTML support). Items are automatically split into two columns."
},
"animationType": {
"required": false,
"default": "smooth",
"options": [
"smooth",
"instant"
],
"note": "Animation type for accordion open/close. 'smooth' uses height transition, 'instant' shows/hides immediately."
}
}
},
"propsSchema": {
"faqs": "Array<{ id: string, title: string, content: string }> - FAQ items",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"animationType?": "'smooth' | 'instant' (default: 'smooth')",
"ariaLabel?": "string (default: 'FAQ section')",
"className?": "string"
},
"usageExample": "<FaqDouble faqs={[{id: '1', title: 'What is your return policy?', content: 'We offer a 30-day money-back guarantee on all our products.'}, {id: '2', title: 'How long does shipping take?', content: 'Standard shipping typically takes 5-7 business days.'}, {id: '3', title: 'Do you ship internationally?', content: 'Yes, we ship to over 100 countries worldwide.'}]} title=\"Frequently Asked Questions\" description=\"Find answers to common questions\" textboxLayout=\"default\" useInvertedBackground={\"noInvert\"} />",
"do": [
"Use for help pages",
"Use for support sections",
"Requires faqs[]",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,98 @@
{
"name": "FaqSplitMedia",
"description": "FAQ section with split layout featuring media (image/video) on one side and accordion list on the other.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Frequently Asked Questions",
"minChars": 2,
"maxChars": 50
},
"description": {
"required": true,
"example": "Find answers to common questions about our products and services",
"minChars": 5,
"maxChars": 250
},
"tag": {
"required": false,
"example": "Help",
"minChars": 2,
"maxChars": 30
}
},
"faqRules": {
"faqs": {
"required": true,
"minItems": 1,
"example": "[{\"id\": \"1\", \"title\": \"What is your return policy?\", \"content\": \"We offer a 30-day money-back guarantee.\"}]",
"note": "Array of FAQ items. Each item requires unique id, title (question), and content (answer with HTML support)."
},
"animationType": {
"required": false,
"default": "smooth",
"options": [
"smooth",
"instant"
],
"note": "Animation type for accordion open/close. 'smooth' uses height transition, 'instant' shows/hides immediately."
},
"mediaPosition": {
"required": false,
"default": "left",
"options": [
"left",
"right"
],
"note": "Position of media relative to FAQ list."
}
},
"mediaRules": {
"imageSrc": {
"required": false,
"note": "Path to image file. Either imageSrc or videoSrc should be provided."
},
"videoSrc": {
"required": false,
"note": "Path to video file. Either imageSrc or videoSrc should be provided."
}
}
},
"propsSchema": {
"faqs": "Array<{ id: string, title: string, content: string }> - FAQ items",
"imageSrc?": "string",
"videoSrc?": "string",
"imageAlt?": "string (default: '')",
"videoAriaLabel?": "string (default: 'FAQ section video')",
"mediaPosition?": "'left' | 'right' (default: 'left')",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"animationType?": "'smooth' | 'instant' (default: 'smooth')",
"showCard?": "boolean (default: true)",
"ariaLabel?": "string (default: 'FAQ section')",
"className?": "string"
},
"usageExample": "<FaqSplitMedia faqs={[{id: '1', title: 'What is your return policy?', content: 'We offer a 30-day money-back guarantee on all our products.'}, {id: '2', title: 'How long does shipping take?', content: 'Standard shipping typically takes 5-7 business days.'}]} imageSrc=\"/images/faq-hero.jpg\" imageAlt=\"Customer support representative\" title=\"Frequently Asked Questions\" description=\"Find answers to common questions\" textboxLayout=\"default\" useInvertedBackground={\"noInvert\"} mediaPosition=\"left\" />",
"do": [
"Use for help pages",
"Use for support sections",
"Requires faqs[]",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [
"Do not use more than 4 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,71 @@
{
"name": "FaqSplitText",
"description": "FAQ section with split layout featuring animated text on one side and accordion list on the other.",
"constraints": {
"textRules": {
"sideTitle": {
"required": true,
"example": "Frequently Asked Questions",
"minChars": 2,
"maxChars": 100
},
"sideDescription": {
"required": false,
"example": "Everything you need to know",
"minChars": 5,
"maxChars": 250
}
},
"faqRules": {
"faqs": {
"required": true,
"minItems": 1,
"example": "[{\"id\": \"1\", \"title\": \"What is your return policy?\", \"content\": \"We offer a 30-day money-back guarantee.\"}]",
"note": "Array of FAQ items. Each item requires unique id, title (question), and content (answer with HTML support)."
},
"animationType": {
"required": false,
"default": "smooth",
"options": [
"smooth",
"instant"
],
"note": "Animation type for accordion open/close. 'smooth' uses height transition, 'instant' shows/hides immediately."
},
"textPosition": {
"required": false,
"default": "left",
"options": [
"left",
"right"
],
"note": "Position of title/description text relative to FAQ list."
}
}
},
"propsSchema": {
"faqs": "Array<{ id: string, title: string, content: string }> - FAQ items",
"sideTitle": "string",
"sideDescription?": "string",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"textPosition?": "'left' | 'right' (default: 'left')",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"animationType?": "'smooth' | 'instant' (default: 'smooth')",
"showCard?": "boolean (default: true)",
"ariaLabel?": "string (default: 'FAQ section')",
"className?": "string"
},
"usageExample": "<FaqSplitText faqs={[{id: '1', title: 'How can I be part of Buenro?', content: 'You can join by signing up on our platform.'}, {id: '2', title: 'Can anyone join Buenro?', content: 'Yes! We welcome remote workers and entrepreneurs.'}]} sideTitle=\"Frequently Asked Questions\" textPosition=\"left\" useInvertedBackground={\"noInvert\"} />",
"do": [
"Use for help pages",
"Use for support sections",
"Requires faqs[]",
"Requires buttons?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,111 @@
{
"name": "FeatureCardEight",
"description": "Horizontal timeline feature section with auto-advancing progress bars, numbered step badges, and shared media display.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Our Process",
"minChars": 2,
"maxChars": 35
},
"description": {
"required": true,
"example": "Discover how we bring ideas to life",
"minChars": 5,
"maxChars": 250
},
"tag": {
"required": false,
"example": "How It Works",
"minChars": 2,
"maxChars": 30
}
},
"featureCardRules": {
"id": {
"required": true,
"example": "1",
"minChars": 1,
"maxChars": 3,
"note": "Step number displayed in circular badge"
},
"title": {
"required": true,
"example": "Research & Planning",
"minChars": 2,
"maxChars": 50
},
"description": {
"required": true,
"example": "Understanding user needs, market trends, and project requirements",
"minChars": 10,
"maxChars": 300
}
},
"mediaRules": {
"imageSrc": {
"required": true,
"example": "/feature1.jpg",
"note": "Either imageSrc or videoSrc required per card (discriminated union)"
},
"videoSrc": {
"required": true,
"example": "/feature1.mp4",
"note": "Either imageSrc or videoSrc required per card (discriminated union)"
},
"imageAlt": {
"required": false,
"example": "Research and planning illustration",
"note": "Falls back to feature title if not provided"
},
"videoAriaLabel": {
"required": false,
"example": "Research and planning video",
"note": "Falls back to feature title if not provided"
}
},
"itemRules": {
"minItems": 2,
"maxItems": 4,
"recommendedItems": "2-4",
"note": "Works best with 2-4 features. Grid layout adapts based on item count."
}
},
"propsSchema": {
"features": "Array<{ id: number, title: string, description: string } & ({ imageSrc: string, imageAlt?: string } | { videoSrc: string, videoAriaLabel?: string })>",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"ariaLabel?": "string (default: 'Feature section')",
"className?": "string"
},
"usageExample": "<FeatureCardEight features={[{ id: 1, title: 'Research & Planning', description: 'Understanding user needs, market trends, and project requirements', imageSrc: '/feature1.jpg' }]} title=\"Our Process\" description=\"Discover how we bring ideas to life\" textboxLayout=\"default\" useInvertedBackground={\"noInvert\"} />",
"do": [
"Use for process flows",
"Use for roadmaps",
"Use for step-by-step explanation",
"Use for feature showcases",
"Use for capability displays",
"Requires features[]",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [
"Do not use non-sequential content",
"Do not use single item",
"Do not use more than 4 items",
"Do not use less than 2 items",
"Do not use more than 4 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,70 @@
{
"name": "FeatureCardMedia",
"description": "Feature section with media cards displaying tag overlay, title, description, and optional buttons.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "From concept to launch, we've got you covered",
"minChars": 10,
"maxChars": 100
},
"description": {
"required": true,
"example": "Discover how we bring ideas to life through a proven methodology",
"minChars": 20,
"maxChars": 300
},
"tag": {
"required": false,
"example": "Our Process",
"minChars": 2,
"maxChars": 30
}
},
"featuresRules": {
"minItems": 2,
"recommendedItems": 3,
"maxItems": 6,
"structure": {
"id": "string - Unique identifier (required)",
"title": "string - Card title (required)",
"description": "string - Card description (required)",
"tag": "string - Tag displayed on media top-right (required)",
"imageSrc": "string - Image source URL (optional)",
"videoSrc": "string - Video source URL (optional)",
"buttons": "ButtonConfig[] - Optional action buttons for the card"
},
"note": "Each card requires id, title, description, and tag. Media (imageSrc or videoSrc) recommended. Buttons are optional per card."
}
},
"propsSchema": {
"features": "Array<{ id: string, title: string, description: string, tag: string, imageSrc?: string, videoSrc?: string, imageAlt?: string, videoAriaLabel?: string, buttons?: ButtonConfig[], onCardClick?: () => void }>",
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal'",
"title": "string",
"description": "string",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image'",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }>",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "ButtonConfig[]",
"carouselMode?": "'auto' | 'buttons' (default: 'buttons')",
"uniformGridCustomHeightClasses?": "string",
"ariaLabel?": "string (default: 'Features section')",
"className?": "string"
},
"usageExample": "<FeatureCardMedia features={[{ id: '1', title: 'Research', description: 'Understanding user needs and market trends', tag: 'Phase 1', imageSrc: '/img.jpg', buttons: [{ text: 'Learn more', href: '#' }] }]} animationType=\"slide-up\" textboxLayout=\"default\" title=\"Our Process\" description=\"Discover how we work\" useInvertedBackground=\"noInvert\" />",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Requires features[]",
"Requires titleSegments?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,130 @@
{
"name": "FeatureCardNine",
"description": "Scroll-based timeline feature section with two animated phone frames and centered content.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Powerful Features",
"minChars": 2,
"maxChars": 35
},
"description": {
"required": true,
"example": "Everything you need to build amazing products",
"minChars": 5,
"maxChars": 250
},
"tag": {
"required": false,
"example": "Features",
"minChars": 2,
"maxChars": 30
}
},
"featureCardRules": {
"id": {
"required": true,
"example": "1",
"minChars": 1,
"maxChars": 3,
"note": "Feature identifier"
},
"title": {
"required": true,
"example": "Seamless Integration",
"minChars": 2,
"maxChars": 50
},
"description": {
"required": true,
"example": "Connect your tools and workflows effortlessly. Our platform integrates with your existing systems.",
"minChars": 10,
"maxChars": 300
}
},
"phoneMediaRules": {
"phoneOne": {
"imageSrc": {
"required": true,
"example": "/phone1.jpg",
"note": "Either imageSrc or videoSrc required for phoneOne (discriminated union)"
},
"videoSrc": {
"required": true,
"example": "/phone1.mp4",
"note": "Either imageSrc or videoSrc required for phoneOne (discriminated union)"
},
"imageAlt": {
"required": false,
"example": "First phone mockup",
"note": "Falls back to '[title] - Phone 1' if not provided"
},
"videoAriaLabel": {
"required": false,
"example": "First phone video",
"note": "Falls back to '[title] - Phone 1 video' if not provided"
}
},
"phoneTwo": {
"imageSrc": {
"required": true,
"example": "/phone2.jpg",
"note": "Either imageSrc or videoSrc required for phoneTwo (discriminated union)"
},
"videoSrc": {
"required": true,
"example": "/phone2.mp4",
"note": "Either imageSrc or videoSrc required for phoneTwo (discriminated union)"
},
"imageAlt": {
"required": false,
"example": "Second phone mockup",
"note": "Falls back to '[title] - Phone 2' if not provided"
},
"videoAriaLabel": {
"required": false,
"example": "Second phone video",
"note": "Falls back to '[title] - Phone 2 video' if not provided"
}
}
},
"itemRules": {
"minItems": 2,
"maxItems": 4,
"recommendedItems": "2-4",
"note": "Each feature takes 100vh height. Recommend 2-4 features to avoid excessive scroll."
}
},
"propsSchema": {
"features": "Array<{ id: number, title: string, description: string, phoneOne: ({ imageSrc: string, imageAlt?: string } | { videoSrc: string, videoAriaLabel?: string }), phoneTwo: ({ imageSrc: string, imageAlt?: string } | { videoSrc: string, videoAriaLabel?: string }) }>",
"showStepNumbers": "boolean (required - controls whether step number badges display)",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"ariaLabel?": "string (default: 'Feature section')",
"className?": "string"
},
"usageExample": "<FeatureCardNine features={[{ id: 1, title: 'Seamless Integration', description: 'Connect your tools and workflows effortlessly', phoneOne: { imageSrc: '/phone1.jpg' }, phoneTwo: { imageSrc: '/phone2.jpg' } }]} showStepNumbers={true} title=\"Powerful Features\" description=\"Everything you need to build amazing products\" textboxLayout=\"default\" useInvertedBackground={\"noInvert\"} />",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Requires features[]",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [
"Do not use less than 2 items",
"Do not use more than 4 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,111 @@
{
"name": "FeatureCardNineteen",
"description": "Timeline feature section with full-width cards showing step numbers and rotated media.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Our Process",
"minChars": 2,
"maxChars": 50
},
"description": {
"required": true,
"example": "Discover how we bring ideas to life",
"minChars": 5,
"maxChars": 300
},
"tag": {
"required": false,
"example": "How it works",
"minChars": 2,
"maxChars": 30
}
},
"featureCardRules": {
"id": {
"required": true,
"example": 1,
"note": "Numeric ID used to generate step number (01, 02, etc.)"
},
"tag": {
"required": true,
"example": "Expertise",
"minChars": 2,
"maxChars": 30
},
"title": {
"required": true,
"example": "Strategy",
"minChars": 2,
"maxChars": 30
},
"subtitle": {
"required": true,
"example": "Data-driven decisions for growth.",
"minChars": 5,
"maxChars": 60
},
"description": {
"required": true,
"example": "We analyze market trends and user behavior to create strategies that drive real results.",
"minChars": 10,
"maxChars": 250
},
"imageSrc": {
"required": false,
"example": "/images/strategy.webp",
"note": "Image source URL (either imageSrc or videoSrc)"
},
"videoSrc": {
"required": false,
"example": "/videos/strategy.mp4",
"note": "Video source URL (either imageSrc or videoSrc)"
},
"buttons": {
"required": false,
"example": [
{
"text": "Learn more",
"href": "/strategy"
}
],
"note": "Optional buttons per feature card (max 2)"
}
}
},
"propsSchema": {
"features": "Array<{ id: number, tag: string, title: string, subtitle: string, description: string, imageSrc?: string, videoSrc?: string, imageAlt?: string, videoAriaLabel?: string, buttons?: Array<{text: string, onClick?: () => void, href?: string}> }> (required)",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required)",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"ariaLabel?": "string (default: 'Feature section')",
"className?": "string"
},
"usageExample": "<FeatureCardNineteen features={[{ id: 1, tag: 'Expertise', title: 'Strategy', subtitle: 'Data-driven decisions', description: 'We analyze market trends...', imageSrc: '/images/strategy.webp' }]} title=\"Our Process\" description=\"Discover how we bring ideas to life\" textboxLayout=\"default\" useInvertedBackground=\"noInvert\" />",
"do": [
"Use for process flows",
"Use for roadmaps",
"Use for step-by-step explanation",
"Use for feature showcases",
"Use for capability displays",
"Requires features[]",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [
"Do not use multiple items",
"Do not use non-sequential content",
"Do not use single item"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,73 @@
{
"name": "FeatureCardOne",
"description": "Adaptive feature section with image/video-based cards in customizable bento grid layouts or carousel.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Our Features",
"minChars": 2,
"maxChars": 35
},
"description": {
"required": true,
"example": "Discover the tools and capabilities that make our platform powerful",
"minChars": 5,
"maxChars": 250
},
"tag": {
"required": false,
"example": "Features",
"minChars": 2,
"maxChars": 30
}
},
"featureCardRules": {
"title": {
"required": true,
"example": "Advanced Analytics",
"minChars": 2,
"maxChars": 35
},
"description": {
"required": true,
"example": "Get detailed insights into your business performance",
"minChars": 10,
"maxChars": 250
}
}
},
"propsSchema": {
"features": "Array<{ title: string, description: string, button?: {text: string, onClick?: () => void, href?: string} } & ({ imageSrc: string, imageAlt?: string } | { videoSrc: string, videoAriaLabel?: string })>",
"carouselMode?": "'auto' | 'buttons' (default: 'buttons')",
"gridVariant": "'uniform-all-items-equal' | 'bento-grid' | 'bento-grid-inverted' | 'two-columns-alternating-heights' | 'asymmetric-60-wide-40-narrow' | 'three-columns-all-equal-width' | 'four-items-2x2-equal-grid' | 'one-large-right-three-stacked-left' | 'items-top-row-full-width-bottom' | 'full-width-top-items-bottom-row' | 'one-large-left-three-stacked-right' | 'timeline' (required)",
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' | 'depth-3d' (required - controls GSAP scroll animations with stagger effect)",
"uniformGridCustomHeightClasses?": "string",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
"ariaLabel?": "string (default: 'Feature section')",
"className?": "string",
"useInvertedBackground": "'noInvert' | 'invertDefault'"
},
"usageExample": "<FeatureCardOne features={[{ title: 'Analytics', description: 'Get insights', imageSrc: '/feature.jpg', button: { text: 'Learn More', href: '#' } }]} title=\"Our Features\" description=\"Discover what makes us different\" textboxLayout=\"default\" animationType=\"slide-up\" useInvertedBackground={\"noInvert\"} />",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Use for statistics displays",
"Use for achievement showcases",
"Requires features[]",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,103 @@
{
"name": "FeatureCardSeven",
"description": "Vertical stack feature section with alternating left/right layouts and numbered step cards with square images.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Our Features",
"minChars": 2,
"maxChars": 35
},
"description": {
"required": true,
"example": "Sequential features with numbered badges",
"minChars": 5,
"maxChars": 250
},
"tag": {
"required": false,
"example": "Features",
"minChars": 2,
"maxChars": 30
}
},
"featureCardRules": {
"id": {
"required": true,
"example": "1",
"minChars": 1,
"maxChars": 3,
"note": "Step number displayed in circular badge"
},
"title": {
"required": true,
"example": "Modern Architecture",
"minChars": 2,
"maxChars": 50
},
"description": {
"required": true,
"example": "Built with the latest technologies and best practices",
"minChars": 10,
"maxChars": 300
}
},
"mediaRules": {
"imageSrc": {
"required": false,
"example": "/feature1.jpg",
"note": "Either imageSrc or videoSrc required per card"
},
"videoSrc": {
"required": false,
"example": "/feature1.mp4",
"note": "Either imageSrc or videoSrc required per card"
},
"imageAlt": {
"required": false,
"example": "Modern architecture illustration",
"note": "Falls back to feature title if not provided"
},
"videoAriaLabel": {
"required": false,
"example": "Modern architecture video",
"note": "Falls back to feature title if not provided"
}
}
},
"propsSchema": {
"features": "Array<{ id: number, title: string, description: string } & ({ imageSrc: string, imageAlt?: string } | { videoSrc: string, videoAriaLabel?: string })>",
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' (required - controls GSAP scroll animations with stagger effect)",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"ariaLabel?": "string (default: 'Feature section')",
"className?": "string"
},
"usageExample": "<FeatureCardSeven features={[{ id: 1, title: 'Modern Architecture', description: 'Built with the latest technologies and best practices', imageSrc: '/feature1.jpg' }]} title=\"Our Features\" description=\"Sequential features with numbered badges\" textboxLayout=\"default\" animationType=\"blur-reveal\" useInvertedBackground={\"noInvert\"} />",
"do": [
"Use for process flows",
"Use for roadmaps",
"Use for step-by-step explanation",
"Use for feature showcases",
"Use for capability displays",
"Requires features[]",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [
"Do not use non-sequential content",
"Do not use single item"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,102 @@
{
"name": "FeatureCardSix",
"description": "Timeline-based feature section with scroll-triggered stacking animations and numbered step cards.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Our Process",
"minChars": 2,
"maxChars": 35
},
"description": {
"required": true,
"example": "Discover how we bring ideas to life",
"minChars": 5,
"maxChars": 250
},
"tag": {
"required": false,
"example": "Process",
"minChars": 2,
"maxChars": 30
}
},
"featureCardRules": {
"id": {
"required": true,
"example": "1",
"minChars": 1,
"maxChars": 3,
"note": "Step number displayed in circular badge"
},
"title": {
"required": true,
"example": "Research & Planning",
"minChars": 2,
"maxChars": 50
},
"description": {
"required": true,
"example": "Understanding user needs, market trends, and project requirements",
"minChars": 10,
"maxChars": 300
}
},
"mediaRules": {
"imageSrc": {
"required": false,
"example": "/step1.jpg",
"note": "Either imageSrc or videoSrc required per card"
},
"videoSrc": {
"required": false,
"example": "/step1.mp4",
"note": "Either imageSrc or videoSrc required per card"
},
"imageAlt": {
"required": false,
"example": "Research phase illustration",
"note": "Falls back to feature title if not provided"
},
"videoAriaLabel": {
"required": false,
"example": "Research phase video",
"note": "Falls back to feature title if not provided"
}
}
},
"propsSchema": {
"features": "Array<{ id: number, title: string, description: string } & ({ imageSrc: string, imageAlt?: string } | { videoSrc: string, videoAriaLabel?: string })>",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"ariaLabel?": "string (default: 'Feature section')",
"className?": "string"
},
"usageExample": "<FeatureCardSix features={[{ id: 1, title: 'Research & Planning', description: 'Understanding user needs and project requirements', imageSrc: '/step1.jpg' }]} title=\"Our Process\" description=\"Discover how we bring ideas to life\" textboxLayout=\"default\" useInvertedBackground={\"noInvert\"} />",
"do": [
"Use for process flows",
"Use for roadmaps",
"Use for step-by-step explanation",
"Use for feature showcases",
"Use for capability displays",
"Requires features[]",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [
"Do not use non-sequential content",
"Do not use single item"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,80 @@
{
"name": "FeatureCardSixteen",
"description": "Comparison section with negative and positive cards showing contrasting features.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "What makes us stand out",
"minChars": 2,
"maxChars": 50
},
"description": {
"required": true,
"example": "See how we compare to traditional approaches",
"minChars": 5,
"maxChars": 300
},
"tag": {
"required": false,
"example": "Why us",
"minChars": 2,
"maxChars": 30
}
},
"negativeCardRules": {
"items": {
"required": true,
"example": [
"Time-consuming processes",
"Limited scalability",
"Higher costs"
],
"minItems": 2,
"maxItems": 10,
"note": "List of negative aspects displayed with X icons"
}
},
"positiveCardRules": {
"items": {
"required": true,
"example": [
"Streamlined workflow",
"Scalable solutions",
"Better value"
],
"minItems": 2,
"maxItems": 10,
"note": "List of positive aspects displayed with Check icons"
}
}
},
"propsSchema": {
"negativeCard": "{ items: string[] } (required)",
"positiveCard": "{ items: string[] } (required)",
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' | 'depth-3d' (required)",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required)",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"ariaLabel?": "string (default: 'Feature comparison section')",
"className?": "string"
},
"usageExample": "<FeatureCardSixteen negativeCard={{ items: ['Time-consuming processes', 'Limited scalability'] }} positiveCard={{ items: ['Streamlined workflow', 'Scalable solutions'] }} animationType=\"slide-up\" title=\"What makes us stand out\" description=\"See how we compare\" textboxLayout=\"default\" useInvertedBackground=\"noInvert\" />",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,90 @@
{
"name": "FeatureCardThree",
"description": "Adaptive feature section with hover-reveal cards displaying numbered features with images.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Our Features",
"minChars": 2,
"maxChars": 35
},
"description": {
"required": true,
"example": "Discover what makes us different",
"minChars": 5,
"maxChars": 250
},
"tag": {
"required": false,
"example": "Features",
"minChars": 2,
"maxChars": 30
}
},
"featureCardRules": {
"id": {
"required": true,
"example": "01",
"minChars": 1,
"maxChars": 3,
"note": "Displayed in the flip badge"
},
"title": {
"required": true,
"example": "Advanced Analytics",
"minChars": 2,
"maxChars": 35
},
"description": {
"required": true,
"example": "Get detailed insights into your business performance",
"minChars": 10,
"maxChars": 250
}
},
"mediaRules": {
"imageSrc": {
"required": true,
"example": "/feature.jpg",
"note": "Supports external URLs with unoptimized prop"
},
"imageAlt": {
"required": false,
"example": "Feature background",
"note": "Empty string marks image as decorative (aria-hidden)"
}
}
},
"propsSchema": {
"features": "Array<{ id: string, title: string, description: string, imageSrc: string, imageAlt?: string }>",
"carouselMode?": "'auto' | 'buttons' (default: 'buttons')",
"gridVariant": "'uniform-all-items-equal' | 'bento-grid' | 'bento-grid-inverted' | 'two-columns-alternating-heights' | 'asymmetric-60-wide-40-narrow' | 'three-columns-all-equal-width' | 'four-items-2x2-equal-grid' | 'one-large-right-three-stacked-left' | 'items-top-row-full-width-bottom' | 'full-width-top-items-bottom-row' | 'one-large-left-three-stacked-right' | 'timeline' (required)",
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' (required - controls GSAP scroll animations with stagger effect)",
"uniformGridCustomHeightClasses?": "string",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
"ariaLabel?": "string (default: 'Feature section')",
"className?": "string",
"useInvertedBackground": "'noInvert' | 'invertDefault'"
},
"usageExample": "<FeatureCardThree features={[{ id: '01', title: 'Analytics', description: 'Track performance with detailed insights', imageSrc: '/feature.jpg' }]} title=\"Our Features\" description=\"Discover what makes us different\" textboxLayout=\"default\" animationType=\"slide-up\" useInvertedBackground={\"noInvert\"} />",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Requires features[]",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,98 @@
{
"name": "FeatureCardTwelve",
"description": "List-based feature section with large label on left and content with bullet points on right.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Choose Your Plan",
"minChars": 2,
"maxChars": 50
},
"description": {
"required": true,
"example": "Find the perfect fit for your needs",
"minChars": 5,
"maxChars": 300
},
"tag": {
"required": false,
"example": "Plans",
"minChars": 2,
"maxChars": 30
}
},
"featureRules": {
"id": {
"required": true,
"example": "premium",
"note": "Unique identifier for the feature"
},
"label": {
"required": true,
"example": "Premium",
"minChars": 2,
"maxChars": 30,
"note": "Large display label shown on left side (5xl mobile, 6xl desktop)"
},
"title": {
"required": true,
"example": "Premium features for your most demanding needs",
"minChars": 10,
"maxChars": 120,
"note": "Feature heading shown at xl (mobile) / 3xl (desktop)"
},
"items": {
"required": true,
"minItems": 1,
"maxItems": 8,
"structure": "string[]",
"note": "Inline bullet list with accent-colored dots. Each item should be 5-50 characters."
},
"buttons": {
"required": false,
"maxButtons": 2,
"structure": "Array<{text: string, onClick?: () => void, href?: string}>",
"note": "Optional buttons at bottom of content area. First button is primary, second is secondary."
}
},
"itemRules": {
"minItems": 1,
"maxItems": 8,
"recommendedItems": "2-5",
"note": "Works best with 2-5 features for clear comparison"
}
},
"propsSchema": {
"features": "Array<{ id: string, label: string, title: string, items: string[], buttons?: Array<{text: string, onClick?: () => void, href?: string}> }>",
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' (required)",
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"ariaLabel?": "string (default: 'Feature section')",
"className?": "string"
},
"usageExample": "<FeatureCardTwelve features={[{ id: 'premium', label: 'Premium', title: 'Premium features for your most demanding needs and growth goals', items: ['Priority support', 'Advanced features', 'Custom integrations'], buttons: [{ text: 'Learn more', href: '#' }, { text: 'Get started', onClick: () => console.log('clicked') }] }]} animationType=\"opacity\" title=\"Choose Your Plan\" description=\"Find the perfect fit for your needs\" textboxLayout=\"default\" useInvertedBackground={\"noInvert\"} />",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Use for pricing pages",
"Use for subscription tiers",
"Requires features[]",
"Requires titleSegments?[]",
"Requires buttons?[]"
],
"dont": [
"Do not use more than 8 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,86 @@
{
"name": "FeatureCardTwentyOne",
"description": "Split layout with media on one side and TextBox with accordion items on the other.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Custom designs",
"minChars": 2,
"maxChars": 60
},
"description": {
"required": true,
"example": "Explore our range of customizable solutions designed to meet your unique needs.",
"minChars": 10,
"maxChars": 300
},
"tag": {
"required": false,
"example": "Features",
"minChars": 2,
"maxChars": 30
}
},
"accordionRules": {
"id": {
"required": true,
"example": "1",
"note": "Unique identifier for each accordion item"
},
"title": {
"required": true,
"example": "Inspiration + innovation",
"minChars": 2,
"maxChars": 60,
"note": "Accordion header text"
},
"content": {
"required": true,
"example": "From custom colourways to bespoke elements built from the ground up.",
"minChars": 10,
"maxChars": 500,
"note": "Accordion expanded content (supports HTML)"
}
},
"itemRules": {
"minItems": 2,
"maxItems": 6,
"recommendedItems": 3
}
},
"propsSchema": {
"title": "string",
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"accordionItems": "Array<{ id: string, title: string, content: string }>",
"imageSrc?": "string (either imageSrc or videoSrc required)",
"imageAlt?": "string",
"videoSrc?": "string (either imageSrc or videoSrc required)",
"videoAriaLabel?": "string",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"mediaPosition?": "'left' | 'right' (default: 'left')",
"ariaLabel?": "string (default: 'Feature section')",
"className?": "string"
},
"usageExample": "<FeatureCardTwentyOne title=\"Custom designs\" description=\"Explore our range of customizable solutions.\" tag=\"Features\" imageSrc=\"/images/feature.webp\" imageAlt=\"Feature showcase\" accordionItems={[{ id: '1', title: 'Inspiration + innovation', content: 'Collaborate with us on custom designs.' }, { id: '2', title: 'Sustainability + us', content: 'Committed to sustainable practices.' }, { id: '3', title: 'Request samples', content: 'Get in touch for samples and pricing.' }]} buttons={[{ text: 'Learn more', href: '#' }]} useInvertedBackground=\"noInvert\" mediaPosition=\"left\" />",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Requires titleSegments?[]",
"Requires buttons?[]",
"Requires accordionItems[]"
],
"dont": [
"Do not use less than 2 items",
"Do not use more than 6 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,67 @@
{
"name": "FeatureProcessSteps",
"description": "Split-layout feature section with text on left and numbered process steps with timeline on right.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Getting you results without the complexity",
"minChars": 10,
"maxChars": 100
},
"description": {
"required": true,
"example": "Our three-step process takes you from identifying opportunities to launching systems, with clear communication and support at every stage.",
"minChars": 20,
"maxChars": 300
},
"tag": {
"required": false,
"example": "How we work",
"minChars": 2,
"maxChars": 30
}
},
"stepsRules": {
"minSteps": 2,
"recommendedSteps": 3,
"maxSteps": 6,
"structure": {
"number": "string - Step number to display (required, e.g., '01', '02', '1', '2')",
"title": "string - Step title (required, e.g., 'Discovery & Assessment')",
"description": "string - Step description (required)",
"tag": "string - Optional tag/badge for the step (e.g., 'Week 1', 'Ongoing')"
},
"note": "Minimum 2 steps required, but 3+ steps recommended for optimal visual balance. Each step shows a numbered card with a connecting timeline line."
}
},
"propsSchema": {
"title": "string",
"description": "string",
"steps": "Array<{ number: string, title: string, description: string, tag?: string }>",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "ButtonConfig[]",
"ariaLabel?": "string (default: 'Process steps section')",
"className?": "string"
},
"usageExample": "// Wrap in ThemeProvider\nimport { Sparkles } from 'lucide-react';\n\n<ThemeProvider defaultButtonVariant=\"text-stagger\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"rounded\" cardStyle=\"solid\" primaryButtonStyle=\"gradient\" secondaryButtonStyle=\"glass\">\n <FeatureProcessSteps\n tag=\"How we work\"\n tagIcon={Sparkles}\n title=\"Getting you results without the complexity\"\n description=\"Our three-step process takes you from identifying opportunities to launching systems.\"\n buttons={[{ text: 'Book a call', href: '#' }, { text: 'Watch video', href: '#' }]}\n steps={[\n { number: '01', title: 'Discovery & Assessment', tag: 'Week 1', description: 'We analyze your workflows and identify opportunities.' },\n { number: '02', title: 'Build & Deploy', tag: 'Weeks 2-4', description: 'We create and launch custom systems tailored to your operations.' },\n { number: '03', title: 'Train & Support', tag: 'Ongoing', description: 'We train your team and provide ongoing support.' }\n ]}\n useInvertedBackground=\"noInvert\"\n />\n</ThemeProvider>",
"do": [
"Use for process flows",
"Use for roadmaps",
"Use for step-by-step explanation",
"Use for feature showcases",
"Use for capability displays",
"Requires steps[]"
],
"dont": [
"Do not use non-sequential content",
"Do not use single item"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,19 @@
{
"name": "FloatingGradientBackground",
"description": "Five animated gradient circles with CSS animations and vertical gradient mask.",
"constraints": {},
"propsSchema": {
"className?": "string"
},
"usageExample": "<FloatingGradientBackground />",
"do": [
"Use for feature showcases",
"Use for capability displays"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,19 @@
{
"name": "FluidBackground",
"description": "Generative fluid patterns using CPPN shader with theme color integration.",
"constraints": {},
"propsSchema": {
"className?": "string"
},
"usageExample": "<FluidBackground />",
"do": [
"Use for feature showcases",
"Use for capability displays"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,71 @@
{
"name": "FooterBase",
"description": "Classic footer with logo, multi-column navigation, copyright text, and privacy policy link.",
"constraints": {
"textRules": {
"logoText": {
"required": false,
"default": "Webild",
"example": "Company Name",
"minChars": 2,
"maxChars": 30
},
"copyrightText": {
"required": false,
"default": "© 2025 | Webild",
"example": "© 2025 Company Name",
"minChars": 5,
"maxChars": 50
},
"columnTitle": {
"required": true,
"example": "Product",
"minChars": 2,
"maxChars": 20
},
"itemLabel": {
"required": true,
"example": "Features",
"minChars": 2,
"maxChars": 30
}
},
"structureRules": {
"columns": {
"required": true,
"minColumns": 1,
"maxColumns": 3,
"note": "Each column must have title and items array"
},
"items": {
"required": true,
"minItems": 1,
"structure": {
"label": "string - Link text (required)",
"href": "string - Link destination (optional). External URLs (https://, http://, www.) open in new tab. Internal values (e.g., 'about', 'contact') scroll to #about, #contact sections",
"onClick": "() => void - Additional click handler (optional)"
}
}
}
},
"propsSchema": {
"columns": "Array<{ title: string, items: Array<{ label: string, href: string }> }> - Footer navigation columns (required)",
"logoText?": "string (default: 'Webild')",
"copyrightText?": "string (default: '© 2025 | Webild')",
"onPrivacyClick?": "() => void",
"ariaLabel?": "string (default: 'Site footer')",
"className?": "string"
},
"usageExample": "<FooterBase columns={[{ title: 'Product', items: [{ label: 'Features', href: 'features' }, { label: 'Pricing', href: 'pricing' }] }]} copyrightText=\"© 2025 | Company\" onPrivacyClick={() => console.log('Privacy clicked')} />",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Requires columns[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,54 @@
{
"name": "FooterBaseCard",
"description": "Card-wrapped footer with logo, navigation columns, copyright, and privacy policy link.",
"constraints": {
"textRules": {
"copyrightText": {
"required": false,
"example": "© 2025 | Webild",
"minChars": 5,
"maxChars": 100,
"note": "Copyright text displayed at bottom left"
},
"logoText": {
"required": false,
"example": "Webild",
"minChars": 2,
"maxChars": 30,
"note": "Text used for h2 heading"
}
},
"columnsRules": {
"required": true,
"structure": {
"title": "string - Column heading (required)",
"items": "Array<{ label: string, href: string }> - Navigation links (required)"
},
"minColumns": 1,
"maxColumns": 5,
"note": "Array of footer column objects. Each column must have title and items array."
},
"logoRules": {
"note": "Uses logoText as h2 heading."
}
},
"propsSchema": {
"logoText?": "string (default: 'Webild')",
"columns": "Array<{ title: string, items: Array<{ label: string, href: string }> }> - Footer navigation columns (required)",
"copyrightText?": "string (default: '© 2025 | Webild')",
"onPrivacyClick?": "() => void",
"ariaLabel?": "string (default: 'Site footer')",
"className?": "string"
},
"usageExample": "<FooterBaseCard columns={[{ title: 'Product', items: [{ label: 'Features', href: '/features' }, { label: 'Pricing', href: '/pricing' }] }, { title: 'Company', items: [{ label: 'About', href: '/about' }, { label: 'Blog', href: '/blog' }] }]} logoText=\"Webild\" copyrightText=\"© 2025 | Webild\" onPrivacyClick={() => console.log('Privacy clicked')} />",
"do": [
"Use for general use",
"Requires columns[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,62 @@
{
"name": "FooterBaseReveal",
"description": "Animated footer reveal wrapper that creates a fixed footer with scroll-triggered reveal effect.",
"constraints": {
"textRules": {
"copyrightText": {
"required": false,
"default": "© 2025 | Webild",
"example": "© 2025 Company Name",
"minChars": 5,
"maxChars": 50
},
"columnTitle": {
"required": true,
"example": "Product",
"minChars": 2,
"maxChars": 20
},
"itemLabel": {
"required": true,
"example": "Features",
"minChars": 2,
"maxChars": 30
}
},
"structureRules": {
"columns": {
"required": true,
"minColumns": 1,
"maxColumns": 3,
"note": "Each column must have title and items array"
},
"items": {
"required": true,
"minItems": 1,
"structure": {
"label": "string - Link text (required)",
"href": "string - Link destination (optional). External URLs open in new tab, internal values scroll to sections",
"onClick": "() => void - Additional click handler (optional)"
}
}
}
},
"propsSchema": {
"columns": "Array<{ title: string, items: Array<{ label: string, href: string }> }> - Footer navigation columns (required)",
"copyrightText?": "string",
"onPrivacyClick?": "() => void",
"ariaLabel?": "string",
"className?": "string"
},
"usageExample": "<FooterBaseReveal columns={[{ title: 'Product', items: [{ label: 'Features', href: 'features' }, { label: 'Pricing', href: 'pricing' }] }]} copyrightText=\"© 2025 | Company\" />",
"do": [
"Use for general use",
"Requires columns[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,53 @@
{
"name": "FooterCard",
"description": "Minimalist footer with card wrapper containing logo, divider, copyright, and optional social links.",
"constraints": {
"textRules": {
"copyrightText": {
"required": false,
"example": "© 2025 | Webild",
"minChars": 5,
"maxChars": 100,
"note": "Copyright text displayed at bottom left"
},
"logoText": {
"required": false,
"example": "Webild",
"minChars": 2,
"maxChars": 30,
"note": "Text used for SVG logo"
}
},
"socialLinksRules": {
"required": false,
"structure": {
"icon": "LucideIcon - Icon component (required)",
"href": "string - Social profile URL (required)",
"ariaLabel": "string - Accessibility label (required)"
},
"note": "Optional array of social links. Only renders if provided and has length > 0."
},
"logoRules": {
"note": "Uses logoText for SVG text logo via FooterLogo component."
}
},
"propsSchema": {
"logoText?": "string (default: 'Webild')",
"copyrightText?": "string (default: '© 2025 | Webild')",
"socialLinks?": "Array<{ icon: LucideIcon, href: string, ariaLabel: string }> - Social media links",
"ariaLabel?": "string (default: 'Site footer')",
"className?": "string",
"logoLineHeight?": "number (default: 1.1)"
},
"usageExample": "<FooterCard logoText=\"Webild\" copyrightText=\"© 2025 | Webild\" socialLinks={[{ icon: Twitter, href: 'https://twitter.com/webild', ariaLabel: 'Twitter' }, { icon: Linkedin, href: 'https://linkedin.com/company/webild', ariaLabel: 'LinkedIn' }]} />",
"do": [
"Use for general use",
"Requires socialLinks?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,61 @@
{
"name": "FooterLogoEmphasis",
"description": "Footer with prominent centered logo emphasis and grid-based navigation layout with chevron icons.",
"constraints": {
"textRules": {
"logoText": {
"required": false,
"default": "Webild",
"example": "Company Name",
"minChars": 2,
"maxChars": 30
},
"itemLabel": {
"required": true,
"example": "Features",
"minChars": 2,
"maxChars": 30
}
},
"structureRules": {
"columns": {
"required": true,
"minColumns": 1,
"maxColumns": 5,
"note": "Grid automatically adjusts from 1-5 columns based on array length"
},
"items": {
"required": true,
"minItems": 1,
"structure": {
"label": "string - Link text (required)",
"href": "string - Link destination (optional). External URLs open in new tab, internal values scroll to sections",
"onClick": "() => void - Additional click handler (optional)"
}
},
"logo": {
"note": "Uses logoText for SVG text logo"
}
}
},
"propsSchema": {
"columns": "Array<{ items: Array<{ label: string, href?: string, onClick?: () => void }> }> - Footer navigation columns (required, max 5)",
"logoText?": "string (default: 'Webild')",
"ariaLabel?": "string (default: 'Site footer')",
"className?": "string"
},
"usageExample": "<FooterLogoEmphasis columns={[{ items: [{ label: 'Features', href: 'features' }] }, { items: [{ label: 'About', href: 'about' }] }]} logoText=\"Company\" />",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Requires columns[]"
],
"dont": [
"Do not use more than 4 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,37 @@
{
"name": "FooterLogoReveal",
"description": "Minimalist footer with logo that reveals on scroll using fixed positioning and clip-path.",
"constraints": {
"textRules": {
"logoText": {
"required": false,
"example": "Webild",
"minChars": 2,
"maxChars": 30,
"note": "Text used for SVG logo"
}
},
"logoRules": {
"note": "Uses logoText for SVG text logo via FooterLogo component."
},
"revealEffectRules": {
"note": "Component uses fixed positioning and clip-path for scroll reveal effect. Requires page content above footer to trigger scroll. ResizeObserver dynamically updates footer height for responsive reveal."
}
},
"propsSchema": {
"logoText?": "string (default: 'Webild')",
"logoLineHeight?": "number (default: 1.1)",
"ariaLabel?": "string (default: 'Site footer')",
"className?": "string"
},
"usageExample": "<FooterLogoReveal logoText=\"Webild\" />",
"do": [
"Use for general use"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,86 @@
{
"name": "FooterMedia",
"description": "Footer with full-width media (image/video) above classic navigation layout.",
"constraints": {
"textRules": {
"logoText": {
"required": false,
"default": "Webild",
"example": "Company Name",
"minChars": 2,
"maxChars": 30
},
"copyrightText": {
"required": false,
"default": "© 2025 | Webild",
"example": "© 2025 Company Name",
"minChars": 5,
"maxChars": 50
},
"columnTitle": {
"required": true,
"example": "Product",
"minChars": 2,
"maxChars": 20
},
"itemLabel": {
"required": true,
"example": "Features",
"minChars": 2,
"maxChars": 30
}
},
"mediaRules": {
"note": "Either imageSrc or videoSrc is required (discriminated union)",
"imageSrc": {
"required": "conditional - required if no videoSrc",
"example": "https://images.unsplash.com/photo-1497215728101-856f4ea42174?w=1920"
},
"videoSrc": {
"required": "conditional - required if no imageSrc",
"example": "/videos/footer-background.mp4"
}
},
"structureRules": {
"columns": {
"required": true,
"minColumns": 1,
"maxColumns": 3,
"note": "Each column must have title and items array"
},
"items": {
"required": true,
"minItems": 1,
"structure": {
"label": "string - Link text (required)",
"href": "string - Link destination (optional)",
"onClick": "() => void - Additional click handler (optional)"
}
}
}
},
"propsSchema": {
"imageSrc": "string (required if no videoSrc)",
"imageAlt?": "string (default: '')",
"videoSrc": "string (required if no imageSrc)",
"videoAriaLabel?": "string (default: 'Footer video')",
"columns": "Array<{ title: string, items: Array<{ label: string, href: string }> }> - Footer navigation columns (required)",
"logoText?": "string (default: 'Webild')",
"copyrightText?": "string (default: '© 2025 | Webild')",
"onPrivacyClick?": "() => void",
"ariaLabel?": "string (default: 'Site footer')",
"className?": "string"
},
"usageExample": "<FooterMedia imageSrc=\"https://images.unsplash.com/photo-1497215728101-856f4ea42174?w=1920\" columns={[{ title: 'Product', items: [{ label: 'Features', href: 'features' }, { label: 'Pricing', href: 'pricing' }] }]} copyrightText=\"© 2025 | Company\" />",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Requires columns[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,68 @@
{
"name": "FooterSimple",
"description": "Minimal footer with navigation columns, divider, and bottom text row.",
"constraints": {
"textRules": {
"bottomLeftText": {
"required": true,
"example": "© 2025 Company. All rights reserved.",
"minChars": 5,
"maxChars": 60
},
"bottomRightText": {
"required": true,
"example": "Made with Webild",
"minChars": 2,
"maxChars": 50
},
"columnTitle": {
"required": true,
"example": "Navigate",
"minChars": 2,
"maxChars": 20
},
"itemLabel": {
"required": true,
"example": "Home",
"minChars": 2,
"maxChars": 30
}
},
"structureRules": {
"columns": {
"required": true,
"minColumns": 2,
"maxColumns": 5,
"note": "Each column must have title and items array. Columns spread evenly across width."
},
"items": {
"required": true,
"minItems": 1,
"structure": {
"label": "string - Link text (required)",
"href": "string - Link destination (optional)",
"onClick": "() => void - Click handler (optional)"
}
}
}
},
"propsSchema": {
"columns": "Array<{ title: string, items: Array<{ label: string, href?: string, onClick?: () => void }> }>",
"bottomLeftText": "string",
"bottomRightText": "string",
"ariaLabel?": "string (default: 'Site footer')",
"className?": "string"
},
"usageExample": "<FooterSimple columns={[{ title: 'Navigate', items: [{ label: 'Home', href: '#' }, { label: 'About', href: '#' }] }, { title: 'Resources', items: [{ label: 'Blog', href: '#' }, { label: 'FAQ', href: '#' }] }, { title: 'Legal', items: [{ label: 'Privacy', href: '#' }, { label: 'Terms', href: '#' }] }]} bottomLeftText=\"© 2025 Company. All rights reserved.\" bottomRightText=\"Made with Webild\" />",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Requires columns[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,26 @@
{
"name": "GradientBarsBackground",
"description": "Vertical gradient bars with dynamic height distribution creating a wave-like pattern.",
"constraints": {},
"propsSchema": {
"className?": "string",
"numBarsPerSide?": "number (default: 8)",
"gradientFrom?": "string (default: 'var(--color-primary-cta)')",
"gradientTo?": "string (default: 'transparent')",
"opacity?": "number (default: 0.075)",
"sideWidth?": "string (default: '35%')"
},
"usageExample": "<GradientBarsBackground numBarsPerSide={8} gradientFrom=\"var(--color-primary-cta)\" gradientTo=\"transparent\" opacity={0.075} sideWidth=\"35%\" />",
"do": [
"Use for feature showcases",
"Use for capability displays",
"Use for statistics displays",
"Use for achievement showcases"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,23 @@
{
"name": "GridBackround",
"description": "Grid pattern background with line-based grid and optional 3D perspective effect.",
"constraints": {},
"propsSchema": {
"size?": "'small' | 'medium' | 'large' (default: 'medium')",
"perspectiveThreeD?": "boolean (default: false)",
"className?": "string"
},
"usageExample": "<GridBackround size=\"medium\" perspectiveThreeD={false} />",
"do": [
"Use for feature showcases",
"Use for capability displays"
],
"dont": [
"Do not use more than 4 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,86 @@
{
"name": "HeroBillboard",
"description": "Full-width hero section with centered text content, optional tag, buttons, and single image/video below in a card frame.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Welcome to Our Platform",
"minChars": 2,
"maxChars": 40
},
"description": {
"required": true,
"example": "Create beautiful, responsive web experiences",
"minChars": 5,
"maxChars": 200
},
"tag": {
"required": false,
"example": "New Release",
"minChars": 2,
"maxChars": 30
}
},
"mediaRules": {
"imageSrc": {
"required": false,
"example": "/hero-image.jpg",
"note": "Supports external URLs with unoptimized prop"
},
"videoSrc": {
"required": false,
"example": "/hero-video.mp4",
"note": "Takes precedence over imageSrc if both provided"
},
"imageAlt": {
"required": false,
"example": "Hero background",
"note": "Empty string marks image as decorative (aria-hidden)"
}
},
"buttonRules": {
"maxButtons": 2,
"structure": {
"text": "string - Button label (required)",
"href": "string - Link destination (optional). External URLs (https://, http://, www.) open in new tab. Internal values (e.g., 'about', 'contact') scroll to #about, #contact sections",
"onClick": "() => void - Additional click handler (optional)",
"props": "Partial<ButtonPropsForVariant> - Additional button props like className, textClassName (optional)"
},
"examples": [
"{ text: 'Get Started', href: 'https://example.com' }",
"{ text: 'Learn More', href: 'about' }"
],
"note": "Button variant is controlled by ThemeProvider's defaultButtonVariant. Border radius is controlled by ThemeProvider's borderRadius (options: 'sharp', 'rounded', 'soft', 'pill'). All sections should be wrapped in a single ThemeProvider at the app/page level to maintain consistent styling across the entire site."
}
},
"propsSchema": {
"title": "string",
"description": "string",
"background": "{ variant: 'plain' | 'animated-grid' | 'canvas-reveal' | 'cell-wave' | 'downward-rays-animated' | 'downward-rays-animated-grid' | 'downward-rays-static' | 'downward-rays-static-grid' | 'gradient-bars' | 'radial-gradient' | 'rotated-rays-animated' | 'rotated-rays-animated-grid' | 'rotated-rays-static' | 'rotated-rays-static-grid' | 'sparkles-gradient' } (required)",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"imageSrc?": "string",
"videoSrc?": "string",
"imageAlt?": "string (default: '')",
"videoAriaLabel?": "string (default: 'Hero video')",
"ariaLabel?": "string (default: 'Hero section')",
"className?": "string"
},
"usageExample": "<ThemeProvider defaultButtonVariant=\"text-stagger\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"rounded\">\n <HeroBillboard \n title=\"Welcome to Our Platform\" \n description=\"Create beautiful, responsive web experiences\" \n tag=\"New Release\" \n imageSrc=\"/hero.jpg\" \n imageAlt=\"Hero banner\"\n buttons={[{ text: 'Get Started', href: 'https://example.com' }, { text: 'Learn More', href: 'about' }]} \n />\n</ThemeProvider>",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays",
"Requires buttons?[]"
],
"dont": [
"Do not use multiple items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,76 @@
{
"name": "HeroBillboardCarousel",
"description": "Full-width hero section with centered text and 5+ auto-scrolling images in carousel layout.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Our Portfolio",
"minChars": 2,
"maxChars": 40
},
"description": {
"required": true,
"example": "Browse through our collection of projects",
"minChars": 5,
"maxChars": 200
},
"tag": {
"required": false,
"example": "Portfolio",
"minChars": 2,
"maxChars": 30
}
},
"mediaRules": {
"mediaItems": {
"required": true,
"example": "[{ imageSrc: '/img1.jpg', imageAlt: 'Product 1' }, { imageSrc: '/img2.jpg', imageAlt: 'Product 2' }, { imageSrc: '/img3.jpg', imageAlt: 'Product 3' }, { imageSrc: '/img4.jpg', imageAlt: 'Product 4' }, { imageSrc: '/img5.jpg', imageAlt: 'Product 5' }]",
"note": "Array of 5+ MediaItem objects. Each item can have imageSrc, videoSrc, imageAlt, videoAriaLabel. Requires minimum 5 images."
}
},
"buttonRules": {
"maxButtons": 2,
"structure": {
"text": "string - Button label (required)",
"href": "string - Link destination (optional). External URLs (https://, http://, www.) open in new tab. Internal values (e.g., 'about', 'contact') scroll to #about, #contact sections",
"onClick": "() => void - Additional click handler (optional)",
"props": "Partial<ButtonPropsForVariant> - Additional button props like className, textClassName (optional)"
},
"examples": [
"{ text: 'View Portfolio', href: 'https://example.com' }",
"{ text: 'Contact Us', href: 'contact' }"
],
"note": "Button variant is controlled by ThemeProvider's defaultButtonVariant. Border radius is controlled by ThemeProvider's borderRadius (options: 'sharp', 'rounded', 'soft', 'pill'). All sections should be wrapped in a single ThemeProvider at the app/page level to maintain consistent styling across the entire site."
}
},
"propsSchema": {
"title": "string",
"description": "string",
"background": "{ variant: 'plain' | 'animated-grid' | 'canvas-reveal' | 'cell-wave' | 'downward-rays-animated' | 'downward-rays-animated-grid' | 'downward-rays-static' | 'downward-rays-static-grid' | 'gradient-bars' | 'radial-gradient' | 'rotated-rays-animated' | 'rotated-rays-animated-grid' | 'rotated-rays-static' | 'rotated-rays-static-grid' | 'sparkles-gradient' } (required)",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"mediaItems": "Array<{ imageSrc?: string, videoSrc?: string, imageAlt?: string, videoAriaLabel?: string }> - Each item requires either imageSrc or videoSrc",
"ariaLabel?": "string (default: 'Hero section')",
"className?": "string"
},
"usageExample": "<ThemeProvider defaultButtonVariant=\"text-stagger\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"rounded\">\n <HeroBillboardCarousel \n title=\"Our Portfolio\" \n description=\"Browse through our collection of projects\" \n tag=\"Portfolio\" \n mediaItems={[\n { imageSrc: '/img1.jpg', imageAlt: 'Product 1' },\n { imageSrc: '/img2.jpg', imageAlt: 'Product 2' },\n { imageSrc: '/img3.jpg', imageAlt: 'Product 3' },\n { imageSrc: '/img4.jpg', imageAlt: 'Product 4' },\n { imageSrc: '/img5.jpg', imageAlt: 'Product 5' },\n { imageSrc: '/img6.jpg', imageAlt: 'Product 6' },\n { imageSrc: '/img7.jpg', imageAlt: 'Product 7' }\n ]}\n buttons={[{ text: 'View Portfolio', href: 'https://example.com' }, { text: 'Contact Us', href: 'contact' }]} \n />\n</ThemeProvider>",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays",
"Use for portfolios",
"Use for image galleries",
"Requires buttons?[]",
"Requires mediaItems[]"
],
"dont": [
"Do not use less than 5 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,76 @@
{
"name": "HeroBillboardGallery",
"description": "Full-width hero section with centered text and 3-5 overlapping rotated images in gallery layout.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Explore Our Collection",
"minChars": 2,
"maxChars": 40
},
"description": {
"required": true,
"example": "Discover amazing products and experiences",
"minChars": 5,
"maxChars": 200
},
"tag": {
"required": false,
"example": "Featured",
"minChars": 2,
"maxChars": 30
}
},
"mediaRules": {
"mediaItems": {
"required": true,
"example": "[{ imageSrc: '/img1.jpg', imageAlt: 'Gallery 1' }, { imageSrc: '/img2.jpg', imageAlt: 'Gallery 2' }, { imageSrc: '/img3.jpg', imageAlt: 'Gallery 3' }]",
"note": "Array of 3-5 MediaItem objects. Each item can have imageSrc, videoSrc, imageAlt, videoAriaLabel. Supports 3-5 images maximum."
}
},
"buttonRules": {
"maxButtons": 2,
"structure": {
"text": "string - Button label (required)",
"href": "string - Link destination (optional). External URLs (https://, http://, www.) open in new tab. Internal values (e.g., 'about', 'contact') scroll to #about, #contact sections",
"onClick": "() => void - Additional click handler (optional)",
"props": "Partial<ButtonPropsForVariant> - Additional button props like className, textClassName (optional)"
},
"examples": [
"{ text: 'View Gallery', href: 'https://example.com' }",
"{ text: 'Learn More', href: 'about' }"
],
"note": "Button variant is controlled by ThemeProvider's defaultButtonVariant. Border radius is controlled by ThemeProvider's borderRadius (options: 'sharp', 'rounded', 'soft', 'pill'). All sections should be wrapped in a single ThemeProvider at the app/page level to maintain consistent styling across the entire site."
}
},
"propsSchema": {
"title": "string",
"description": "string",
"background": "{ variant: 'plain' | 'animated-grid' | 'canvas-reveal' | 'cell-wave' | 'downward-rays-animated' | 'downward-rays-animated-grid' | 'downward-rays-static' | 'downward-rays-static-grid' | 'gradient-bars' | 'radial-gradient' | 'rotated-rays-animated' | 'rotated-rays-animated-grid' | 'rotated-rays-static' | 'rotated-rays-static-grid' | 'sparkles-gradient' } (required)",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"mediaItems": "Array<{ imageSrc?: string, videoSrc?: string, imageAlt?: string, videoAriaLabel?: string }> - Each item requires either imageSrc or videoSrc",
"ariaLabel?": "string (default: 'Hero section')",
"className?": "string"
},
"usageExample": "<ThemeProvider defaultButtonVariant=\"text-stagger\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"rounded\">\n <HeroBillboardGallery \n title=\"Explore Our Collection\" \n description=\"Discover amazing products and experiences\" \n tag=\"Featured\" \n mediaItems={[\n { imageSrc: '/img1.jpg', imageAlt: 'Gallery 1' },\n { imageSrc: '/img2.jpg', imageAlt: 'Gallery 2' },\n { imageSrc: '/img3.jpg', imageAlt: 'Gallery 3' },\n { imageSrc: '/img4.jpg', imageAlt: 'Gallery 4' },\n { imageSrc: '/img5.jpg', imageAlt: 'Gallery 5' }\n ]}\n buttons={[{ text: 'View Gallery', href: 'https://example.com' }, { text: 'Learn More', href: 'about' }]} \n />\n</ThemeProvider>",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays",
"Use for portfolios",
"Use for image galleries",
"Requires buttons?[]",
"Requires mediaItems[]"
],
"dont": [
"Do not use less than 3 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,81 @@
{
"name": "HeroBillboardRotatedCarousel",
"description": "Hero section with centered text content and angled/rotated carousel below. Features auto-playing carousel with scaled and rotated side cards.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Transform Your Workflow",
"minChars": 2,
"maxChars": 60
},
"description": {
"required": true,
"example": "Experience the power of seamless collaboration and productivity tools designed for modern teams",
"minChars": 5,
"maxChars": 200
},
"tag": {
"required": false,
"example": "New Release",
"minChars": 2,
"maxChars": 30
}
},
"buttonRules": {
"maxButtons": 2,
"structure": {
"text": "string - Button label (required)",
"href": "string - Link destination (optional)",
"onClick": "() => void - Click handler (optional)",
"props": "Partial<ButtonPropsForVariant> - Additional button props (optional)"
},
"note": "Button variant controlled by ThemeProvider's defaultButtonVariant. All sections should be wrapped in a single ThemeProvider at the app/page level."
},
"carouselItemRules": {
"required": true,
"minItems": 6,
"structure": {
"id": "string - Unique identifier (required)",
"imageSrc": "string - Image URL (optional)",
"videoSrc": "string - Video URL (optional, takes precedence over imageSrc)",
"imageAlt": "string - Alt text for image (optional)",
"videoAriaLabel": "string - ARIA label for video (optional)"
},
"note": "Minimum 6 items required to prevent duplicate keys. Carousel displays 5 positions simultaneously (-2, -1, 0, 1, 2). Each item should have either imageSrc or videoSrc. Uses MediaContent component for rendering."
}
},
"propsSchema": {
"title": "string",
"description": "string",
"background": "{ variant: 'plain' | 'animated-grid' | 'canvas-reveal' | 'cell-wave' | 'downward-rays-animated' | 'downward-rays-animated-grid' | 'downward-rays-static' | 'downward-rays-static-grid' | 'gradient-bars' | 'radial-gradient' | 'rotated-rays-animated' | 'rotated-rays-animated-grid' | 'rotated-rays-static' | 'rotated-rays-static-grid' | 'sparkles-gradient' } (required)",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"carouselItems": "Array<{ id: string, imageSrc?: string, videoSrc?: string, imageAlt?: string, videoAriaLabel?: string }> - Carousel items (minimum 6 items)",
"autoPlay?": "boolean (default: true)",
"autoPlayInterval?": "number (default: 4000)",
"ariaLabel?": "string (default: 'Hero section')",
"className?": "string"
},
"usageExample": "<ThemeProvider defaultButtonVariant=\"hover-bubble\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"pill\">\n <HeroBillboardRotatedCarousel \n title=\"Transform Your Workflow\" \n description=\"Experience seamless collaboration and productivity\" \n tag=\"New Release\" \n tagIcon={Sparkles}\n buttons={[{ text: 'Get Started' }, { text: 'Learn More' }]}\n carouselItems={[\n { id: '1', imageSrc: '/image1.jpg', imageAlt: 'Product 1' },\n { id: '2', imageSrc: '/image2.jpg', imageAlt: 'Product 2' },\n { id: '3', imageSrc: '/image3.jpg', imageAlt: 'Product 3' },\n { id: '4', imageSrc: '/image4.jpg', imageAlt: 'Product 4' },\n { id: '5', imageSrc: '/image5.jpg', imageAlt: 'Product 5' },\n { id: '6', imageSrc: '/image6.jpg', imageAlt: 'Product 6' }\n ]}\n autoPlay={true}\n autoPlayInterval={4000}\n />\n</ThemeProvider>",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays",
"Use for portfolios",
"Use for image galleries",
"Use for product catalogs",
"Use for e-commerce",
"Requires buttons?[]",
"Requires carouselItems[]"
],
"dont": [
"Do not use less than 6 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,101 @@
{
"name": "HeroBillboardScroll",
"description": "Full-screen hero section with centered text and media card that animates with 3D perspective transforms on scroll (desktop only).",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Scroll Animations",
"minChars": 2,
"maxChars": 60
},
"description": {
"required": true,
"example": "Experience smooth, performant animations as you scroll through your content",
"minChars": 5,
"maxChars": 200
},
"tag": {
"required": false,
"example": "Unleash the Power",
"minChars": 2,
"maxChars": 30
}
},
"mediaRules": {
"imageSrc": {
"required": false,
"example": "/dashboard.jpg",
"note": "Image to display in the animated card. Supports external URLs with unoptimized prop"
},
"videoSrc": {
"required": false,
"example": "/demo.mp4",
"note": "Video to display in the animated card. Takes precedence over imageSrc if both provided"
},
"imageAlt": {
"required": false,
"example": "Dashboard preview",
"note": "Empty string marks image as decorative (aria-hidden)"
},
"animationBehavior": {
"desktop": {
"rotateX": "Animates from 20deg to 0deg based on scroll progress",
"scale": "Animates from 1.05 to 1 based on scroll progress",
"height": "h-[75svh] (75% of viewport height)",
"note": "Uses Framer Motion's useScroll and useTransform for smooth scroll-linked animations"
},
"mobile": {
"rotateX": "Static 20deg rotation (no animation)",
"scale": "No scale animation",
"height": "h-[50svh] (50% of viewport height)",
"note": "Separate static div implementation to prevent performance issues and hydration errors"
},
"perspective": "1000px applied to container for 3D effect"
}
},
"buttonRules": {
"maxButtons": 2,
"structure": {
"text": "string - Button label (required)",
"href": "string - Link destination (optional). External URLs (https://, http://, www.) open in new tab. Internal values (e.g., 'about', 'contact') scroll to #about, #contact sections",
"onClick": "() => void - Additional click handler (optional)",
"props": "Partial<ButtonPropsForVariant> - Additional button props like className, textClassName (optional)"
},
"examples": [
"{ text: 'Get Started', onClick: () => console.log('Get Started clicked') }",
"{ text: 'Learn More', href: 'about' }"
],
"note": "Button variant is controlled by ThemeProvider's defaultButtonVariant. Border radius is controlled by ThemeProvider's borderRadius (options: 'sharp', 'rounded', 'soft', 'pill'). All sections should be wrapped in a single ThemeProvider at the app/page level to maintain consistent styling across the entire site."
}
},
"propsSchema": {
"title": "string",
"description": "string",
"background": "{ variant: 'plain' | 'animated-grid' | 'canvas-reveal' | 'cell-wave' | 'downward-rays-animated' | 'downward-rays-animated-grid' | 'downward-rays-static' | 'downward-rays-static-grid' | 'gradient-bars' | 'radial-gradient' | 'rotated-rays-animated' | 'rotated-rays-animated-grid' | 'rotated-rays-static' | 'rotated-rays-static-grid' | 'sparkles-gradient' } (required)",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"imageSrc?": "string",
"videoSrc?": "string",
"imageAlt?": "string (default: '')",
"videoAriaLabel?": "string (default: 'Hero video')",
"ariaLabel?": "string (default: 'Hero section')",
"className?": "string"
},
"usageExample": "<ThemeProvider defaultButtonVariant=\"hover-bubble\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"pill\">\n <HeroBillboardScroll \n title=\"Scroll Animations\" \n description=\"Experience smooth, performant animations as you scroll through your content\" \n tag=\"Unleash the Power\" \n imageSrc=\"/dashboard.jpg\" \n imageAlt=\"Dashboard preview\"\n buttons={[{ text: 'Get Started', onClick: () => console.log('Get Started clicked') }, { text: 'Learn More', href: 'about' }]} \n />\n</ThemeProvider>",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays",
"Use for product catalogs",
"Use for e-commerce",
"Requires buttons?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,78 @@
{
"name": "HeroCarouselLogo",
"description": "Full-screen hero section with auto-playing carousel background, large text logo at bottom that scales to fill container width, description and button row above, with progress bars and linear gradient blur overlay.",
"constraints": {
"textRules": {
"logoText": {
"required": true,
"example": "WEBILD",
"minChars": 2,
"maxChars": 20
},
"description": {
"required": true,
"example": "Create stunning, responsive websites with our comprehensive component library",
"minChars": 5,
"maxChars": 200
}
},
"mediaRules": {
"slides": {
"required": true,
"example": "[{ imageSrc: '/slide1.jpg', imageAlt: 'Slide 1' }, { imageSrc: '/slide2.jpg', imageAlt: 'Slide 2' }]",
"note": "Array of CarouselSlide objects. Each slide can have imageSrc, videoSrc, imageAlt, videoAriaLabel. Video takes precedence over image if both provided in a slide."
},
"autoplayDelay": {
"required": false,
"default": 3000,
"note": "Milliseconds between automatic slide transitions"
},
"showDimOverlay": {
"required": false,
"default": false,
"note": "Adds semi-transparent dark overlay (bg-background/20) over background media for improved text and logo contrast"
}
},
"buttonRules": {
"maxButtons": 2,
"structure": {
"text": "string - Button label (required)",
"href": "string - Link destination (optional). External URLs (https://, http://, www.) open in new tab. Internal values (e.g., 'about', 'contact') scroll to #about, #contact sections",
"onClick": "() => void - Additional click handler (optional)",
"props": "Partial<ButtonPropsForVariant> - Additional button props like className, textClassName (optional)"
},
"examples": [
"{ text: 'Get Started', href: 'https://github.com' }",
"{ text: 'Learn More', href: 'about' }"
],
"note": "Buttons are required (cannot be empty array). Button variant is controlled by ThemeProvider's defaultButtonVariant. Border radius is controlled by ThemeProvider's borderRadius (options: 'sharp', 'rounded', 'soft', 'pill'). All sections should be wrapped in a single ThemeProvider at the app/page level to maintain consistent styling across the entire site."
}
},
"propsSchema": {
"logoText": "string",
"description": "string",
"buttons": "Array<{text: string, onClick?: () => void, href?: string}>",
"slides": "Array<{ imageSrc?: string, videoSrc?: string, imageAlt?: string, videoAriaLabel?: string }> - Carousel slide items",
"autoplayDelay?": "number (default: 3000)",
"showDimOverlay?": "boolean (default: false)",
"logoLineHeight?": "number (default: 1.1)",
"ariaLabel?": "string (default: 'Hero section')",
"className?": "string"
},
"usageExample": "<ThemeProvider defaultButtonVariant=\"icon-arrow\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"pill\">\n <HeroCarouselLogo \n logoText=\"WEBILD\" \n description=\"Create stunning, responsive websites with our comprehensive component library\" \n buttons={[{ text: 'Get Started', href: 'https://github.com' }, { text: 'Learn More', href: 'about' }]} \n slides={[{ imageSrc: '/slide1.jpg', imageAlt: 'Slide 1' }, { imageSrc: '/slide2.jpg', imageAlt: 'Slide 2' }, { imageSrc: '/slide3.jpg', imageAlt: 'Slide 3' }]}\n autoplayDelay={5000}\n />\n</ThemeProvider>",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays",
"Requires buttons[]",
"Requires slides[]"
],
"dont": [
"Do not use less than 5 items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,82 @@
{
"name": "HeroLogo",
"description": "Full-screen hero section with background media, large text logo at bottom that scales to fill container width, description and button row above, featuring a linear gradient blur overlay.",
"constraints": {
"textRules": {
"logoText": {
"required": true,
"example": "Webild",
"minChars": 2,
"maxChars": 20
},
"description": {
"required": true,
"example": "Building the future of web design with innovative solutions",
"minChars": 5,
"maxChars": 200
}
},
"mediaRules": {
"imageSrc": {
"required": false,
"example": "/hero-background.jpg",
"note": "Background image that fills the viewport. Supports external URLs with unoptimized prop"
},
"videoSrc": {
"required": false,
"example": "/hero-background.mp4",
"note": "Background video that fills the viewport. Takes precedence over imageSrc if both provided"
},
"imageAlt": {
"required": false,
"example": "Hero background",
"note": "Empty string marks image as decorative (aria-hidden)"
},
"showDimOverlay": {
"required": false,
"default": false,
"note": "Adds semi-transparent dark overlay (bg-background/20) over background media for improved text and logo contrast"
}
},
"buttonRules": {
"maxButtons": 2,
"structure": {
"text": "string - Button label (required)",
"href": "string - Link destination (optional). External URLs (https://, http://, www.) open in new tab. Internal values (e.g., 'about', 'contact') scroll to #about, #contact sections",
"onClick": "() => void - Additional click handler (optional)",
"props": "Partial<ButtonPropsForVariant> - Additional button props like className, textClassName (optional)"
},
"examples": [
"{ text: 'Get Started', href: 'https://github.com' }",
"{ text: 'Learn More', href: 'about' }"
],
"note": "Buttons are required (cannot be empty array). Button variant is controlled by ThemeProvider's defaultButtonVariant. Border radius is controlled by ThemeProvider's borderRadius (options: 'sharp', 'rounded', 'soft', 'pill'). All sections should be wrapped in a single ThemeProvider at the app/page level to maintain consistent styling across the entire site."
}
},
"propsSchema": {
"logoText": "string",
"description": "string",
"buttons": "Array<{text: string, onClick?: () => void, href?: string}>",
"imageSrc?": "string",
"videoSrc?": "string",
"imageAlt?": "string (default: '')",
"videoAriaLabel?": "string (default: 'Hero video')",
"showDimOverlay?": "boolean (default: false)",
"logoLineHeight?": "number (default: 1.1)",
"ariaLabel?": "string (default: 'Hero section')",
"className?": "string"
},
"usageExample": "<ThemeProvider defaultButtonVariant=\"hover-bubble\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"pill\">\n <HeroLogo \n logoText=\"Webild\" \n description=\"Building the future of web design with innovative solutions\" \n buttons={[{ text: 'Get Started', href: 'https://github.com' }, { text: 'Learn More', href: 'about' }]} \n imageSrc=\"/placeholders/placeholder5.jpg\" \n imageAlt=\"Hero background\"\n />\n</ThemeProvider>",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays",
"Requires buttons[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,73 @@
{
"name": "HeroLogoBillboard",
"description": "Hero section with large text logo at top that scales to fill container width, description text, and single framed media (card or browser style) below.",
"constraints": {
"textRules": {
"logoText": {
"required": true,
"example": "klime studio",
"minChars": 2,
"maxChars": 30
},
"description": {
"required": true,
"example": "we help driven founders build the brands of tomorrow through websites, product design & branding.",
"minChars": 5,
"maxChars": 300
}
},
"mediaRules": {
"imageSrc": {
"required": false,
"example": "/hero-image.jpg",
"note": "Supports external URLs with unoptimized prop"
},
"videoSrc": {
"required": false,
"example": "/hero-video.mp4",
"note": "Takes precedence over imageSrc if both provided"
},
"imageAlt": {
"required": false,
"example": "Product showcase",
"note": "Empty string marks image as decorative (aria-hidden)"
},
"frameStyle": {
"required": false,
"options": [
"card",
"browser"
],
"default": "card",
"note": "'card' displays media in simple card with padding. 'browser' wraps media in browser mockup with address bar and window controls."
}
}
},
"propsSchema": {
"logoText": "string",
"description": "string",
"background": "{ variant: 'plain' | 'animated-grid' | 'canvas-reveal' | 'cell-wave' | 'downward-rays-animated' | 'downward-rays-animated-grid' | 'downward-rays-static' | 'downward-rays-static-grid' | 'glowing-orb' | 'gradient-bars' | 'radial-gradient' | 'rotated-rays-animated' | 'rotated-rays-animated-grid' | 'rotated-rays-static' | 'rotated-rays-static-grid' | 'sparkles-gradient' } (required)",
"imageSrc?": "string",
"videoSrc?": "string",
"imageAlt?": "string (default: '')",
"videoAriaLabel?": "string (default: 'Hero video')",
"frameStyle?": "'card' | 'browser' (default: 'card')",
"logoLineHeight?": "number (default: 1.1)",
"ariaLabel?": "string (default: 'Hero section')",
"className?": "string"
},
"usageExample": "<ThemeProvider defaultButtonVariant=\"text-stagger\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"pill\" cardStyle=\"layered-gradient\">\n <HeroLogoBillboard \n logoText=\"klime studio\" \n description=\"we help driven founders build the brands of tomorrow through websites, product design & branding.\" \n imageSrc=\"/hero.jpg\"\n imageAlt=\"Hero showcase\"\n frameStyle=\"card\"\n />\n</ThemeProvider>",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays"
],
"dont": [
"Do not use multiple items"
],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,92 @@
{
"name": "HeroLogoBillboardSplit",
"description": "Hero section with split layout (description left, buttons right), large text logo that scales to fill container width, and single framed media at bottom. Supports flex-col or flex-col-reverse layout order.",
"constraints": {
"textRules": {
"logoText": {
"required": true,
"example": "ACME",
"minChars": 2,
"maxChars": 30
},
"description": {
"required": true,
"example": "Create stunning, responsive websites with our comprehensive component library",
"minChars": 5,
"maxChars": 300
}
},
"layoutRules": {
"layoutOrder": {
"required": true,
"options": [
"default",
"reverse"
],
"note": "'default' displays split section (description/buttons) then logo (flex-col). 'reverse' displays logo then split section (flex-col-reverse)."
}
},
"buttonRules": {
"buttons": {
"required": true,
"minItems": 1,
"maxItems": 2,
"note": "Only first 2 buttons are displayed using slice(0, 2). Uses theme.defaultButtonVariant for styling."
}
},
"mediaRules": {
"imageSrc": {
"required": false,
"example": "/hero-image.jpg",
"note": "Supports external URLs with unoptimized prop"
},
"videoSrc": {
"required": false,
"example": "/hero-video.mp4",
"note": "Takes precedence over imageSrc if both provided"
},
"imageAlt": {
"required": false,
"example": "Product showcase",
"note": "Empty string marks image as decorative (aria-hidden)"
},
"frameStyle": {
"required": false,
"options": [
"card",
"browser"
],
"default": "card",
"note": "'card' displays media in simple card with padding. 'browser' wraps media in browser mockup with address bar and window controls."
}
}
},
"propsSchema": {
"logoText": "string",
"description": "string",
"background": "{ variant: 'plain' | 'animated-grid' | 'canvas-reveal' | 'cell-wave' | 'downward-rays-animated' | 'downward-rays-animated-grid' | 'downward-rays-static' | 'downward-rays-static-grid' | 'glowing-orb' | 'gradient-bars' | 'radial-gradient' | 'rotated-rays-animated' | 'rotated-rays-animated-grid' | 'rotated-rays-static' | 'rotated-rays-static-grid' | 'sparkles-gradient' } (required)",
"buttons": "Array<{text: string, onClick?: () => void, href?: string}>",
"layoutOrder": "'default' | 'reverse'",
"imageSrc?": "string",
"videoSrc?": "string",
"imageAlt?": "string (default: '')",
"videoAriaLabel?": "string (default: 'Hero video')",
"frameStyle?": "'card' | 'browser' (default: 'card')",
"logoLineHeight?": "number (default: 1.1)",
"ariaLabel?": "string (default: 'Hero section')",
"className?": "string"
},
"usageExample": "<ThemeProvider defaultButtonVariant=\"text-stagger\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"pill\" cardStyle=\"layered-gradient\">\n <HeroLogoBillboardSplit \n logoText=\"ACME\" \n description=\"Create stunning, responsive websites with our comprehensive component library\" \n buttons={[\n { text: 'Get Started', href: '#' },\n { text: 'Learn More', href: '#' }\n ]}\n layoutOrder=\"default\"\n imageSrc=\"/hero.jpg\"\n imageAlt=\"Hero showcase\"\n frameStyle=\"browser\"\n />\n</ThemeProvider>",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays",
"Requires buttons[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,105 @@
{
"name": "HeroOverlay",
"description": "Full-screen hero section with background image/video overlay, circular blur effect, and configurable text positioning (center or bottom-left).",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Build Modern Web Experiences",
"minChars": 2,
"maxChars": 40
},
"description": {
"required": true,
"example": "Create stunning, responsive websites with our comprehensive component library",
"minChars": 5,
"maxChars": 200
},
"tag": {
"required": false,
"example": "New Release",
"minChars": 2,
"maxChars": 30
}
},
"mediaRules": {
"imageSrc": {
"required": false,
"example": "/hero-background.jpg",
"note": "Background image that fills the viewport. Supports external URLs with unoptimized prop"
},
"videoSrc": {
"required": false,
"example": "/hero-background.mp4",
"note": "Background video that fills the viewport. Takes precedence over imageSrc if both provided"
},
"imageAlt": {
"required": false,
"example": "Hero background",
"note": "Empty string marks image as decorative (aria-hidden)"
},
"textPosition": {
"required": false,
"options": [
"center",
"bottom-left"
],
"default": "bottom-left",
"note": "'center' positions text in the center of viewport, 'bottom-left' positions text at bottom-left corner"
},
"showBlur": {
"required": false,
"default": true,
"note": "Controls circular blur effect with radial gradient. Blur follows text position (centered or bottom-left corner)"
},
"showDimOverlay": {
"required": false,
"default": false,
"note": "Adds semi-transparent dark overlay (bg-background/20) over background media for improved text contrast"
}
},
"buttonRules": {
"maxButtons": 2,
"structure": {
"text": "string - Button label (required)",
"href": "string - Link destination (optional). External URLs (https://, http://, www.) open in new tab. Internal values (e.g., 'about', 'contact') scroll to #about, #contact sections",
"onClick": "() => void - Additional click handler (optional)",
"props": "Partial<ButtonPropsForVariant> - Additional button props like className, textClassName (optional)"
},
"examples": [
"{ text: 'Get Started', href: 'https://example.com' }",
"{ text: 'Learn More', href: 'about' }"
],
"note": "Button variant is controlled by ThemeProvider's defaultButtonVariant. Border radius is controlled by ThemeProvider's borderRadius (options: 'sharp', 'rounded', 'soft', 'pill'). All sections should be wrapped in a single ThemeProvider at the app/page level to maintain consistent styling across the entire site."
}
},
"propsSchema": {
"title": "string",
"description": "string",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"imageSrc?": "string",
"videoSrc?": "string",
"imageAlt?": "string (default: '')",
"videoAriaLabel?": "string (default: 'Hero video')",
"textPosition?": "'center' | 'bottom-left' (default: 'bottom-left')",
"showDimOverlay?": "boolean (default: false)",
"showBlur?": "boolean (default: true)",
"ariaLabel?": "string (default: 'Hero section')",
"className?": "string"
},
"usageExample": "<ThemeProvider defaultButtonVariant=\"hover-bubble\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"pill\">\n <HeroOverlay \n title=\"Build Modern Web Experiences\" \n description=\"Create stunning, responsive websites with our comprehensive component library\" \n tag=\"New Release\" \n imageSrc=\"/hero-background.jpg\" \n imageAlt=\"Hero background\"\n textPosition=\"bottom-left\"\n showBlur={true}\n showDimOverlay={false}\n buttons={[{ text: 'Get Started', href: 'https://example.com' }, { text: 'Learn More', href: 'about' }]} \n />\n</ThemeProvider>",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays",
"Requires buttons?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,97 @@
{
"name": "HeroSplit",
"description": "Split-layout hero section with text content on one side and single image/video on the other, with responsive centering.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Build Better Products",
"minChars": 2,
"maxChars": 36
},
"description": {
"required": true,
"example": "Create exceptional user experiences with our design system",
"minChars": 5,
"maxChars": 200
},
"tag": {
"required": false,
"example": "New Release",
"minChars": 2,
"maxChars": 30
}
},
"mediaRules": {
"imageSrc": {
"required": false,
"example": "/hero-image.jpg",
"note": "Supports external URLs with unoptimized prop"
},
"videoSrc": {
"required": false,
"example": "/hero-video.mp4",
"note": "Takes precedence over imageSrc if both provided"
},
"imageAlt": {
"required": false,
"example": "Product showcase",
"note": "Empty string marks image as decorative (aria-hidden)"
},
"imagePosition": {
"required": false,
"options": [
"left",
"right"
],
"default": "right"
}
},
"buttonRules": {
"maxButtons": 2,
"structure": {
"text": "string - Button label (required)",
"href": "string - Link destination (optional). External URLs (https://, http://, www.) open in new tab. Internal values (e.g., 'about', 'contact') scroll to #about, #contact sections",
"onClick": "() => void - Additional click handler (optional)",
"props": "Partial<ButtonPropsForVariant> - Additional button props like className, textClassName (optional)"
},
"examples": [
"{ text: 'Get Started', href: 'https://example.com' }",
"{ text: 'Learn More', href: 'about' }"
],
"note": "Button variant is controlled by ThemeProvider's defaultButtonVariant. Border radius is controlled by ThemeProvider's borderRadius (options: 'sharp', 'rounded', 'soft', 'pill'). All sections should be wrapped in a single ThemeProvider at the app/page level to maintain consistent styling across the entire site."
}
},
"propsSchema": {
"title": "string",
"description": "string",
"background": "{ variant: 'plain' | 'animated-grid' | 'canvas-reveal' | 'cell-wave' | 'downward-rays-animated' | 'downward-rays-animated-grid' | 'downward-rays-static' | 'downward-rays-static-grid' | 'glowing-orb' | 'gradient-bars' | 'radial-gradient' | 'rotated-rays-animated' | 'rotated-rays-animated-grid' | 'rotated-rays-static' | 'rotated-rays-static-grid' | 'sparkles-gradient' } (required)",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"avatars?": "Avatar[] - Array of avatar objects with src and alt properties",
"avatarText?": "string - Text displayed next to the avatar group",
"imageSrc?": "string",
"videoSrc?": "string",
"imageAlt?": "string (default: '')",
"videoAriaLabel?": "string (default: 'Hero video')",
"ariaLabel?": "string (default: 'Hero section')",
"imagePosition?": "'left' | 'right' (default: 'right')",
"fixedMediaHeight?": "boolean (default: true) - When true, media wrapper is aspect-square on mobile and md:h-[65vh] on desktop",
"className?": "string"
},
"usageExample": "<ThemeProvider defaultButtonVariant=\"text-stagger\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"rounded\" background=\"aurora\" cardStyle=\"glass-elevated\" primaryButtonStyle=\"gradient\" secondaryButtonStyle=\"glass\">\n <HeroSplit \n title=\"Build Better Products\" \n description=\"Create exceptional user experiences with our design system\" \n tag=\"New Release\"\n imagePosition=\"right\" \n imageSrc=\"/hero.jpg\"\n imageAlt=\"Product showcase\"\n buttons={[{ text: 'Start Building', href: 'https://example.com' }, { text: 'View Demo', href: 'demo' }]} \n />\n</ThemeProvider>",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays",
"Requires buttons?[]",
"Requires avatars?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,106 @@
{
"name": "HeroSplitKpi",
"description": "Split-layout hero with media image/video and three KPI metric boxes positioned around it.",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "The Future of Supply Chain",
"minChars": 2,
"maxChars": 36
},
"description": {
"required": true,
"example": "Ship globally within 3 days post-production with smart fulfillment",
"minChars": 5,
"maxChars": 200
},
"tag": {
"required": false,
"example": "Trusted by 150+ Brands",
"minChars": 2,
"maxChars": 30
}
},
"kpiRules": {
"kpis": {
"required": true,
"note": "Array of exactly 3 KPI items. Each item has 'value' (the metric) and 'label' (description)",
"structure": {
"value": "string - The metric value (e.g., '99.8%', '10x', '4-10 Days')",
"label": "string - Description of the metric (e.g., 'Order Accuracy')"
},
"example": "[{ value: '4-10 Days', label: 'Worldwide Delivery' }, { value: '99.8%', label: 'Order Accuracy' }, { value: '10x', label: 'Faster Lead Times' }]"
}
},
"mediaRules": {
"imageSrc": {
"required": false,
"example": "/hero-image.jpg",
"note": "Image displayed in scaled card wrapper"
},
"videoSrc": {
"required": false,
"example": "/hero-video.mp4",
"note": "Video takes precedence over image if both provided"
},
"imageAlt": {
"required": false,
"example": "Product showcase",
"note": "Empty string marks image as decorative (aria-hidden)"
},
"imagePosition": {
"required": false,
"options": [
"left",
"right"
],
"default": "right"
}
},
"buttonRules": {
"maxButtons": 2,
"structure": {
"text": "string - Button label (required)",
"href": "string - Link destination (optional)",
"onClick": "() => void - Additional click handler (optional)"
}
}
},
"propsSchema": {
"title": "string",
"description": "string",
"background": "{ variant: 'plain' | 'animated-grid' | 'canvas-reveal' | 'cell-wave' | 'downward-rays-animated' | 'downward-rays-animated-grid' | 'downward-rays-static' | 'downward-rays-static-grid' | 'glowing-orb' | 'gradient-bars' | 'radial-gradient' | 'rotated-rays-animated' | 'rotated-rays-animated-grid' | 'rotated-rays-static' | 'rotated-rays-static-grid' | 'sparkles-gradient' } (required)",
"kpis": "[KpiItem, KpiItem, KpiItem] - Array of exactly 3 KPI items with value and label",
"enableKpiAnimation": "boolean - Enable/disable mouse-following animation on KPI boxes",
"tag?": "string",
"tagIcon?": "LucideIcon",
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
"avatars?": "Avatar[] - Array of avatar objects with src and alt properties",
"avatarText?": "string - Text displayed next to the avatar group",
"imageSrc?": "string",
"videoSrc?": "string",
"imageAlt?": "string (default: '')",
"videoAriaLabel?": "string (default: 'Hero video')",
"ariaLabel?": "string (default: 'Hero section')",
"imagePosition?": "'left' | 'right' (default: 'right')",
"className?": "string"
},
"usageExample": "<HeroSplitKpi title=\"The Future of Supply Chain\" description=\"Ship globally within 3 days with smart fulfillment\" background={{ variant: \"radial-gradient\" }} enableKpiAnimation={true} kpis={[{ value: '4-10 Days', label: 'Worldwide Delivery' }, { value: '99.8%', label: 'Order Accuracy' }, { value: '10x', label: 'Faster Lead Times' }]} imageSrc=\"/hero-image.jpg\" imageAlt=\"Supply chain\" buttons={[{ text: 'Get Started', href: 'https://example.com' }]} />",
"do": [
"Use for landing pages",
"Use for feature showcases",
"Use for capability displays",
"Use for statistics displays",
"Use for achievement showcases",
"Requires kpis[]",
"Requires buttons?[]",
"Requires avatars?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

View File

@@ -0,0 +1,61 @@
{
"name": "InlineImageSplitTextAbout",
"description": "About section with dynamic heading composed of alternating text and inline image segments.",
"constraints": {
"textRules": {
"heading[].content": {
"required": "text segments require content",
"example": "Building the future with",
"minChars": 1,
"maxChars": 100,
"note": "Each text segment in the heading array"
}
},
"imageRules": {
"heading[].src": {
"required": "image segments require src",
"example": "/brand/logo.png or https://example.com/image.png",
"note": "Supports local paths and external URLs. External URLs are rendered with unoptimized flag."
},
"heading[].alt": {
"required": false,
"example": "Company logo",
"note": "Optional alt text for images. Omit or use empty string for decorative images (aria-hidden=true when empty)."
}
},
"headingRules": {
"minSegments": 1,
"note": "heading array can contain any number of text and image segments in any order. Images automatically alternate rotation direction (1st: -rotate-12, 2nd: rotate-12, etc.)."
},
"buttonRules": {
"maxButtons": 2,
"structure": {
"text": "string - Button label (required)",
"href": "string - Link destination (optional)",
"onClick": "() => void - Click handler (optional)",
"props": "Partial<ButtonPropsForVariant> - Additional button props (optional)"
},
"note": "Button variant controlled by ThemeProvider's defaultButtonVariant. Border radius controlled by ThemeProvider's borderRadius."
}
},
"propsSchema": {
"heading": "Array<{ type: 'text'; content: string } | { type: 'image'; src: string; alt?: string }>",
"buttons?": "Array<{ text: string, onClick?: () => void, href?: string, props?: Partial<ButtonPropsForVariant<CTAButtonVariant>> }>",
"useInvertedBackground": "'noInvert' | 'invertDefault'",
"ariaLabel?": "string (default: 'About section')",
"className?": "string"
},
"usageExample": "// Wrap in ThemeProvider\n<ThemeProvider defaultButtonVariant=\"text-stagger\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"rounded\" background=\"aurora\" cardStyle=\"glass-elevated\" primaryButtonStyle=\"gradient\" secondaryButtonStyle=\"glass\">\n <InlineImageSplitTextAbout heading={[{ type: 'text', content: 'Building the future with' }, { type: 'image', src: '/brand/logo.png', alt: 'Company logo' }, { type: 'text', content: 'innovative solutions' }]} useInvertedBackground={\"noInvert\"} buttons={[{ text: 'Get Started', href: '/signup' }, { text: 'Learn More', href: '/about' }]} />\n</ThemeProvider>",
"do": [
"Use for about pages",
"Use for company information",
"Requires heading[]",
"Requires buttons?[]"
],
"dont": [],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}

Some files were not shown because too many files have changed in this diff Show More