Initial commit
This commit is contained in:
4
.env
Normal file
4
.env
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
NEXT_PUBLIC_API_URL=https://api.webild.io
|
||||
NEXT_PUBLIC_PROJECT_ID=5dc51405-c4e9-42d6-b5fc-267f6b2834a3
|
||||
|
||||
37
.gitea/workflows/build.yml
Normal file
37
.gitea/workflows/build.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
name: Code Check
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
run: git clone --depth 1 --branch ${{ gitea.ref_name }} ${{ gitea.server_url }}/${{ gitea.repository }}.git . || exit 1
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
if [ -d "/var/node_modules_cache/node_modules" ]; then
|
||||
ln -s /var/node_modules_cache/node_modules ./node_modules
|
||||
else
|
||||
npm ci --prefer-offline --no-audit
|
||||
fi
|
||||
timeout-minutes: 5
|
||||
|
||||
- name: TypeScript check
|
||||
run: npm run typecheck 2>&1 | tee build.log
|
||||
timeout-minutes: 3
|
||||
|
||||
- name: ESLint check
|
||||
run: npm run lint 2>&1 | tee -a build.log
|
||||
timeout-minutes: 3
|
||||
|
||||
- name: Upload build log on failure
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: build-log
|
||||
path: build.log
|
||||
retention-days: 1
|
||||
36
README.md
Normal file
36
README.md
Normal 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.
|
||||
117
THEME_PROVIDER_OPTIONS.txt
Normal file
117
THEME_PROVIDER_OPTIONS.txt
Normal file
@@ -0,0 +1,117 @@
|
||||
================================================================================
|
||||
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"
|
||||
|
||||
2. defaultTextAnimation
|
||||
• "entrance-slide"
|
||||
• "reveal-blur"
|
||||
• "background-highlight"
|
||||
|
||||
3. borderRadius
|
||||
• "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"
|
||||
• "noise"
|
||||
• "noiseDiagonalGradient"
|
||||
• "fluid"
|
||||
• "blurBottom"
|
||||
• "grid"
|
||||
|
||||
7. cardStyle
|
||||
• "solid"
|
||||
• "outline"
|
||||
• "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"
|
||||
• "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>
|
||||
|
||||
================================================================================
|
||||
804
colorThemes.css
Normal file
804
colorThemes.css
Normal file
@@ -0,0 +1,804 @@
|
||||
/* ============================================ */
|
||||
/* LIGHT THEME VARIANTS */
|
||||
/* ============================================ */
|
||||
|
||||
/* Light Theme - Minimal Dark Blue */
|
||||
:root[data-theme="minimal-dark-blue"] {
|
||||
--background: #ffffff;
|
||||
--card: #f9f9f9;
|
||||
--foreground: #000612e6;
|
||||
--primary-cta: #15479c;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #f9f9f9;
|
||||
--secondary-cta-text: #000612e6;
|
||||
--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;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #f9f9f9;
|
||||
--secondary-cta-text: #000f06e6;
|
||||
--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;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #f9f9f9;
|
||||
--secondary-cta-text: #120006e6;
|
||||
--accent: #e2e2e2;
|
||||
--background-accent: #c4c4c4;
|
||||
}
|
||||
|
||||
/* Light Theme - Minimal Bright Blue */
|
||||
:root[data-theme="minimal-bright-blue"] {
|
||||
--background: #ffffff;
|
||||
--card: #f9f9f9;
|
||||
--foreground: #000612e6;
|
||||
--primary-cta: #106EFB;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #f9f9f9;
|
||||
--secondary-cta-text: #000612e6;
|
||||
--accent: #e2e2e2;
|
||||
--background-accent: #106EFB;
|
||||
}
|
||||
|
||||
/* Light Theme - Minimal Bright Orange */
|
||||
:root[data-theme="minimal-bright-orange"] {
|
||||
--background: #ffffff;
|
||||
--card: #f9f9f9;
|
||||
--foreground: #120a00e6;
|
||||
--primary-cta: #E34400;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #f9f9f9;
|
||||
--secondary-cta-text: #120a00e6;
|
||||
--accent: #e2e2e2;
|
||||
--background-accent: #E34400;
|
||||
}
|
||||
|
||||
/* Light Theme - Minimal Golden Orange */
|
||||
:root[data-theme="minimal-golden-orange"] {
|
||||
--background: #ffffff;
|
||||
--card: #f9f9f9;
|
||||
--foreground: #120a00e6;
|
||||
--primary-cta: #FF7B05;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #f9f9f9;
|
||||
--secondary-cta-text: #120a00e6;
|
||||
--accent: #e2e2e2;
|
||||
--background-accent: #FF7B05;
|
||||
}
|
||||
|
||||
/* Light Theme - Minimal Light Orange */
|
||||
:root[data-theme="minimal-light-orange"] {
|
||||
--background: #ffffff;
|
||||
--card: #f9f9f9;
|
||||
--foreground: #120a00e6;
|
||||
--primary-cta: #ff8c42;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #f9f9f9;
|
||||
--secondary-cta-text: #120a00e6;
|
||||
--accent: #e2e2e2;
|
||||
--background-accent: #c4c4c4;
|
||||
}
|
||||
|
||||
/* Light Theme - Dark Blue */
|
||||
:root[data-theme="dark-blue"] {
|
||||
--background: #f5faff;
|
||||
--card: #f1f8ff;
|
||||
--foreground: #001122;
|
||||
--primary-cta: #15479c;
|
||||
--primary-cta-text: #f5faff;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #001122;
|
||||
--accent: #a8cce8;
|
||||
--background-accent: #7ba3cf;
|
||||
}
|
||||
|
||||
/* Light Theme - Dark Green */
|
||||
:root[data-theme="dark-green"] {
|
||||
--background: #fafffb;
|
||||
--card: #f7fffa;
|
||||
--foreground: #001a0a;
|
||||
--primary-cta: #0a7039;
|
||||
--primary-cta-text: #fafffb;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #001a0a;
|
||||
--accent: #a8d9be;
|
||||
--background-accent: #6bbf8e;
|
||||
}
|
||||
|
||||
/* Light Theme - Light Red */
|
||||
:root[data-theme="light-red"] {
|
||||
--background: #fffafa;
|
||||
--card: #fff7f7;
|
||||
--foreground: #1a0000;
|
||||
--primary-cta: #e63946;
|
||||
--primary-cta-text: #fffafa;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #1a0000;
|
||||
--accent: #f5c4c7;
|
||||
--background-accent: #f09199;
|
||||
}
|
||||
|
||||
/* Light Theme - Light Purple */
|
||||
:root[data-theme="light-purple"] {
|
||||
--background: #fbfaff;
|
||||
--card: #f7f5ff;
|
||||
--foreground: #0f0022;
|
||||
--primary-cta: #8b5cf6;
|
||||
--primary-cta-text: #fbfaff;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #0f0022;
|
||||
--accent: #d8cef5;
|
||||
--background-accent: #c4a8f9;
|
||||
}
|
||||
|
||||
/* Light Theme - Warm Cream */
|
||||
:root[data-theme="warm-cream"] {
|
||||
--background: #f6f0e9;
|
||||
--card: #efe7dd;
|
||||
--foreground: #2b180a;
|
||||
--primary-cta: #2b180a;
|
||||
--primary-cta-text: #f6f0e9;
|
||||
--secondary-cta: #efe7dd;
|
||||
--secondary-cta-text: #2b180a;
|
||||
--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;
|
||||
--primary-cta-text: #f5f5f5;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #1c1c1c;
|
||||
--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;
|
||||
--primary-cta-text: #f5f5f5;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #1c1c1c;
|
||||
--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;
|
||||
--primary-cta-text: #f5f5f5;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #1c1c1c;
|
||||
--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;
|
||||
--primary-cta-text: #f5f5f5;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #1c1c1c;
|
||||
--accent: #6139e6;
|
||||
--background-accent: #b3a8e8;
|
||||
}
|
||||
|
||||
/* Light Theme - Warm Beige */
|
||||
:root[data-theme="warm-beige"] {
|
||||
--background: #efebe5;
|
||||
--card: #f7f2ea;
|
||||
--foreground: #000000;
|
||||
--primary-cta: #000000;
|
||||
--primary-cta-text: #efebe5;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #000000;
|
||||
--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;
|
||||
--primary-cta-text: #f5f5f5;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #1c1c1c;
|
||||
--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;
|
||||
--primary-cta-text: #f5f5f5;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #1c1c1c;
|
||||
--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;
|
||||
--primary-cta-text: #f5f5f5;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #1c1c1c;
|
||||
--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;
|
||||
--primary-cta-text: #f5f5f5;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #1c1c1c;
|
||||
--accent: #6139e6;
|
||||
--background-accent: #b3a8e8;
|
||||
}
|
||||
|
||||
/* Light Theme - Warm Gray Pink */
|
||||
:root[data-theme="warmgray-pink"] {
|
||||
--background: #f7f6f7;
|
||||
--card: #ffffff;
|
||||
--foreground: #1b0c25;
|
||||
--primary-cta: #1b0c25;
|
||||
--primary-cta-text: #f7f6f7;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #1b0c25;
|
||||
--accent: #ff93e4;
|
||||
--background-accent: #e8a8c3;
|
||||
}
|
||||
|
||||
/* Light Theme - Warm Gray Orange */
|
||||
:root[data-theme="warmgray-orange"] {
|
||||
--background: #f7f6f7;
|
||||
--card: #ffffff;
|
||||
--foreground: #25190c;
|
||||
--primary-cta: #ff6207;
|
||||
--primary-cta-text: #f7f6f7;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #25190c;
|
||||
--accent: #ffce93;
|
||||
--background-accent: #e8cfa8;
|
||||
}
|
||||
|
||||
/* Light Theme - Warm Gray Blue */
|
||||
:root[data-theme="warmgray-blue"] {
|
||||
--background: #f7f6f7;
|
||||
--card: #ffffff;
|
||||
--foreground: #0c1325;
|
||||
--primary-cta: #0798ff;
|
||||
--primary-cta-text: #f7f6f7;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #0c1325;
|
||||
--accent: #93c7ff;
|
||||
--background-accent: #a8cde8;
|
||||
}
|
||||
|
||||
/* Light Theme - Warm Gray Indigo */
|
||||
:root[data-theme="warmgray-indigo"] {
|
||||
--background: #f7f6f7;
|
||||
--card: #ffffff;
|
||||
--foreground: #0c1325;
|
||||
--primary-cta: #0b07ff;
|
||||
--primary-cta-text: #f7f6f7;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #0c1325;
|
||||
--accent: #93b7ff;
|
||||
--background-accent: #a8bae8;
|
||||
}
|
||||
|
||||
/* Light Theme - Lavender Peach */
|
||||
:root[data-theme="lavender-peach"] {
|
||||
--background: #e3deea;
|
||||
--card: #ffffff;
|
||||
--foreground: #27231f;
|
||||
--primary-cta: #27231f;
|
||||
--primary-cta-text: #e3deea;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #27231f;
|
||||
--accent: #c68a62;
|
||||
--background-accent: #c68a62;
|
||||
}
|
||||
|
||||
/* Light Theme - Lavender Blue */
|
||||
:root[data-theme="lavender-blue"] {
|
||||
--background: #e3deea;
|
||||
--card: #ffffff;
|
||||
--foreground: #1f2027;
|
||||
--primary-cta: #1f2027;
|
||||
--primary-cta-text: #e3deea;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #1f2027;
|
||||
--accent: #627dc6;
|
||||
--background-accent: #627dc6;
|
||||
}
|
||||
|
||||
/* Light Theme - Warm Stone */
|
||||
:root[data-theme="warm-stone"] {
|
||||
--background: #f5f4ef;
|
||||
--card: #dad6cd;
|
||||
--foreground: #2a2928;
|
||||
--primary-cta: #2a2928;
|
||||
--primary-cta-text: #f5f4ef;
|
||||
--secondary-cta: #ecebea;
|
||||
--secondary-cta-text: #2a2928;
|
||||
--accent: #ffffff;
|
||||
--background-accent: #c6b180;
|
||||
}
|
||||
|
||||
/* Light Theme - Warm Stone Gray */
|
||||
:root[data-theme="warm-stone-gray"] {
|
||||
--background: #f5f4f0;
|
||||
--card: #ffffff;
|
||||
--foreground: #1a1a1a;
|
||||
--primary-cta: #2c2c2c;
|
||||
--primary-cta-text: #f5f4f0;
|
||||
--secondary-cta: #f5f4f0;
|
||||
--secondary-cta-text: #1a1a1a;
|
||||
--accent: #8a8a8a;
|
||||
--background-accent: #e8e6e1;
|
||||
}
|
||||
|
||||
/* Light Theme - Warm Green */
|
||||
:root[data-theme="warm-green"] {
|
||||
--background: #fffefe;
|
||||
--card: #f6f7f4;
|
||||
--foreground: #080908;
|
||||
--primary-cta: #0e3a29;
|
||||
--primary-cta-text: #fffefe;
|
||||
--secondary-cta: #e7eecd;
|
||||
--secondary-cta-text: #080908;
|
||||
--accent: #35c18b;
|
||||
--background-accent: #ecebe4;
|
||||
}
|
||||
|
||||
/* Light Theme - Warm Sand */
|
||||
:root[data-theme="warm-sand"] {
|
||||
--background: #fcf6ec;
|
||||
--card: #f3ede2;
|
||||
--foreground: #2e2521;
|
||||
--primary-cta: #2e2521;
|
||||
--primary-cta-text: #fcf6ec;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #2e2521;
|
||||
--accent: #b2a28b;
|
||||
--background-accent: #b2a28b;
|
||||
}
|
||||
|
||||
/* Light Theme - Warm Gray Red */
|
||||
:root[data-theme="warmgray-red"] {
|
||||
--background: #f7f6f7;
|
||||
--card: #ffffff;
|
||||
--foreground: #250c0d;
|
||||
--primary-cta: #b82b40;
|
||||
--primary-cta-text: #f7f6f7;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta-text: #250c0d;
|
||||
--accent: #b90941;
|
||||
--background-accent: #e8a8b6;
|
||||
}
|
||||
|
||||
|
||||
/* ============================================ */
|
||||
/* DARK THEME VARIANTS */
|
||||
/* ============================================ */
|
||||
|
||||
/* Dark Theme - Minimal */
|
||||
:root[data-theme="dark"] {
|
||||
--background: #0a0a0a;
|
||||
--card: #1a1a1a;
|
||||
--foreground: #ffffffe6;
|
||||
--primary-cta: #e6e6e6;
|
||||
--primary-cta-text: #0a0a0a;
|
||||
--secondary-cta: #1a1a1a;
|
||||
--secondary-cta-text: #ffffffe6;
|
||||
--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;
|
||||
--primary-cta-text: #0a0a0a;
|
||||
--secondary-cta: #1a1a1a;
|
||||
--secondary-cta-text: #f0f8ffe6;
|
||||
--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;
|
||||
--primary-cta-text: #0a0a0a;
|
||||
--secondary-cta: #1a1a1a;
|
||||
--secondary-cta-text: #f5fffae6;
|
||||
--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;
|
||||
--primary-cta-text: #0a0a0a;
|
||||
--secondary-cta: #1a1a1a;
|
||||
--secondary-cta-text: #fff5f5e6;
|
||||
--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;
|
||||
--primary-cta-text: #0a0a0a;
|
||||
--secondary-cta: #1a1a1a;
|
||||
--secondary-cta-text: #f8f5ffe6;
|
||||
--accent: #737373;
|
||||
--background-accent: #737373;
|
||||
}
|
||||
|
||||
/* Dark Theme - Light Blue White */
|
||||
:root[data-theme="dark-light-blue-white"] {
|
||||
--background: #010912;
|
||||
--card: #152840;
|
||||
--foreground: #e6f0ff;
|
||||
--primary-cta: #cee7ff;
|
||||
--primary-cta-text: #010912;
|
||||
--secondary-cta: #0e1a29;
|
||||
--secondary-cta-text: #ffffff;
|
||||
--accent: #3f5c79;
|
||||
--background-accent: #004a93;
|
||||
}
|
||||
|
||||
/* Dark Theme - Lime */
|
||||
:root[data-theme="dark-lime"] {
|
||||
--background: #0a0a0a;
|
||||
--card: #1a1a1a;
|
||||
--foreground: #f5f5f5;
|
||||
--primary-cta: #dfff1c;
|
||||
--primary-cta-text: #0a0a0a;
|
||||
--secondary-cta: #1a1a1a;
|
||||
--secondary-cta-text: #ffffff;
|
||||
--accent: #8b9a1b;
|
||||
--background-accent: #5d6b00;
|
||||
}
|
||||
|
||||
/* Dark Theme - Gold */
|
||||
:root[data-theme="dark-gold"] {
|
||||
--background: #0a0a0a;
|
||||
--card: #1a1a1a;
|
||||
--foreground: #f5f5f5;
|
||||
--primary-cta: #ffdf7d;
|
||||
--primary-cta-text: #0a0a0a;
|
||||
--secondary-cta: #1a1a1a;
|
||||
--secondary-cta-text: #ffffff;
|
||||
--accent: #b8860b;
|
||||
--background-accent: #8b6914;
|
||||
}
|
||||
|
||||
/* Dark Theme - Crimson */
|
||||
:root[data-theme="dark-crimson"] {
|
||||
--background: #0a0a0a;
|
||||
--card: #1a1a1a;
|
||||
--foreground: #f5f5f5;
|
||||
--primary-cta: #ff0000;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #1a1a1a;
|
||||
--secondary-cta-text: #ffffff;
|
||||
--accent: #991b1b;
|
||||
--background-accent: #7f1d1d;
|
||||
}
|
||||
|
||||
/* Dark Theme - Midnight Ice */
|
||||
:root[data-theme="dark-midnight-ice"] {
|
||||
--background: #000000;
|
||||
--card: #0c0c0c;
|
||||
--foreground: #ffffff;
|
||||
--primary-cta: #cee7ff;
|
||||
--primary-cta-text: #000000;
|
||||
--secondary-cta: #000000;
|
||||
--secondary-cta-text: #ffffff;
|
||||
--accent: #535353;
|
||||
--background-accent: #CEE7FF;
|
||||
}
|
||||
|
||||
/* Dark Theme - Midnight Blue */
|
||||
:root[data-theme="dark-midnight-blue"] {
|
||||
--background: #000000;
|
||||
--card: #0c0c0c;
|
||||
--foreground: #ffffff;
|
||||
--primary-cta: #106EFB;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #000000;
|
||||
--secondary-cta-text: #ffffff;
|
||||
--accent: #535353;
|
||||
--background-accent: #106EFB;
|
||||
}
|
||||
|
||||
/* Dark Theme - Blue Orange Accent */
|
||||
:root[data-theme="dark-blue-orange-accent"] {
|
||||
--background: #0a0a0a;
|
||||
--card: #1a1a1a;
|
||||
--foreground: #ffffff;
|
||||
--primary-cta: #1f7cff;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #010101;
|
||||
--secondary-cta-text: #ffffff;
|
||||
--accent: #1f7cff;
|
||||
--background-accent: #f96b2f;
|
||||
}
|
||||
|
||||
/* Dark Theme - Orange Blue Accent */
|
||||
:root[data-theme="dark-orange-blue-accent"] {
|
||||
--background: #0a0a0a;
|
||||
--card: #1a1a1a;
|
||||
--foreground: #ffffff;
|
||||
--primary-cta: #e34400;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #010101;
|
||||
--secondary-cta-text: #ffffff;
|
||||
--accent: #ff7b05;
|
||||
--background-accent: #106efb;
|
||||
}
|
||||
|
||||
/* Dark Theme - Minimal Bright Orange */
|
||||
:root[data-theme="dark-minimal-bright-orange"] {
|
||||
--background: #0a0a0a;
|
||||
--card: #1a1a1a;
|
||||
--foreground: #ffffff;
|
||||
--primary-cta: #e34400;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #010101;
|
||||
--secondary-cta-text: #ffffff;
|
||||
--accent: #737373;
|
||||
--background-accent: #e34400;
|
||||
}
|
||||
|
||||
/* Dark Theme - Minimal Light Orange */
|
||||
:root[data-theme="dark-minimal-light-orange"] {
|
||||
--background: #0a0a0a;
|
||||
--card: #1a1a1a;
|
||||
--foreground: #fffaf5e6;
|
||||
--primary-cta: #ffaa70;
|
||||
--primary-cta-text: #0a0a0a;
|
||||
--secondary-cta: #1a1a1a;
|
||||
--secondary-cta-text: #fffaf5e6;
|
||||
--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;
|
||||
--primary-cta-text: #0a0a0a;
|
||||
--secondary-cta: #1a1a1a;
|
||||
--secondary-cta-text: #fffffae6;
|
||||
--accent: #737373;
|
||||
--background-accent: #737373;
|
||||
}
|
||||
|
||||
/* Dark Theme - Light Blue */
|
||||
:root[data-theme="dark-light-blue"] {
|
||||
--background: #010912;
|
||||
--card: #152840;
|
||||
--foreground: #e6f0ff;
|
||||
--primary-cta: #cee7ff;
|
||||
--primary-cta-text: #010912;
|
||||
--secondary-cta: #0e1a29;
|
||||
--secondary-cta-text: #e6f0ff;
|
||||
--accent: #3f5c79;
|
||||
--background-accent: #004a93;
|
||||
}
|
||||
|
||||
/* Dark Theme - Light Green */
|
||||
:root[data-theme="dark-light-green"] {
|
||||
--background: #000802;
|
||||
--card: #0b1a0b;
|
||||
--foreground: #e6ffe6;
|
||||
--primary-cta: #80da9b;
|
||||
--primary-cta-text: #000802;
|
||||
--secondary-cta: #07170b;
|
||||
--secondary-cta-text: #e6ffe6;
|
||||
--accent: #38714a;
|
||||
--background-accent: #2c6541;
|
||||
}
|
||||
|
||||
/* Dark Theme - Light Red */
|
||||
:root[data-theme="dark-light-red"] {
|
||||
--background: #080000;
|
||||
--card: #1e0d0d;
|
||||
--foreground: #ffe6e6;
|
||||
--primary-cta: #ff7a7a;
|
||||
--primary-cta-text: #080000;
|
||||
--secondary-cta: #1e0909;
|
||||
--secondary-cta-text: #ffe6e6;
|
||||
--accent: #7b4242;
|
||||
--background-accent: #65292c;
|
||||
}
|
||||
|
||||
/* Dark Theme - Dark Red */
|
||||
:root[data-theme="dark-dark-red"] {
|
||||
--background: #060000;
|
||||
--card: #1d0d0d;
|
||||
--foreground: #ffe6e6;
|
||||
--primary-cta: #ff3d4a;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #1f0a0a;
|
||||
--secondary-cta-text: #ffe6e6;
|
||||
--accent: #7b2d2d;
|
||||
--background-accent: #b8111f;
|
||||
}
|
||||
|
||||
/* Dark Theme - Light Purple */
|
||||
:root[data-theme="dark-light-purple"] {
|
||||
--background: #050012;
|
||||
--card: #040121;
|
||||
--foreground: #f0e6ff;
|
||||
--primary-cta: #c89bff;
|
||||
--primary-cta-text: #050012;
|
||||
--secondary-cta: #1d123b;
|
||||
--secondary-cta-text: #f0e6ff;
|
||||
--accent: #684f7b;
|
||||
--background-accent: #65417c;
|
||||
}
|
||||
|
||||
/* Dark Theme - Light Orange */
|
||||
:root[data-theme="dark-light-orange"] {
|
||||
--background: #080200;
|
||||
--card: #1a0d0b;
|
||||
--foreground: #ffe6d5;
|
||||
--primary-cta: #ffaa70;
|
||||
--primary-cta-text: #080200;
|
||||
--secondary-cta: #170b07;
|
||||
--secondary-cta-text: #ffe6d5;
|
||||
--accent: #7b5e4a;
|
||||
--background-accent: #b8541e;
|
||||
}
|
||||
|
||||
/* Dark Theme - Deep Blue */
|
||||
:root[data-theme="dark-deep-blue"] {
|
||||
--background: #020617;
|
||||
--card: #0f172a;
|
||||
--foreground: #e2e8f0;
|
||||
--primary-cta: #c4d8f9;
|
||||
--primary-cta-text: #020617;
|
||||
--secondary-cta: #041633;
|
||||
--secondary-cta-text: #e2e8f0;
|
||||
--accent: #2d30f3;
|
||||
--background-accent: #1d4ed8;
|
||||
}
|
||||
|
||||
/* Dark Theme - Violet */
|
||||
:root[data-theme="dark-violet"] {
|
||||
--background: #030128;
|
||||
--card: #241f48;
|
||||
--foreground: #ffffff;
|
||||
--primary-cta: #ffffff;
|
||||
--primary-cta-text: #030128;
|
||||
--secondary-cta: #131136;
|
||||
--secondary-cta-text: #d5d4f6;
|
||||
--accent: #44358a;
|
||||
--background-accent: #b597fe;
|
||||
}
|
||||
|
||||
/* Dark Theme - Ruby */
|
||||
:root[data-theme="dark-ruby"] {
|
||||
--background: #000000;
|
||||
--card: #481f1f;
|
||||
--foreground: #ffffff;
|
||||
--primary-cta: #ffffff;
|
||||
--primary-cta-text: #280101;
|
||||
--secondary-cta: #361311;
|
||||
--secondary-cta-text: #f6d4d4;
|
||||
--accent: #51000b;
|
||||
--background-accent: #ff2231;
|
||||
}
|
||||
|
||||
/* Dark Theme - Emerald */
|
||||
:root[data-theme="dark-emerald"] {
|
||||
--background: #000000;
|
||||
--card: #1f4035;
|
||||
--foreground: #ffffff;
|
||||
--primary-cta: #ffffff;
|
||||
--primary-cta-text: #051a12;
|
||||
--secondary-cta: #0d2b1f;
|
||||
--secondary-cta-text: #d4f6e8;
|
||||
--accent: #0d5238;
|
||||
--background-accent: #10b981;
|
||||
}
|
||||
|
||||
/* Dark Theme - Indigo */
|
||||
:root[data-theme="dark-indigo"] {
|
||||
--background: #000000;
|
||||
--card: #1f1f40;
|
||||
--foreground: #ffffff;
|
||||
--primary-cta: #ffffff;
|
||||
--primary-cta-text: #0a051a;
|
||||
--secondary-cta: #0d0d2b;
|
||||
--secondary-cta-text: #d4d4f6;
|
||||
--accent: #3d2880;
|
||||
--background-accent: #663cff;
|
||||
}
|
||||
|
||||
/* Dark Theme - Forest */
|
||||
:root[data-theme="dark-forest"] {
|
||||
--background: #000000;
|
||||
--card: #1a2f1d;
|
||||
--foreground: #ffffff;
|
||||
--primary-cta: #ffffff;
|
||||
--primary-cta-text: #0a1a0c;
|
||||
--secondary-cta: #0d200f;
|
||||
--secondary-cta-text: #d4f6d8;
|
||||
--accent: #1a3d1f;
|
||||
--background-accent: #355e3b;
|
||||
}
|
||||
|
||||
/* Dark Theme - Mint */
|
||||
:root[data-theme="dark-mint"] {
|
||||
--background: #000000;
|
||||
--card: #1a2a1a;
|
||||
--foreground: #ffffff;
|
||||
--primary-cta: #ffffff;
|
||||
--primary-cta-text: #0a150a;
|
||||
--secondary-cta: #0d1a0d;
|
||||
--secondary-cta-text: #e1f6e1;
|
||||
--accent: #2d4a2d;
|
||||
--background-accent: #c1e1c1;
|
||||
}
|
||||
|
||||
|
||||
677
colorThemes.json
Normal file
677
colorThemes.json
Normal file
@@ -0,0 +1,677 @@
|
||||
{
|
||||
"lightTheme": {
|
||||
"minimalDarkBlue": {
|
||||
"--background": "#ffffff",
|
||||
"--card": "#f9f9f9",
|
||||
"--foreground": "#000612e6",
|
||||
"--primary-cta": "#15479c",
|
||||
"--secondary-cta": "#f9f9f9",
|
||||
"--accent": "#e2e2e2",
|
||||
"--background-accent": "#c4c4c4",
|
||||
"--primary-cta-text": "#ffffff",
|
||||
"--secondary-cta-text": "#000612e6"
|
||||
},
|
||||
"minimalDarkGreen": {
|
||||
"--background": "#ffffff",
|
||||
"--card": "#f9f9f9",
|
||||
"--foreground": "#000f06e6",
|
||||
"--primary-cta": "#0a7039",
|
||||
"--secondary-cta": "#f9f9f9",
|
||||
"--accent": "#e2e2e2",
|
||||
"--background-accent": "#c4c4c4",
|
||||
"--primary-cta-text": "#ffffff",
|
||||
"--secondary-cta-text": "#000f06e6"
|
||||
},
|
||||
"minimalLightRed": {
|
||||
"--background": "#ffffff",
|
||||
"--card": "#f9f9f9",
|
||||
"--foreground": "#120006e6",
|
||||
"--primary-cta": "#e63946",
|
||||
"--secondary-cta": "#f9f9f9",
|
||||
"--accent": "#e2e2e2",
|
||||
"--background-accent": "#c4c4c4",
|
||||
"--primary-cta-text": "#ffffff",
|
||||
"--secondary-cta-text": "#120006e6"
|
||||
},
|
||||
"minimalBrightBlue": {
|
||||
"--background": "#ffffff",
|
||||
"--card": "#f9f9f9",
|
||||
"--foreground": "#000612e6",
|
||||
"--primary-cta": "#106EFB",
|
||||
"--secondary-cta": "#f9f9f9",
|
||||
"--accent": "#e2e2e2",
|
||||
"--background-accent": "#106EFB",
|
||||
"--primary-cta-text": "#ffffff",
|
||||
"--secondary-cta-text": "#000612e6"
|
||||
},
|
||||
"minimalBrightOrange": {
|
||||
"--background": "#ffffff",
|
||||
"--card": "#f9f9f9",
|
||||
"--foreground": "#120a00e6",
|
||||
"--primary-cta": "#E34400",
|
||||
"--secondary-cta": "#f9f9f9",
|
||||
"--accent": "#e2e2e2",
|
||||
"--background-accent": "#E34400",
|
||||
"--primary-cta-text": "#ffffff",
|
||||
"--secondary-cta-text": "#120a00e6"
|
||||
},
|
||||
"minimalGoldenOrange": {
|
||||
"--background": "#ffffff",
|
||||
"--card": "#f9f9f9",
|
||||
"--foreground": "#120a00e6",
|
||||
"--primary-cta": "#FF7B05",
|
||||
"--secondary-cta": "#f9f9f9",
|
||||
"--accent": "#e2e2e2",
|
||||
"--background-accent": "#FF7B05",
|
||||
"--primary-cta-text": "#ffffff",
|
||||
"--secondary-cta-text": "#120a00e6"
|
||||
},
|
||||
"minimalLightOrange": {
|
||||
"--background": "#ffffff",
|
||||
"--card": "#f9f9f9",
|
||||
"--foreground": "#120a00e6",
|
||||
"--primary-cta": "#ff8c42",
|
||||
"--secondary-cta": "#f9f9f9",
|
||||
"--accent": "#e2e2e2",
|
||||
"--background-accent": "#c4c4c4",
|
||||
"--primary-cta-text": "#ffffff",
|
||||
"--secondary-cta-text": "#120a00e6"
|
||||
},
|
||||
"darkBlue": {
|
||||
"--background": "#f5faff",
|
||||
"--card": "#f1f8ff",
|
||||
"--foreground": "#001122",
|
||||
"--primary-cta": "#15479c",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#a8cce8",
|
||||
"--background-accent": "#7ba3cf",
|
||||
"--primary-cta-text": "#f5faff",
|
||||
"--secondary-cta-text": "#001122"
|
||||
},
|
||||
"darkGreen": {
|
||||
"--background": "#fafffb",
|
||||
"--card": "#f7fffa",
|
||||
"--foreground": "#001a0a",
|
||||
"--primary-cta": "#0a7039",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#a8d9be",
|
||||
"--background-accent": "#6bbf8e",
|
||||
"--primary-cta-text": "#fafffb",
|
||||
"--secondary-cta-text": "#001a0a"
|
||||
},
|
||||
"lightRed": {
|
||||
"--background": "#fffafa",
|
||||
"--card": "#fff7f7",
|
||||
"--foreground": "#1a0000",
|
||||
"--primary-cta": "#e63946",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#f5c4c7",
|
||||
"--background-accent": "#f09199",
|
||||
"--primary-cta-text": "#fffafa",
|
||||
"--secondary-cta-text": "#1a0000"
|
||||
},
|
||||
"lightPurple": {
|
||||
"--background": "#fbfaff",
|
||||
"--card": "#f7f5ff",
|
||||
"--foreground": "#0f0022",
|
||||
"--primary-cta": "#8b5cf6",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#d8cef5",
|
||||
"--background-accent": "#c4a8f9",
|
||||
"--primary-cta-text": "#fbfaff",
|
||||
"--secondary-cta-text": "#0f0022"
|
||||
},
|
||||
"warmCream": {
|
||||
"--background": "#f6f0e9",
|
||||
"--card": "#efe7dd",
|
||||
"--foreground": "#2b180a",
|
||||
"--primary-cta": "#2b180a",
|
||||
"--secondary-cta": "#efe7dd",
|
||||
"--accent": "#94877c",
|
||||
"--background-accent": "#afa094",
|
||||
"--primary-cta-text": "#f6f0e9",
|
||||
"--secondary-cta-text": "#2b180a"
|
||||
},
|
||||
"grayBlueAccent": {
|
||||
"--background": "#f5f5f5",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#1c1c1c",
|
||||
"--primary-cta": "#1c1c1c",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#15479c",
|
||||
"--background-accent": "#a8cce8",
|
||||
"--primary-cta-text": "#f5f5f5",
|
||||
"--secondary-cta-text": "#1c1c1c"
|
||||
},
|
||||
"grayGreenAccent": {
|
||||
"--background": "#f5f5f5",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#1c1c1c",
|
||||
"--primary-cta": "#1c1c1c",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#159c49",
|
||||
"--background-accent": "#a8e8ba",
|
||||
"--primary-cta-text": "#f5f5f5",
|
||||
"--secondary-cta-text": "#1c1c1c"
|
||||
},
|
||||
"grayRedAccent": {
|
||||
"--background": "#f5f5f5",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#1c1c1c",
|
||||
"--primary-cta": "#1c1c1c",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#e63946",
|
||||
"--background-accent": "#e8bea8",
|
||||
"--primary-cta-text": "#f5f5f5",
|
||||
"--secondary-cta-text": "#1c1c1c"
|
||||
},
|
||||
"grayPurpleAccent": {
|
||||
"--background": "#f5f5f5",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#1c1c1c",
|
||||
"--primary-cta": "#1c1c1c",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#6139e6",
|
||||
"--background-accent": "#b3a8e8",
|
||||
"--primary-cta-text": "#f5f5f5",
|
||||
"--secondary-cta-text": "#1c1c1c"
|
||||
},
|
||||
"warmBeige": {
|
||||
"--background": "#efebe5",
|
||||
"--card": "#f7f2ea",
|
||||
"--foreground": "#000000",
|
||||
"--primary-cta": "#000000",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#ffffff",
|
||||
"--background-accent": "#e1b875",
|
||||
"--primary-cta-text": "#efebe5",
|
||||
"--secondary-cta-text": "#000000"
|
||||
},
|
||||
"grayTealGreen": {
|
||||
"--background": "#f5f5f5",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#1c1c1c",
|
||||
"--primary-cta": "#1f514c",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#159c49",
|
||||
"--background-accent": "#a8e8ba",
|
||||
"--primary-cta-text": "#f5f5f5",
|
||||
"--secondary-cta-text": "#1c1c1c"
|
||||
},
|
||||
"grayNavyBlue": {
|
||||
"--background": "#f5f5f5",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#1c1c1c",
|
||||
"--primary-cta": "#1f3251",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#15479c",
|
||||
"--background-accent": "#a8cce8",
|
||||
"--primary-cta-text": "#f5f5f5",
|
||||
"--secondary-cta-text": "#1c1c1c"
|
||||
},
|
||||
"grayBurgundyRed": {
|
||||
"--background": "#f5f5f5",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#1c1c1c",
|
||||
"--primary-cta": "#511f1f",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#e63946",
|
||||
"--background-accent": "#e8bea8",
|
||||
"--primary-cta-text": "#f5f5f5",
|
||||
"--secondary-cta-text": "#1c1c1c"
|
||||
},
|
||||
"grayIndigoPurple": {
|
||||
"--background": "#f5f5f5",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#1c1c1c",
|
||||
"--primary-cta": "#341f51",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#6139e6",
|
||||
"--background-accent": "#b3a8e8",
|
||||
"--primary-cta-text": "#f5f5f5",
|
||||
"--secondary-cta-text": "#1c1c1c"
|
||||
},
|
||||
"warmgrayPink": {
|
||||
"--background": "#f7f6f7",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#1b0c25",
|
||||
"--primary-cta": "#1b0c25",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#ff93e4",
|
||||
"--background-accent": "#e8a8c3",
|
||||
"--primary-cta-text": "#f7f6f7",
|
||||
"--secondary-cta-text": "#1b0c25"
|
||||
},
|
||||
"warmgrayOrange": {
|
||||
"--background": "#f7f6f7",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#25190c",
|
||||
"--primary-cta": "#ff6207",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#ffce93",
|
||||
"--background-accent": "#e8cfa8",
|
||||
"--primary-cta-text": "#f7f6f7",
|
||||
"--secondary-cta-text": "#25190c"
|
||||
},
|
||||
"warmgrayBlue": {
|
||||
"--background": "#f7f6f7",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#0c1325",
|
||||
"--primary-cta": "#0798ff",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#93c7ff",
|
||||
"--background-accent": "#a8cde8",
|
||||
"--primary-cta-text": "#f7f6f7",
|
||||
"--secondary-cta-text": "#0c1325"
|
||||
},
|
||||
"warmgrayIndigo": {
|
||||
"--background": "#f7f6f7",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#0c1325",
|
||||
"--primary-cta": "#0b07ff",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#93b7ff",
|
||||
"--background-accent": "#a8bae8",
|
||||
"--primary-cta-text": "#f7f6f7",
|
||||
"--secondary-cta-text": "#0c1325"
|
||||
},
|
||||
"lavenderPeach": {
|
||||
"--background": "#e3deea",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#27231f",
|
||||
"--primary-cta": "#27231f",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#c68a62",
|
||||
"--background-accent": "#c68a62",
|
||||
"--primary-cta-text": "#e3deea",
|
||||
"--secondary-cta-text": "#27231f"
|
||||
},
|
||||
"lavenderBlue": {
|
||||
"--background": "#e3deea",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#1f2027",
|
||||
"--primary-cta": "#1f2027",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#627dc6",
|
||||
"--background-accent": "#627dc6",
|
||||
"--primary-cta-text": "#e3deea",
|
||||
"--secondary-cta-text": "#1f2027"
|
||||
},
|
||||
"warmStone": {
|
||||
"--background": "#f5f4ef",
|
||||
"--card": "#dad6cd",
|
||||
"--foreground": "#2a2928",
|
||||
"--primary-cta": "#2a2928",
|
||||
"--secondary-cta": "#ecebea",
|
||||
"--accent": "#ffffff",
|
||||
"--background-accent": "#c6b180",
|
||||
"--primary-cta-text": "#f5f4ef",
|
||||
"--secondary-cta-text": "#2a2928"
|
||||
},
|
||||
"warmStoneGray": {
|
||||
"--background": "#f5f4f0",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#1a1a1a",
|
||||
"--primary-cta": "#2c2c2c",
|
||||
"--secondary-cta": "#f5f4f0",
|
||||
"--accent": "#8a8a8a",
|
||||
"--background-accent": "#e8e6e1",
|
||||
"--primary-cta-text": "#f5f4f0",
|
||||
"--secondary-cta-text": "#1a1a1a"
|
||||
},
|
||||
"warmGreen": {
|
||||
"--background": "#fffefe",
|
||||
"--card": "#f6f7f4",
|
||||
"--foreground": "#080908",
|
||||
"--primary-cta": "#0e3a29",
|
||||
"--secondary-cta": "#e7eecd",
|
||||
"--accent": "#35c18b",
|
||||
"--background-accent": "#ecebe4",
|
||||
"--primary-cta-text": "#fffefe",
|
||||
"--secondary-cta-text": "#080908"
|
||||
},
|
||||
"warmSand": {
|
||||
"--background": "#fcf6ec",
|
||||
"--card": "#f3ede2",
|
||||
"--foreground": "#2e2521",
|
||||
"--primary-cta": "#2e2521",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#b2a28b",
|
||||
"--background-accent": "#b2a28b",
|
||||
"--primary-cta-text": "#fcf6ec",
|
||||
"--secondary-cta-text": "#2e2521"
|
||||
},
|
||||
"warmgrayRed": {
|
||||
"--background": "#f7f6f7",
|
||||
"--card": "#ffffff",
|
||||
"--foreground": "#250c0d",
|
||||
"--primary-cta": "#b82b40",
|
||||
"--secondary-cta": "#ffffff",
|
||||
"--accent": "#b90941",
|
||||
"--background-accent": "#e8a8b6",
|
||||
"--primary-cta-text": "#f7f6f7",
|
||||
"--secondary-cta-text": "#250c0d"
|
||||
}
|
||||
},
|
||||
"darkTheme": {
|
||||
"minimal": {
|
||||
"--background": "#0a0a0a",
|
||||
"--card": "#1a1a1a",
|
||||
"--foreground": "#ffffffe6",
|
||||
"--primary-cta": "#e6e6e6",
|
||||
"--secondary-cta": "#1a1a1a",
|
||||
"--accent": "#737373",
|
||||
"--background-accent": "#737373",
|
||||
"--primary-cta-text": "#0a0a0a",
|
||||
"--secondary-cta-text": "#ffffffe6"
|
||||
},
|
||||
"minimalLightBlue": {
|
||||
"--background": "#0a0a0a",
|
||||
"--card": "#1a1a1a",
|
||||
"--foreground": "#f0f8ffe6",
|
||||
"--primary-cta": "#cee7ff",
|
||||
"--secondary-cta": "#1a1a1a",
|
||||
"--accent": "#737373",
|
||||
"--background-accent": "#737373",
|
||||
"--primary-cta-text": "#0a0a0a",
|
||||
"--secondary-cta-text": "#f0f8ffe6"
|
||||
},
|
||||
"minimalLightGreen": {
|
||||
"--background": "#0a0a0a",
|
||||
"--card": "#1a1a1a",
|
||||
"--foreground": "#f5fffae6",
|
||||
"--primary-cta": "#80da9b",
|
||||
"--secondary-cta": "#1a1a1a",
|
||||
"--accent": "#737373",
|
||||
"--background-accent": "#737373",
|
||||
"--primary-cta-text": "#0a0a0a",
|
||||
"--secondary-cta-text": "#f5fffae6"
|
||||
},
|
||||
"minimalLightRed": {
|
||||
"--background": "#0a0a0a",
|
||||
"--card": "#1a1a1a",
|
||||
"--foreground": "#fff5f5e6",
|
||||
"--primary-cta": "#ff7a7a",
|
||||
"--secondary-cta": "#1a1a1a",
|
||||
"--accent": "#737373",
|
||||
"--background-accent": "#737373",
|
||||
"--primary-cta-text": "#0a0a0a",
|
||||
"--secondary-cta-text": "#fff5f5e6"
|
||||
},
|
||||
"minimalLightPurple": {
|
||||
"--background": "#0a0a0a",
|
||||
"--card": "#1a1a1a",
|
||||
"--foreground": "#f8f5ffe6",
|
||||
"--primary-cta": "#c89bff",
|
||||
"--secondary-cta": "#1a1a1a",
|
||||
"--accent": "#737373",
|
||||
"--background-accent": "#737373",
|
||||
"--primary-cta-text": "#0a0a0a",
|
||||
"--secondary-cta-text": "#f8f5ffe6"
|
||||
},
|
||||
"lightBlueWhite": {
|
||||
"--background": "#010912",
|
||||
"--card": "#152840",
|
||||
"--foreground": "#e6f0ff",
|
||||
"--primary-cta": "#cee7ff",
|
||||
"--secondary-cta": "#0e1a29",
|
||||
"--accent": "#3f5c79",
|
||||
"--background-accent": "#004a93",
|
||||
"--primary-cta-text": "#010912",
|
||||
"--secondary-cta-text": "#ffffff"
|
||||
},
|
||||
"lime": {
|
||||
"--background": "#0a0a0a",
|
||||
"--card": "#1a1a1a",
|
||||
"--foreground": "#f5f5f5",
|
||||
"--primary-cta": "#dfff1c",
|
||||
"--secondary-cta": "#1a1a1a",
|
||||
"--accent": "#8b9a1b",
|
||||
"--background-accent": "#5d6b00",
|
||||
"--primary-cta-text": "#0a0a0a",
|
||||
"--secondary-cta-text": "#ffffff"
|
||||
},
|
||||
"gold": {
|
||||
"--background": "#0a0a0a",
|
||||
"--card": "#1a1a1a",
|
||||
"--foreground": "#f5f5f5",
|
||||
"--primary-cta": "#ffdf7d",
|
||||
"--secondary-cta": "#1a1a1a",
|
||||
"--accent": "#b8860b",
|
||||
"--background-accent": "#8b6914",
|
||||
"--primary-cta-text": "#0a0a0a",
|
||||
"--secondary-cta-text": "#ffffff"
|
||||
},
|
||||
"crimson": {
|
||||
"--background": "#0a0a0a",
|
||||
"--card": "#1a1a1a",
|
||||
"--foreground": "#f5f5f5",
|
||||
"--primary-cta": "#ff0000",
|
||||
"--secondary-cta": "#1a1a1a",
|
||||
"--accent": "#991b1b",
|
||||
"--background-accent": "#7f1d1d",
|
||||
"--primary-cta-text": "#ffffff",
|
||||
"--secondary-cta-text": "#ffffff"
|
||||
},
|
||||
"midnightIce": {
|
||||
"--background": "#000000",
|
||||
"--card": "#0c0c0c",
|
||||
"--foreground": "#ffffff",
|
||||
"--primary-cta": "#cee7ff",
|
||||
"--secondary-cta": "#000000",
|
||||
"--accent": "#535353",
|
||||
"--background-accent": "#CEE7FF",
|
||||
"--primary-cta-text": "#000000",
|
||||
"--secondary-cta-text": "#ffffff"
|
||||
},
|
||||
"midnightBlue": {
|
||||
"--background": "#000000",
|
||||
"--card": "#0c0c0c",
|
||||
"--foreground": "#ffffff",
|
||||
"--primary-cta": "#106EFB",
|
||||
"--secondary-cta": "#000000",
|
||||
"--accent": "#535353",
|
||||
"--background-accent": "#106EFB",
|
||||
"--primary-cta-text": "#ffffff",
|
||||
"--secondary-cta-text": "#ffffff"
|
||||
},
|
||||
"blueOrangeAccent": {
|
||||
"--background": "#0a0a0a",
|
||||
"--card": "#1a1a1a",
|
||||
"--foreground": "#ffffff",
|
||||
"--primary-cta": "#1f7cff",
|
||||
"--secondary-cta": "#010101",
|
||||
"--accent": "#1f7cff",
|
||||
"--background-accent": "#f96b2f",
|
||||
"--primary-cta-text": "#ffffff",
|
||||
"--secondary-cta-text": "#ffffff"
|
||||
},
|
||||
"orangeBlueAccent": {
|
||||
"--background": "#0a0a0a",
|
||||
"--card": "#1a1a1a",
|
||||
"--foreground": "#ffffff",
|
||||
"--primary-cta": "#e34400",
|
||||
"--secondary-cta": "#010101",
|
||||
"--accent": "#ff7b05",
|
||||
"--background-accent": "#106efb",
|
||||
"--primary-cta-text": "#ffffff",
|
||||
"--secondary-cta-text": "#ffffff"
|
||||
},
|
||||
"minimalBrightOrange": {
|
||||
"--background": "#0a0a0a",
|
||||
"--card": "#1a1a1a",
|
||||
"--foreground": "#ffffff",
|
||||
"--primary-cta": "#e34400",
|
||||
"--secondary-cta": "#010101",
|
||||
"--accent": "#737373",
|
||||
"--background-accent": "#e34400",
|
||||
"--primary-cta-text": "#ffffff",
|
||||
"--secondary-cta-text": "#ffffff"
|
||||
},
|
||||
"minimalLightOrange": {
|
||||
"--background": "#0a0a0a",
|
||||
"--card": "#1a1a1a",
|
||||
"--foreground": "#fffaf5e6",
|
||||
"--primary-cta": "#ffaa70",
|
||||
"--secondary-cta": "#1a1a1a",
|
||||
"--accent": "#737373",
|
||||
"--background-accent": "#737373",
|
||||
"--primary-cta-text": "#0a0a0a",
|
||||
"--secondary-cta-text": "#fffaf5e6"
|
||||
},
|
||||
"minimalLightYellow": {
|
||||
"--background": "#0a0a0a",
|
||||
"--card": "#1a1a1a",
|
||||
"--foreground": "#fffffae6",
|
||||
"--primary-cta": "#fde047",
|
||||
"--secondary-cta": "#1a1a1a",
|
||||
"--accent": "#737373",
|
||||
"--background-accent": "#737373",
|
||||
"--primary-cta-text": "#0a0a0a",
|
||||
"--secondary-cta-text": "#fffffae6"
|
||||
},
|
||||
"lightBlue": {
|
||||
"--background": "#010912",
|
||||
"--card": "#152840",
|
||||
"--foreground": "#e6f0ff",
|
||||
"--primary-cta": "#cee7ff",
|
||||
"--secondary-cta": "#0e1a29",
|
||||
"--accent": "#3f5c79",
|
||||
"--background-accent": "#004a93",
|
||||
"--primary-cta-text": "#010912",
|
||||
"--secondary-cta-text": "#e6f0ff"
|
||||
},
|
||||
"lightGreen": {
|
||||
"--background": "#000802",
|
||||
"--card": "#0b1a0b",
|
||||
"--foreground": "#e6ffe6",
|
||||
"--primary-cta": "#80da9b",
|
||||
"--secondary-cta": "#07170b",
|
||||
"--accent": "#38714a",
|
||||
"--background-accent": "#2c6541",
|
||||
"--primary-cta-text": "#000802",
|
||||
"--secondary-cta-text": "#e6ffe6"
|
||||
},
|
||||
"lightRed": {
|
||||
"--background": "#080000",
|
||||
"--card": "#1e0d0d",
|
||||
"--foreground": "#ffe6e6",
|
||||
"--primary-cta": "#ff7a7a",
|
||||
"--secondary-cta": "#1e0909",
|
||||
"--accent": "#7b4242",
|
||||
"--background-accent": "#65292c",
|
||||
"--primary-cta-text": "#080000",
|
||||
"--secondary-cta-text": "#ffe6e6"
|
||||
},
|
||||
"darkRed": {
|
||||
"--background": "#060000",
|
||||
"--card": "#1d0d0d",
|
||||
"--foreground": "#ffe6e6",
|
||||
"--primary-cta": "#ff3d4a",
|
||||
"--secondary-cta": "#1f0a0a",
|
||||
"--accent": "#7b2d2d",
|
||||
"--background-accent": "#b8111f",
|
||||
"--primary-cta-text": "#ffffff",
|
||||
"--secondary-cta-text": "#ffe6e6"
|
||||
},
|
||||
"lightPurple": {
|
||||
"--background": "#050012",
|
||||
"--card": "#040121",
|
||||
"--foreground": "#f0e6ff",
|
||||
"--primary-cta": "#c89bff",
|
||||
"--secondary-cta": "#1d123b",
|
||||
"--accent": "#684f7b",
|
||||
"--background-accent": "#65417c",
|
||||
"--primary-cta-text": "#050012",
|
||||
"--secondary-cta-text": "#f0e6ff"
|
||||
},
|
||||
"lightOrange": {
|
||||
"--background": "#080200",
|
||||
"--card": "#1a0d0b",
|
||||
"--foreground": "#ffe6d5",
|
||||
"--primary-cta": "#ffaa70",
|
||||
"--secondary-cta": "#170b07",
|
||||
"--accent": "#7b5e4a",
|
||||
"--background-accent": "#b8541e",
|
||||
"--primary-cta-text": "#080200",
|
||||
"--secondary-cta-text": "#ffe6d5"
|
||||
},
|
||||
"deepBlue": {
|
||||
"--background": "#020617",
|
||||
"--card": "#0f172a",
|
||||
"--foreground": "#e2e8f0",
|
||||
"--primary-cta": "#c4d8f9",
|
||||
"--secondary-cta": "#041633",
|
||||
"--accent": "#2d30f3",
|
||||
"--background-accent": "#1d4ed8",
|
||||
"--primary-cta-text": "#020617",
|
||||
"--secondary-cta-text": "#e2e8f0"
|
||||
},
|
||||
"violet": {
|
||||
"--background": "#030128",
|
||||
"--card": "#241f48",
|
||||
"--foreground": "#ffffff",
|
||||
"--primary-cta": "#ffffff",
|
||||
"--secondary-cta": "#131136",
|
||||
"--accent": "#44358a",
|
||||
"--background-accent": "#b597fe",
|
||||
"--primary-cta-text": "#030128",
|
||||
"--secondary-cta-text": "#d5d4f6"
|
||||
},
|
||||
"ruby": {
|
||||
"--background": "#000000",
|
||||
"--card": "#481f1f",
|
||||
"--foreground": "#ffffff",
|
||||
"--primary-cta": "#ffffff",
|
||||
"--secondary-cta": "#361311",
|
||||
"--accent": "#51000b",
|
||||
"--background-accent": "#ff2231",
|
||||
"--primary-cta-text": "#280101",
|
||||
"--secondary-cta-text": "#f6d4d4"
|
||||
},
|
||||
"emerald": {
|
||||
"--background": "#000000",
|
||||
"--card": "#1f4035",
|
||||
"--foreground": "#ffffff",
|
||||
"--primary-cta": "#ffffff",
|
||||
"--secondary-cta": "#0d2b1f",
|
||||
"--accent": "#0d5238",
|
||||
"--background-accent": "#10b981",
|
||||
"--primary-cta-text": "#051a12",
|
||||
"--secondary-cta-text": "#d4f6e8"
|
||||
},
|
||||
"indigo": {
|
||||
"--background": "#000000",
|
||||
"--card": "#1f1f40",
|
||||
"--foreground": "#ffffff",
|
||||
"--primary-cta": "#ffffff",
|
||||
"--secondary-cta": "#0d0d2b",
|
||||
"--accent": "#3d2880",
|
||||
"--background-accent": "#663cff",
|
||||
"--primary-cta-text": "#0a051a",
|
||||
"--secondary-cta-text": "#d4d4f6"
|
||||
},
|
||||
"forest": {
|
||||
"--background": "#000000",
|
||||
"--card": "#1a2f1d",
|
||||
"--foreground": "#ffffff",
|
||||
"--primary-cta": "#ffffff",
|
||||
"--secondary-cta": "#0d200f",
|
||||
"--accent": "#1a3d1f",
|
||||
"--background-accent": "#355e3b",
|
||||
"--primary-cta-text": "#0a1a0c",
|
||||
"--secondary-cta-text": "#d4f6d8"
|
||||
},
|
||||
"mint": {
|
||||
"--background": "#000000",
|
||||
"--card": "#1a2a1a",
|
||||
"--foreground": "#ffffff",
|
||||
"--primary-cta": "#ffffff",
|
||||
"--secondary-cta": "#0d1a0d",
|
||||
"--accent": "#2d4a2d",
|
||||
"--background-accent": "#c1e1c1",
|
||||
"--primary-cta-text": "#0a150a",
|
||||
"--secondary-cta-text": "#e1f6e1"
|
||||
}
|
||||
}
|
||||
}
|
||||
500
docs/ACCESSIBILITY.md
Normal file
500
docs/ACCESSIBILITY.md
Normal 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`)
|
||||
489
docs/CARDSTACK_SECTIONS.md
Normal file
489
docs/CARDSTACK_SECTIONS.md
Normal file
@@ -0,0 +1,489 @@
|
||||
# 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 and carousel 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)
|
||||
|
||||
## 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
|
||||
|
||||
## 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
|
||||
433
docs/COMPONENT_IMPLEMENTATION.md
Normal file
433
docs/COMPONENT_IMPLEMENTATION.md
Normal 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
|
||||
499
docs/PREVIEW_PAGE_STANDARDS.md
Normal file
499
docs/PREVIEW_PAGE_STANDARDS.md
Normal 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
|
||||
161
docs/README.md
Normal file
161
docs/README.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# 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
|
||||
|
||||
---
|
||||
|
||||
### 📁 [REGISTRY_FOLDER_STRUCTURE.md](./REGISTRY_FOLDER_STRUCTURE.md)
|
||||
**New folder-based registry structure**
|
||||
|
||||
Load when: Working with files in `/registry/` folder
|
||||
|
||||
Covers:
|
||||
- Folder overview (index.json, intents.json, components/, schemas/)
|
||||
- File purposes and use cases
|
||||
- When to update each file
|
||||
- Common prop patterns (animations, backgrounds, buttons)
|
||||
- Validation checklist for each file type
|
||||
- File relationships and quick reference
|
||||
|
||||
---
|
||||
|
||||
### 📄 [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_FOLDER_STRUCTURE.md` for the new folder structure
|
||||
2. Load `REGISTRY_STANDARDS.md` for documentation rules
|
||||
|
||||
### 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.
|
||||
299
docs/REGISTRY_FOLDER_STRUCTURE.md
Normal file
299
docs/REGISTRY_FOLDER_STRUCTURE.md
Normal file
@@ -0,0 +1,299 @@
|
||||
# Registry Folder Structure
|
||||
|
||||
This document explains the new folder-based registry structure in `/registry/` and how to work with it.
|
||||
|
||||
## Folder Overview
|
||||
|
||||
```
|
||||
registry/
|
||||
├── index.json # Quick lookup index for all components
|
||||
├── intents.json # Intent-based component grouping
|
||||
├── components/ # Full component documentation
|
||||
│ ├── HeroBillboard.json
|
||||
│ ├── FeatureCardOne.json
|
||||
│ └── ...
|
||||
└── schemas/ # Simplified prop schemas
|
||||
├── HeroBillboard.schema.json
|
||||
├── FeatureCardOne.schema.json
|
||||
└── ...
|
||||
```
|
||||
|
||||
## File Purposes
|
||||
|
||||
### index.json
|
||||
|
||||
**Quick lookup index** for component discovery and selection.
|
||||
|
||||
**Use case:** AI builders use this to find the right component for a given intent.
|
||||
|
||||
```json
|
||||
{
|
||||
"HeroBillboard": {
|
||||
"category": "hero",
|
||||
"intent": "hero with media",
|
||||
"bestFor": ["landing pages", "feature showcases", "capability displays"],
|
||||
"avoidWhen": ["multiple items"],
|
||||
"requires": ["buttons?[]"],
|
||||
"import": "@/components/sections/hero/HeroBillboard"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Fields:**
|
||||
- `category` - Component category (hero, feature, pricing, team, etc.)
|
||||
- `intent` - Primary use case
|
||||
- `bestFor` - Ideal scenarios for this component
|
||||
- `avoidWhen` - When NOT to use this component
|
||||
- `requires` - Required prop arrays (use `?[]` for optional)
|
||||
- `import` - Import path for the component
|
||||
|
||||
---
|
||||
|
||||
### intents.json
|
||||
|
||||
**Intent-based grouping** for semantic component discovery.
|
||||
|
||||
**Use case:** AI builders use this to find all components that match a specific intent.
|
||||
|
||||
```json
|
||||
{
|
||||
"hero with media": [
|
||||
"HeroBillboard",
|
||||
"HeroBillboardCarousel",
|
||||
"HeroSplit",
|
||||
"HeroOverlay"
|
||||
],
|
||||
"feature showcase": [
|
||||
"FeatureCardOne",
|
||||
"FeatureCardThree",
|
||||
"FeatureBento"
|
||||
],
|
||||
"testimonials": [
|
||||
"TestimonialCardOne",
|
||||
"TestimonialCardTwo"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Common intents:**
|
||||
- `hero with media` - Hero sections with images/videos
|
||||
- `feature showcase` - Feature display sections
|
||||
- `testimonials` - Customer testimonial sections
|
||||
- `sequential process` - Step-by-step or timeline sections
|
||||
- `metrics display` - Statistics and KPI sections
|
||||
- `contact form` - Contact and CTA sections
|
||||
- `pricing plans` - Pricing tier sections
|
||||
|
||||
---
|
||||
|
||||
### components/*.json
|
||||
|
||||
**Full component documentation** with constraints, examples, and rules.
|
||||
|
||||
**Use case:** AI builders use this for detailed implementation guidance.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "HeroBillboard",
|
||||
"description": "Full-width hero section with centered text content...",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Welcome to Our Platform",
|
||||
"minChars": 2,
|
||||
"maxChars": 36
|
||||
}
|
||||
},
|
||||
"mediaRules": {...},
|
||||
"buttonRules": {...}
|
||||
},
|
||||
"propsSchema": {
|
||||
"title": "string",
|
||||
"description": "string",
|
||||
"tag?": "string",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"mediaAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'"
|
||||
},
|
||||
"usageExample": "<HeroBillboard title=\"...\" ... />",
|
||||
"do": ["Use for landing pages", "Use for feature showcases"],
|
||||
"dont": ["Do not use multiple items"],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Sections:**
|
||||
- `name` - Component name
|
||||
- `description` - Brief component description
|
||||
- `constraints` - Text length limits, media rules, button rules
|
||||
- `propsSchema` - All props with types and defaults
|
||||
- `usageExample` - Complete usage example with ThemeProvider
|
||||
- `do` - Recommended use cases
|
||||
- `dont` - Anti-patterns to avoid
|
||||
- `editRules` - What can/cannot be customized
|
||||
|
||||
---
|
||||
|
||||
### schemas/*.schema.json
|
||||
|
||||
**Simplified prop schemas** for quick reference.
|
||||
|
||||
**Use case:** AI builders use this for prop validation and code generation.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "HeroBillboard",
|
||||
"propsSchema": {
|
||||
"title": "string",
|
||||
"description": "string",
|
||||
"background": "{ variant: 'plain' | 'animated-grid' | ... } (required)",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"mediaAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"titleClassName?": "string"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Note:** Schema files include ALL className props while component files may omit them for brevity.
|
||||
|
||||
---
|
||||
|
||||
## When to Update Each File
|
||||
|
||||
### Adding a New Component
|
||||
|
||||
1. Add entry to `index.json` with category, intent, bestFor, avoidWhen, requires, import
|
||||
2. Add component name to appropriate intent(s) in `intents.json`
|
||||
3. Create `components/ComponentName.json` with full documentation
|
||||
4. Create `schemas/ComponentName.schema.json` with prop schema
|
||||
|
||||
### Adding a New Prop
|
||||
|
||||
1. Update `components/ComponentName.json` propsSchema
|
||||
2. Update `schemas/ComponentName.schema.json` propsSchema
|
||||
3. If prop affects usage, update `usageExample` in component file
|
||||
|
||||
### Modifying Constraints
|
||||
|
||||
1. Only update `components/ComponentName.json` constraints section
|
||||
|
||||
### Changing Component Intent/Category
|
||||
|
||||
1. Update `index.json` entry
|
||||
2. Move component name between arrays in `intents.json`
|
||||
|
||||
---
|
||||
|
||||
## Common Prop Patterns
|
||||
|
||||
### Animation Props
|
||||
|
||||
All animation props follow the same pattern:
|
||||
|
||||
```json
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"mediaAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'"
|
||||
```
|
||||
|
||||
### Background Props
|
||||
|
||||
Hero sections use background variant:
|
||||
|
||||
```json
|
||||
"background": "{ variant: 'plain' | 'animated-grid' | 'canvas-reveal' | 'cell-wave' | 'downward-rays-animated' | ... } (required)"
|
||||
```
|
||||
|
||||
### Button Config
|
||||
|
||||
Standard button array structure:
|
||||
|
||||
```json
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>"
|
||||
```
|
||||
|
||||
### ClassName Props
|
||||
|
||||
Always include standard className props in schema files:
|
||||
|
||||
```json
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"descriptionClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"buttonContainerClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "string",
|
||||
"mediaWrapperClassName?": "string",
|
||||
"imageClassName?": "string"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
When updating registry files:
|
||||
|
||||
### index.json
|
||||
- [ ] Category matches component type
|
||||
- [ ] Intent matches primary use case
|
||||
- [ ] bestFor list is comprehensive
|
||||
- [ ] avoidWhen captures real limitations
|
||||
- [ ] requires uses `?[]` for optional arrays
|
||||
- [ ] import path is correct
|
||||
|
||||
### intents.json
|
||||
- [ ] Component is listed under correct intent(s)
|
||||
- [ ] No duplicate entries
|
||||
- [ ] Intent names are consistent
|
||||
|
||||
### components/*.json
|
||||
- [ ] name matches filename
|
||||
- [ ] description is concise
|
||||
- [ ] constraints have realistic examples
|
||||
- [ ] propsSchema matches component interface
|
||||
- [ ] usageExample is valid JSX
|
||||
- [ ] do/dont provide useful guidance
|
||||
- [ ] editRules are accurate
|
||||
|
||||
### schemas/*.schema.json
|
||||
- [ ] name matches filename
|
||||
- [ ] propsSchema matches component file
|
||||
- [ ] All className props included
|
||||
- [ ] Optional props use `?` suffix
|
||||
- [ ] Defaults noted with `(default: value)`
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference: File Relationships
|
||||
|
||||
```
|
||||
Component: HeroBillboard
|
||||
|
||||
registry/
|
||||
├── index.json
|
||||
│ └── "HeroBillboard": { category, intent, bestFor, ... }
|
||||
│
|
||||
├── intents.json
|
||||
│ └── "hero with media": ["HeroBillboard", ...]
|
||||
│
|
||||
├── components/HeroBillboard.json
|
||||
│ └── Full documentation with constraints, examples, rules
|
||||
│
|
||||
└── schemas/HeroBillboard.schema.json
|
||||
└── Simplified propsSchema for code generation
|
||||
```
|
||||
487
docs/REGISTRY_STANDARDS.md
Normal file
487
docs/REGISTRY_STANDARDS.md
Normal 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
521
docs/THEME_AND_STYLING.md
Normal 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
55
eslint.config.mjs
Normal 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",
|
||||
],
|
||||
}
|
||||
);
|
||||
237
fontThemes.json
Normal file
237
fontThemes.json
Normal file
@@ -0,0 +1,237 @@
|
||||
{
|
||||
"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;"
|
||||
},
|
||||
"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;"
|
||||
},
|
||||
"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;"
|
||||
},
|
||||
"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;"
|
||||
},
|
||||
"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;"
|
||||
},
|
||||
"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;"
|
||||
},
|
||||
"nunito": {
|
||||
"name": "Nunito",
|
||||
"import": "import { Nunito } from \"next/font/google\";",
|
||||
"initialization": "const nunito = Nunito({\n variable: \"--font-nunito\",\n subsets: [\"latin\"],\n});",
|
||||
"className": "${nunito.variable}",
|
||||
"cssVariable": "font-family: var(--font-nunito), sans-serif;"
|
||||
},
|
||||
"nunitoSans": {
|
||||
"name": "Nunito Sans",
|
||||
"import": "import { Nunito_Sans } from \"next/font/google\";",
|
||||
"initialization": "const nunitoSans = Nunito_Sans({\n variable: \"--font-nunito-sans\",\n subsets: [\"latin\"],\n});",
|
||||
"className": "${nunitoSans.variable}",
|
||||
"cssVariable": "font-family: var(--font-nunito-sans), sans-serif;"
|
||||
},
|
||||
"raleway": {
|
||||
"name": "Raleway",
|
||||
"import": "import { Raleway } from \"next/font/google\";",
|
||||
"initialization": "const raleway = Raleway({\n variable: \"--font-raleway\",\n subsets: [\"latin\"],\n});",
|
||||
"className": "${raleway.variable}",
|
||||
"cssVariable": "font-family: var(--font-raleway), sans-serif;"
|
||||
},
|
||||
"archivo": {
|
||||
"name": "Archivo",
|
||||
"import": "import { Archivo } from \"next/font/google\";",
|
||||
"initialization": "const archivo = Archivo({\n variable: \"--font-archivo\",\n subsets: [\"latin\"],\n});",
|
||||
"className": "${archivo.variable}",
|
||||
"cssVariable": "font-family: var(--font-archivo), sans-serif;"
|
||||
},
|
||||
"figtree": {
|
||||
"name": "Figtree",
|
||||
"import": "import { Figtree } from \"next/font/google\";",
|
||||
"initialization": "const figtree = Figtree({\n variable: \"--font-figtree\",\n subsets: [\"latin\"],\n});",
|
||||
"className": "${figtree.variable}",
|
||||
"cssVariable": "font-family: var(--font-figtree), 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"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"libreBaskervilleInter": {
|
||||
"name": "Libre Baskerville + Inter",
|
||||
"description": "Classic serif headings with neutral body. Elegant and readable.",
|
||||
"headingFont": "libreBaskerville",
|
||||
"bodyFont": "inter",
|
||||
"imports": "import { Libre_Baskerville } from \"next/font/google\";\nimport { Inter } from \"next/font/google\";",
|
||||
"initializations": "const libreBaskerville = Libre_Baskerville({\n variable: \"--font-libre-baskerville\",\n subsets: [\"latin\"],\n weight: [\"400\", \"700\"],\n});\n\nconst inter = Inter({\n variable: \"--font-inter\",\n subsets: [\"latin\"],\n});",
|
||||
"classNames": "${libreBaskerville.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-libre-baskerville), serif;\n}",
|
||||
"bodyFontFamily": "var(--font-inter), sans-serif",
|
||||
"headingsFontFamily": "var(--font-libre-baskerville), serif"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
6
next-env.d.ts
vendored
Normal file
6
next-env.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
import "./.next/types/routes.d.ts";
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||
32
next.config.ts
Normal file
32
next.config.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
allowedDevOrigins: ["*.sandbox-staging.webild.io", "*.webildsbx.cc", "*.webild.io"],
|
||||
devIndicators: false,
|
||||
experimental: {
|
||||
serverComponentsHmrCache: false,
|
||||
},
|
||||
images: {
|
||||
localPatterns: [
|
||||
{
|
||||
pathname: '/**',
|
||||
},
|
||||
],
|
||||
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;
|
||||
8321
package-lock.json
generated
Normal file
8321
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
47
package.json
Normal file
47
package.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "webild-components-2",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"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",
|
||||
"@rive-app/react-canvas": "^4.26.2",
|
||||
"@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
5
postcss.config.mjs
Normal file
@@ -0,0 +1,5 @@
|
||||
const config = {
|
||||
plugins: ["@tailwindcss/postcss"],
|
||||
};
|
||||
|
||||
export default config;
|
||||
4767
registry.json
Normal file
4767
registry.json
Normal file
File diff suppressed because it is too large
Load Diff
58
registry/components/AboutMetric.json
Normal file
58
registry/components/AboutMetric.json
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "AboutMetric",
|
||||
"description": "About section with centered animated title and metric cards in a responsive grid.",
|
||||
"details": "Use for showcasing company metrics, achievements, and statistics with visual impact. Features centered large animated title (2xl on mobile, 5xl on desktop) using words-trigger variant with theme's default text animation. Displays 2-4 metric cards in a responsive grid (1 column mobile, 2-4 columns desktop based on metric count). Each card includes an icon in a primary-button styled container, metric label, and large value text (6xl). Cards have fixed height (h-fit with py-8 md:py-10), rounded-theme-capped borders, and centered content. Perfect for highlighting key business achievements, statistics, or milestones.",
|
||||
"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 }>",
|
||||
"metricsAnimation": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"useInvertedBackground": "boolean",
|
||||
"ariaLabel?": "string (default: 'About metrics section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"metricsContainerClassName?": "string",
|
||||
"metricCardClassName?": "string",
|
||||
"metricIconClassName?": "string",
|
||||
"metricLabelClassName?": "string",
|
||||
"metricValueClassName?": "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={false}\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
|
||||
}
|
||||
}
|
||||
22
registry/components/AnimatedAuroraBackground.json
Normal file
22
registry/components/AnimatedAuroraBackground.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "AnimatedAuroraBackground",
|
||||
"description": "Aurora borealis effect with animated repeating gradients and mix-blend-difference.",
|
||||
"details": "Use for premium, vibrant backgrounds with flowing aurora animation. Features repeating linear gradients with theme colors (primary-cta, accent, secondary-cta) that animate across the screen. Uses background color for base gradient with 10px blur filter. Optional radial gradient mask (default: true) creates elliptical spotlight effect from top-right. Uses mix-blend-difference blend mode and after pseudo-element for layered animation. Requires aurora keyframes animation in globals.css. Set invertColors to true for light backgrounds, false for dark backgrounds.",
|
||||
"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
|
||||
}
|
||||
}
|
||||
25
registry/components/AnimatedGridBackground.json
Normal file
25
registry/components/AnimatedGridBackground.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "AnimatedGridBackground",
|
||||
"description": "Grid pattern with animated pulsing squares using Framer Motion with 3D perspective and radial mask from top center.",
|
||||
"details": "Use for modern, interactive backgrounds with subtle animation. Features SVG grid with randomly positioned squares that pulse in opacity. Includes 3D perspective with skew transform (skew-y-12) and stretched height (200%). Radial gradient mask positioned at top center (ellipse 100% 100% at 50% 0%) creates a dome-shaped spotlight effect fading towards edges and bottom. Uses accent color for grid lines (20% opacity) and background-accent for animated squares. Perfect for hero sections where grid should be most prominent at top. Requires 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
|
||||
}
|
||||
}
|
||||
21
registry/components/AuroraBackground.json
Normal file
21
registry/components/AuroraBackground.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "AuroraBackground",
|
||||
"description": "Aurora borealis-style background with multiple rotated gradient bars and blur effect.",
|
||||
"details": "Use for premium, visually striking hero sections or landing pages. Features 5 rotated gradient bars with backdrop-blur-3xl overlay creating an aurora effect. Uses background-accent color at varying opacities (5-10%). Fixed positioning with z-0.",
|
||||
"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
|
||||
}
|
||||
}
|
||||
36
registry/components/AvatarGroup.json
Normal file
36
registry/components/AvatarGroup.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "AvatarGroup",
|
||||
"description": "Displays a group of user avatars with overlapping layout and optional text label.",
|
||||
"details": "Use for showing user participation, testimonials, or social proof. Displays up to 5 avatars by default with remaining count badge. Avatars overlap with card styling. Includes optional text label (e.g., 'Join 1,000+ members').",
|
||||
"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",
|
||||
"avatarClassName?": "string",
|
||||
"textClassName?": "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
|
||||
}
|
||||
}
|
||||
28
registry/components/BentoGlobe.json
Normal file
28
registry/components/BentoGlobe.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "BentoGlobe",
|
||||
"description": "Interactive 3D rotating globe component using COBE library with theme-aware colors and customizable markers.",
|
||||
"details": "Use for showcasing global presence, international reach, or geographic data. Features auto-rotating 3D globe with location markers. Colors automatically sync with theme CSS variables (--card for base/glow, --primary-cta for markers). Fully customizable via COBEOptions config. Includes default world markers. Responsive with smooth opacity fade-in. Requires 'cobe' package. Best used within a card container with fixed dimensions.",
|
||||
"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": "<BentoGlobe 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
|
||||
}
|
||||
}
|
||||
90
registry/components/BlogCardOne.json
Normal file
90
registry/components/BlogCardOne.json
Normal file
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"name": "BlogCardOne",
|
||||
"description": "Blog section with card grid/carousel layout featuring image, category, title, excerpt, and author info.",
|
||||
"details": "Use for displaying blog posts or articles. Uses CardStack for adaptive layout (grid for 1-4 items, carousel for 5+). Card structure: Image with overlay arrow button → Category badge → Title → Excerpt → Author (avatar + name + date). Image has zoom effect on hover. Category displayed in primary-button badge. Optional header with title, description, tag, and buttons via CardStack. Best for blog pages, news sections, or article listings.",
|
||||
"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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"ariaLabel?": "string (default: 'Blog section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"imageWrapperClassName?": "string",
|
||||
"imageClassName?": "string",
|
||||
"categoryClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"excerptClassName?": "string",
|
||||
"authorContainerClassName?": "string",
|
||||
"authorAvatarClassName?": "string",
|
||||
"authorNameClassName?": "string",
|
||||
"dateClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxTitleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"textBoxTitleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"gridClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"controlsClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "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={false} 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
|
||||
}
|
||||
}
|
||||
94
registry/components/BlogCardThree.json
Normal file
94
registry/components/BlogCardThree.json
Normal file
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"name": "BlogCardThree",
|
||||
"description": "Blog section with vertical card layout featuring tag, title, excerpt, optional author info, and media with overlay button.",
|
||||
"details": "Use for featured blog posts with prominent visual layout. Uses CardStack for adaptive layout (grid for 1-4 items, carousel for 5+). Card structure: Tag → Title → Excerpt → Optional Author (avatar + name + date) → Media content with overlay arrow button. Author info is optional and displays only when authorName or date is provided. Best for hero blog sections or featured articles.",
|
||||
"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-[600px]')",
|
||||
"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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"ariaLabel?": "string (default: 'Blog section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"cardContentClassName?": "string",
|
||||
"categoryTagClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"excerptClassName?": "string",
|
||||
"authorContainerClassName?": "string",
|
||||
"authorAvatarClassName?": "string",
|
||||
"authorNameClassName?": "string",
|
||||
"dateClassName?": "string",
|
||||
"mediaWrapperClassName?": "string",
|
||||
"mediaClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxTitleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"textBoxTitleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"gridClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"controlsClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "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', authorName: 'Alex Chen', authorAvatar: '/avatar.jpg', date: 'Jan 15, 2025', onBlogClick: () => console.log('clicked')}]} title=\"Featured Articles\" description=\"Explore our latest insights\" textboxLayout=\"default\" useInvertedBackground={false} 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
|
||||
}
|
||||
}
|
||||
88
registry/components/BlogCardTwo.json
Normal file
88
registry/components/BlogCardTwo.json
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"name": "BlogCardTwo",
|
||||
"description": "Blog section with card grid/carousel layout featuring image, optional author avatar, author/date, title, excerpt, and category badge(s).",
|
||||
"details": "Use for displaying blog posts with category categorization. Uses CardStack for adaptive layout (grid for 1-4 items, carousel for 5+). Card structure: Image with overlay arrow button → Optional Author Avatar + Author & Date → Title → Excerpt → Category badge(s). Image has zoom effect on hover. Category supports single string or array for multiple badges displayed as primary-button badges at bottom. Author avatar is optional. Optional header with title, description, tag, and buttons via CardStack. Best for blog pages with category filtering.",
|
||||
"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\", \"authorAvatar\": \"/avatar.jpg\", \"date\": \"20 Jan 2025\"}]",
|
||||
"note": "Array of blog items. Each item requires id, category (string or string[]), title, excerpt, imageSrc, authorName, and date. authorAvatar is optional."
|
||||
}
|
||||
}
|
||||
},
|
||||
"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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"ariaLabel?": "string (default: 'Blog section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"imageWrapperClassName?": "string",
|
||||
"imageClassName?": "string",
|
||||
"authorAvatarClassName?": "string",
|
||||
"authorDateClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"excerptClassName?": "string",
|
||||
"categoryClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxTitleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"textBoxTitleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"gridClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"controlsClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string"
|
||||
},
|
||||
"usageExample": "<BlogCardTwo blogs={[{id: '1', category: ['Design', 'Research'], title: 'UX review presentations', excerpt: 'How to create compelling presentations that wow your audience', imageSrc: '/blog-1.jpg', authorName: 'Olivia Rhye', authorAvatar: '/avatar.jpg', date: '20 Jan 2025', onBlogClick: () => console.log('clicked')}]} title=\"Latest Articles\" description=\"Stay updated with our latest insights\" textboxLayout=\"default\" useInvertedBackground={false} 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
|
||||
}
|
||||
}
|
||||
20
registry/components/BlurBottomBackground.json
Normal file
20
registry/components/BlurBottomBackground.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "BlurBottomBackground",
|
||||
"description": "Backdrop blur effect positioned at the bottom of the page with linear gradient mask.",
|
||||
"details": "Use for clean, minimal backgrounds with a subtle blur effect at the bottom of the page. Features fixed positioning with backdrop-blur-sm effect at the bottom using linear gradient mask (to bottom, transparent to black 60%). The blur is h-50 in height, fixed at bottom-left (left-0 bottom-0). Creates a frosted glass effect rising from the bottom of the page. Useful for creating depth and visual interest on pages with bottom-aligned content or CTAs without adding background color.",
|
||||
"constraints": {},
|
||||
"propsSchema": {
|
||||
"className?": "string"
|
||||
},
|
||||
"usageExample": "<BlurBottomBackground />",
|
||||
"do": [
|
||||
"Use for feature showcases",
|
||||
"Use for capability displays"
|
||||
],
|
||||
"dont": [],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
36
registry/components/ButtonBounceEffect.json
Normal file
36
registry/components/ButtonBounceEffect.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "ButtonBounceEffect",
|
||||
"description": "CTA button with bouncing character animation on hover.",
|
||||
"details": "Use for primary or secondary CTAs where playful motion adds personality. On hover, each character bounces with a slight delay creating a wave effect. Includes background styling with bgClassName.",
|
||||
"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",
|
||||
"className?": "string",
|
||||
"bgClassName?": "string",
|
||||
"textClassName?": "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
|
||||
}
|
||||
}
|
||||
37
registry/components/ButtonDirectionalHover.json
Normal file
37
registry/components/ButtonDirectionalHover.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "ButtonDirectionalHover",
|
||||
"description": "CTA button with a circle that expands from the mouse entry point on hover.",
|
||||
"details": "Use for CTAs where directional awareness adds visual interest. On hover, a circle expands from where the cursor entered the button, creating a fluid reveal effect. The circleClassName controls the expanding circle color (bg-accent for primary, bg-accent/10 for secondary).",
|
||||
"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",
|
||||
"className?": "string",
|
||||
"bgClassName?": "string",
|
||||
"textClassName?": "string",
|
||||
"circleClassName?": "string - Controls the expanding circle color",
|
||||
"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
|
||||
}
|
||||
}
|
||||
35
registry/components/ButtonElasticEffect.json
Normal file
35
registry/components/ButtonElasticEffect.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "ButtonElasticEffect",
|
||||
"description": "CTA button with elastic scale animation on hover.",
|
||||
"details": "Use for CTAs where a springy, elastic feel adds playfulness. On hover, the button scales with an elastic easing that overshoots and settles, creating a bouncy tactile response.",
|
||||
"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",
|
||||
"className?": "string",
|
||||
"textClassName?": "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
|
||||
}
|
||||
}
|
||||
37
registry/components/ButtonExpandHover.json
Normal file
37
registry/components/ButtonExpandHover.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "ButtonExpandHover",
|
||||
"description": "CTA button with expanding background animation from right to left on hover, with a fixed arrow icon.",
|
||||
"details": "Use for CTAs where a smooth expanding effect adds visual interest. On hover (desktop only), the background expands from right to left across the button while the text transitions color. The arrow icon remains fixed on the right side throughout the animation. Mobile shows static button. Uses className for base button styling (primary-button or secondary-button), with iconClassName for arrow icon color and iconBgClassName for expanding background (automatically set via buttonUtils.ts).",
|
||||
"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",
|
||||
"className?": "string",
|
||||
"textClassName?": "string - Applied to the text span (automatically includes base and hover colors in sections)",
|
||||
"iconClassName?": "string - Applied to the arrow icon container (automatically set in sections)",
|
||||
"iconBgClassName?": "string - Applied to the expanding background (automatically set in sections)",
|
||||
"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
|
||||
}
|
||||
}
|
||||
37
registry/components/ButtonHoverBubble.json
Normal file
37
registry/components/ButtonHoverBubble.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "ButtonHoverBubble",
|
||||
"description": "CTA button with expanding bubble animation where an arrow icon slides out and the text expands on hover.",
|
||||
"details": "Use for CTAs where a playful expansion effect adds emphasis. On hover (desktop only), a circular arrow icon expands from the left while the text container slides into view. The initial state shows just the arrow on the right which transforms into the full button. Mobile shows static full button. Uses bgClassName for text container (primary-button for primary, secondary-button for secondary) and iconClassName for arrow icons (automatically set via buttonUtils.ts).",
|
||||
"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",
|
||||
"className?": "string",
|
||||
"bgClassName?": "string - Applied to the text container (automatically set in sections)",
|
||||
"textClassName?": "string - Applied to the text span",
|
||||
"iconClassName?": "string - Applied to both arrow icon containers (automatically set in sections)",
|
||||
"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
|
||||
}
|
||||
}
|
||||
36
registry/components/ButtonHoverMagnetic.json
Normal file
36
registry/components/ButtonHoverMagnetic.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "ButtonHoverMagnetic",
|
||||
"description": "CTA button that subtly follows the cursor with a magnetic hover effect.",
|
||||
"details": "Use when you want a playful, high-affordance interaction. On hover, the button shifts toward the cursor and recenters on leave. Keep labels short; no multiline.",
|
||||
"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",
|
||||
"className?": "string",
|
||||
"textClassName?": "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
|
||||
}
|
||||
}
|
||||
36
registry/components/ButtonIconArrow.json
Normal file
36
registry/components/ButtonIconArrow.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "ButtonIconArrow",
|
||||
"description": "Button with a trailing arrow icon that transforms on hover.",
|
||||
"details": "Use for CTAs where a subtle icon transformation helps indicate forward navigation. The arrow icon transitions into a square on hover/focus. Keep label short and simple.",
|
||||
"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",
|
||||
"className?": "string",
|
||||
"textClassName?": "string",
|
||||
"iconClassName?": "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
|
||||
}
|
||||
}
|
||||
38
registry/components/ButtonShiftHover.json
Normal file
38
registry/components/ButtonShiftHover.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "ButtonShiftHover",
|
||||
"description": "CTA button where the label nudges upward on hover and a trailing dot fills from outline to solid.",
|
||||
"details": "Use for primary or secondary CTAs that benefit from a gentle motion cue. Keep the label short and single‑line. The trailing dot is purely decorative and fills 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",
|
||||
"className?": "string",
|
||||
"bgClassName?": "string",
|
||||
"textClassName?": "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
|
||||
}
|
||||
}
|
||||
36
registry/components/ButtonTextShift.json
Normal file
36
registry/components/ButtonTextShift.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "ButtonTextShift",
|
||||
"description": "CTA button with synchronized character shift animation on hover.",
|
||||
"details": "Use for primary or secondary CTAs where uniform text motion adds emphasis. Similar to ButtonTextStagger but all characters shift together simultaneously instead of in sequence. Includes background styling with bgClassName.",
|
||||
"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",
|
||||
"className?": "string",
|
||||
"bgClassName?": "string",
|
||||
"textClassName?": "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
|
||||
}
|
||||
}
|
||||
37
registry/components/ButtonTextStagger.json
Normal file
37
registry/components/ButtonTextStagger.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "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": 25
|
||||
}
|
||||
}
|
||||
},
|
||||
"propsSchema": {
|
||||
"text": "string",
|
||||
"onClick?": "() => void",
|
||||
"href?": "string - External URLs open in new tab, internal values scroll to section",
|
||||
"className?": "string",
|
||||
"bgClassName?": "string",
|
||||
"textClassName?": "string",
|
||||
"disabled?": "boolean (default: false)",
|
||||
"ariaLabel?": "string",
|
||||
"type?": "'button' | 'submit' | 'reset' (default: 'button')",
|
||||
"scrollToSection?": "boolean"
|
||||
},
|
||||
"usageExample": "<ButtonTextStagger text=\"Get Started\" href=\"https://example.com\" />",
|
||||
"do": [
|
||||
"Use for general use"
|
||||
],
|
||||
"dont": [],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
34
registry/components/ButtonTextUnderline.json
Normal file
34
registry/components/ButtonTextUnderline.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "ButtonTextUnderline",
|
||||
"description": "Text-only button where an underline animates in on hover.",
|
||||
"details": "Use for inline or minimal CTAs or links where you want the hover state to reveal affordance without altering color or layout. The underline appears smoothly under the label when hovered.",
|
||||
"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",
|
||||
"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
|
||||
}
|
||||
}
|
||||
77
registry/components/CardStack.json
Normal file
77
registry/components/CardStack.json
Normal file
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"name": "CardStack",
|
||||
"description": "Adaptive layout component that displays children in a grid or carousel based on item count.",
|
||||
"details": "Use for displaying collections of cards. Automatically switches between grid (1-4 items) and carousel (5+ items). Carousel offers auto-scroll or button controls (recommended: keep default buttons). Optional header supports centered or split textbox layout (split: tag + title + description left, buttons right; split-actions: tag + title left, buttons only right; split-description: tag + title left, description only right).",
|
||||
"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' | 'two-items-per-row' (default: 'uniform-all-items-equal')",
|
||||
"uniformGridCustomHeightClasses?": "string",
|
||||
"gridRowsClassName?": "string",
|
||||
"itemHeightClassesOverride?": "Array<string>",
|
||||
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' | 'depth-3d' (required - controls GSAP scroll animations with stagger effect)",
|
||||
"supports3DAnimation?": "boolean (default: false)",
|
||||
"carouselThreshold?": "number (default: 5)",
|
||||
"bottomContent?": "React.ReactNode",
|
||||
"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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground?": "boolean",
|
||||
"ariaLabel?": "string (default: 'Card stack')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"gridClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"carouselItemClassName?": "string",
|
||||
"controlsClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"titleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"descriptionClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"buttonContainerClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "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
|
||||
}
|
||||
}
|
||||
21
registry/components/CircleGradientBackground.json
Normal file
21
registry/components/CircleGradientBackground.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "CircleGradientBackground",
|
||||
"description": "Two large gradient circles positioned diagonally in corners.",
|
||||
"details": "Use for soft, modern backgrounds with subtle color accents. Features two blurred gradient circles in diagonal corners (primary: top-right + bottom-left, secondary: top-left + bottom-right). Circles are responsive (w-100 mobile, md:w-70 desktop) with 10% opacity. Uses background-accent color.",
|
||||
"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
|
||||
}
|
||||
}
|
||||
70
registry/components/ContactCTA.json
Normal file
70
registry/components/ContactCTA.json
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"name": "ContactCTA",
|
||||
"description": "Centered contact CTA section with tag, title, description, and action buttons in a card container with background support.",
|
||||
"details": "Use for call-to-action contact sections with full textbox support. Features a centered card layout with tag (optional icon), title, description, and buttons. Supports multiple background variants through HeroBackgrounds. Best for conversion-focused contact sections at the end of pages.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"tag": {
|
||||
"required": true,
|
||||
"example": "Get in Touch",
|
||||
"minChars": 2,
|
||||
"maxChars": 30
|
||||
},
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Ready to Build Your Next Project?",
|
||||
"minChars": 5,
|
||||
"maxChars": 100
|
||||
},
|
||||
"description": {
|
||||
"required": true,
|
||||
"example": "Let's work together to create something amazing. Our team is ready to help you bring your vision to life.",
|
||||
"minChars": 10,
|
||||
"maxChars": 300
|
||||
}
|
||||
},
|
||||
"buttonRules": {
|
||||
"maxButtons": 2,
|
||||
"required": true,
|
||||
"note": "At least one button is required. Supports up to 2 buttons with gap-4 spacing."
|
||||
}
|
||||
},
|
||||
"propsSchema": {
|
||||
"tag": "string (required)",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"title": "string (required)",
|
||||
"description": "string (required)",
|
||||
"buttons": "Array<{text: string, onClick?: () => void, href?: string}> (required)",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"background": "ContactCTABackgroundProps = { 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' }",
|
||||
"useInvertedBackground": "boolean",
|
||||
"ariaLabel?": "string (default: 'Contact section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"contentClassName?": "string - Card content wrapper styling",
|
||||
"textBoxClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"descriptionClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"buttonContainerClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "string"
|
||||
},
|
||||
"usageExample": "<ContactCTA tag=\"Get in Touch\" tagIcon={Mail} title=\"Ready to Build Your Next Project?\" description=\"Let's work together to create something amazing.\" buttons={[{ text: 'Contact Us', href: '/contact' }, { text: 'View Portfolio', href: '/portfolio' }]} background={{ variant: 'plain' }} useInvertedBackground={false} />",
|
||||
"do": [
|
||||
"Use for call-to-action contact sections",
|
||||
"Place at the end of pages for conversion",
|
||||
"Use with appropriate background variant",
|
||||
"Requires at least one button"
|
||||
],
|
||||
"dont": [
|
||||
"Do not use without buttons",
|
||||
"Do not use for general content sections"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
87
registry/components/ContactCenter.json
Normal file
87
registry/components/ContactCenter.json
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"name": "ContactCenter",
|
||||
"description": "Centered contact section with tag, animated title and description, email signup form, and terms text.",
|
||||
"details": "Use for newsletter signups, contact forms, or email capture. Features centered layout with tag (with optional icon), animated title and description using ThemeProvider's defaultTextAnimation, EmailSignupForm component, and customizable terms text. Content is placed in a card container with rounded-theme-capped styling. Ideal for prominently placed contact/signup sections with strong visual emphasis.",
|
||||
"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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"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' }",
|
||||
"useInvertedBackground": "boolean",
|
||||
"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",
|
||||
"containerClassName?": "string",
|
||||
"contentClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"descriptionClassName?": "string",
|
||||
"formWrapperClassName?": "string",
|
||||
"formClassName?": "string",
|
||||
"inputClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "string",
|
||||
"termsClassName?": "string"
|
||||
},
|
||||
"usageExample": "<ContactCenter tag=\"Newsletter\" title=\"Stay updated with our latest news\" description=\"Subscribe to our newsletter for weekly updates and exclusive content.\" background={{ variant: 'rotated-rays-animated-grid' }} useInvertedBackground={false} onSubmit={(email) => console.log(email)} />",
|
||||
"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
|
||||
}
|
||||
}
|
||||
83
registry/components/ContactForm.json
Normal file
83
registry/components/ContactForm.json
Normal file
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"name": "ContactForm",
|
||||
"description": "Complete contact form component with tag, animated title and description, email signup form, and terms text.",
|
||||
"details": "Use for email signup sections with full context and branding. Features Tag component, TextAnimation for title and description using ThemeProvider defaults, EmailSignupForm for input, and terms/conditions text below. Supports centered layout for hero-style presentation. Returns email string on submit.",
|
||||
"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",
|
||||
"centered?": "boolean (default: false)",
|
||||
"className?": "string",
|
||||
"tagClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"descriptionClassName?": "string",
|
||||
"formWrapperClassName?": "string",
|
||||
"formClassName?": "string",
|
||||
"inputClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "string",
|
||||
"termsClassName?": "string"
|
||||
},
|
||||
"usageExample": "<ContactForm title=\"Join our newsletter\" description=\"Get updates\" tag=\"Newsletter\" 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
|
||||
}
|
||||
}
|
||||
96
registry/components/ContactSplit.json
Normal file
96
registry/components/ContactSplit.json
Normal file
@@ -0,0 +1,96 @@
|
||||
{
|
||||
"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.",
|
||||
"details": "Use for newsletter signups or email capture with visual context. Features split layout with ContactForm (tag with optional icon, animated title and description, EmailSignupForm) on one side and image or video media on the other. Form is placed in a card with constrained width on larger screens. Media can be positioned left or right. Media uses fixed height on desktop. Ideal for contact sections that benefit from visual storytelling alongside the 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",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"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' }",
|
||||
"useInvertedBackground": "boolean",
|
||||
"imageSrc?": "string",
|
||||
"videoSrc?": "string",
|
||||
"imageAlt?": "string (default: '')",
|
||||
"videoAriaLabel?": "string (default: 'Contact section video')",
|
||||
"mediaAnimation": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"mediaPosition?": "'left' | 'right' (default: 'right')",
|
||||
"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",
|
||||
"containerClassName?": "string",
|
||||
"contentClassName?": "string",
|
||||
"contactFormClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"descriptionClassName?": "string",
|
||||
"formWrapperClassName?": "string",
|
||||
"formClassName?": "string",
|
||||
"inputClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "string",
|
||||
"termsClassName?": "string",
|
||||
"mediaWrapperClassName?": "string",
|
||||
"mediaClassName?": "string"
|
||||
},
|
||||
"usageExample": "<ContactSplit tag=\"Newsletter\" title=\"Stay updated\" description=\"Subscribe to our newsletter for weekly updates and exclusive content.\" background={{ variant: 'sparkles-gradient' }} useInvertedBackground={false} imageSrc=\"/contact.jpg\" onSubmit={(email) => console.log(email)} />",
|
||||
"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
|
||||
}
|
||||
}
|
||||
69
registry/components/ContactSplitForm.json
Normal file
69
registry/components/ContactSplitForm.json
Normal file
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"name": "ContactSplitForm",
|
||||
"description": "Split layout contact form with animated title and description, dynamic input fields, optional textarea, submit button, and media content.",
|
||||
"details": "Use for full contact forms with visual context. Features split layout with form (animated title and description, dynamic input fields array with minimum 2 required, optional textarea, submit button) on one side and image or video media on the other. All form inputs use secondary-button styling with rounded-theme borders. Media can be positioned left or right. On mobile, media displays with natural aspect ratio; on desktop, uses absolute positioning to match form height. Returns Record<string, string> with all field values on submit. Ideal for contact pages that combine detailed forms with visual storytelling.",
|
||||
"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)",
|
||||
"multiSelect?": "{ name: string, label: string, options: string[] } - Optional multi-select dropdown field",
|
||||
"textarea?": "{ name: string, placeholder: string, rows?: number, required?: boolean, className?: string } - Optional textarea field",
|
||||
"useInvertedBackground": "boolean",
|
||||
"imageSrc?": "string",
|
||||
"videoSrc?": "string",
|
||||
"imageAlt?": "string (default: '')",
|
||||
"videoAriaLabel?": "string (default: 'Contact section video')",
|
||||
"mediaAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal' (default: 'none')",
|
||||
"mediaPosition?": "'left' | 'right' (default: 'right')",
|
||||
"buttonText?": "string (default: 'Submit')",
|
||||
"onSubmit?": "(data: Record<string, string>) => void",
|
||||
"ariaLabel?": "string (default: 'Contact section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"contentClassName?": "string",
|
||||
"formCardClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"descriptionClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "string",
|
||||
"mediaWrapperClassName?": "string",
|
||||
"mediaClassName?": "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={false} 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
|
||||
}
|
||||
}
|
||||
56
registry/components/ContactText.json
Normal file
56
registry/components/ContactText.json
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "ContactText",
|
||||
"description": "Centered contact section with animated text and action buttons in a card container.",
|
||||
"details": "Use for simple, focused contact call-to-actions with emphasis on messaging. Layout: Section wrapper with optional inverted background → Card container (w-content-width, card class, rounded-theme-capped, py-20 px-10) → Centered content area (w-3/4 on md+) with TextAnimation heading and buttons. Text uses GSAP scroll-triggered animation (words-trigger variant) with configurable animation type (entrance-slide, reveal-blur, or background-highlight). Supports up to 2 buttons with px-8 spacing in flex layout. Card background adapts to theme.cardStyle. Text color determined by shouldUseInvertedText utility based on useInvertedBackground and cardStyle. Best for clean contact sections, inquiry prompts, or call-to-action blocks with animated messaging.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"text": {
|
||||
"required": true,
|
||||
"example": "Ready to start your next project? Let's create something amazing together.",
|
||||
"minChars": 10,
|
||||
"maxChars": 125
|
||||
},
|
||||
"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}>",
|
||||
"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)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"ariaLabel?": "string (default: 'Contact section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string - Outer wrapper styling",
|
||||
"contentClassName?": "string - Card content wrapper styling",
|
||||
"textClassName?": "string - TextAnimation heading styling",
|
||||
"buttonContainerClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "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' }]} background={{ variant: 'plain' }} useInvertedBackground={false} />",
|
||||
"do": [
|
||||
"Use for contact pages",
|
||||
"Use for lead generation",
|
||||
"Requires buttons?[]"
|
||||
],
|
||||
"dont": [],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
24
registry/components/DotGridBackground.json
Normal file
24
registry/components/DotGridBackground.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "DotGridBackground",
|
||||
"description": "Dot pattern background with radial gradient dots and optional 3D perspective effect.",
|
||||
"details": "Use for subtle, modern backgrounds. Features dense dot grid (small: 100 dots, medium: 50 dots, large: 25 dots per 100vw). Optional perspectiveThreeD adds skew transform and radial mask. Uses background-accent color at 30% opacity. Has radial fade mask at 90%.",
|
||||
"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
|
||||
}
|
||||
}
|
||||
28
registry/components/DownwardRaysBackground.json
Normal file
28
registry/components/DownwardRaysBackground.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "DownwardRaysBackground",
|
||||
"description": "Atmospheric light rays emanating from top center directly downward with blur and radial gradient effects, with optional grid overlay.",
|
||||
"details": "Use for dramatic, atmospheric backgrounds with light rays cascading from above. Features 9 symmetrical rays with varying widths (15-40px), opacities, rotations fanning outward, and scales emanating from top center. Container is centered horizontally with 16px blur and masked with radial gradient for natural falloff. Includes 3 light sources for additional depth. Uses theme color via var(--color-primary-cta) for both rays and light sources. When animated=true, rays pulse between opacity 0 and their target opacity with staggered timing. When showGrid=true, displays a medium grid overlay (10vw spacing) that fades from top center. Perfect for hero sections, landing pages, or any area needing dramatic top-down lighting effects.",
|
||||
"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
|
||||
}
|
||||
}
|
||||
43
registry/components/EmailSignupForm.json
Normal file
43
registry/components/EmailSignupForm.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "EmailSignupForm",
|
||||
"description": "Compact email signup form with inline input and submit button in card container.",
|
||||
"details": "Use for newsletter signups, waitlists, or email collection. Features inline layout with email input on left and submit button on right, all wrapped in a card with rounded-theme borders and 1-unit padding. Input is flex-1 to fill available space. Button uses ThemeProvider's defaultButtonVariant. Returns email string on submit.",
|
||||
"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",
|
||||
"inputClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "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
|
||||
}
|
||||
}
|
||||
93
registry/components/FaqBase.json
Normal file
93
registry/components/FaqBase.json
Normal file
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"name": "FaqBase",
|
||||
"description": "FAQ section with accordion items and optional header.",
|
||||
"details": "Use for displaying frequently asked questions in an expandable accordion format. Layout: Optional TextBox Header → Accordion List. Supports two animation types: 'smooth' (height transition) and 'instant' (immediate show/hide). Only one accordion item can be open at a time. Each FAQ requires a unique id, title (question), and content (answer). Content supports HTML for rich formatting. Optional header with title, description, tag, and buttons via CardStackTextBox. Best for FAQ pages, help sections, or any Q&A content.",
|
||||
"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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"faqsAnimation": "'none' | 'opacity' | 'slide-up' | 'blur-reveal' (required)",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"animationType?": "'smooth' | 'instant' (default: 'smooth')",
|
||||
"showCard?": "boolean (default: true)",
|
||||
"ariaLabel?": "string (default: 'FAQ section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"titleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"faqsContainerClassName?": "string",
|
||||
"accordionClassName?": "string",
|
||||
"accordionTitleClassName?": "string",
|
||||
"accordionIconContainerClassName?": "string",
|
||||
"accordionIconClassName?": "string",
|
||||
"accordionContentClassName?": "string",
|
||||
"separatorClassName?": "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={false} faqsAnimation=\"slide-up\" />",
|
||||
"do": [
|
||||
"Use for help pages",
|
||||
"Use for support sections",
|
||||
"Requires faqs[]",
|
||||
"Requires titleSegments?[]",
|
||||
"Requires buttons?[]"
|
||||
],
|
||||
"dont": [],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
92
registry/components/FaqDouble.json
Normal file
92
registry/components/FaqDouble.json
Normal file
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"name": "FaqDouble",
|
||||
"description": "FAQ section with two-column accordion layout and optional header.",
|
||||
"details": "Use for displaying frequently asked questions in a two-column layout for better space utilization. Layout: Optional TextBox Header → Card Container with Two Columns of Accordions. FAQs are automatically split into two equal columns (first half in left column, second half in right). On mobile, columns stack vertically. Supports two animation types: 'smooth' (height transition) and 'instant' (immediate show/hide). Only one accordion item can be open at a time across both columns. Each FAQ requires a unique id, title (question), and content (answer). Content supports HTML for rich formatting. Card container has rounded-theme styling. Best for FAQ pages with many questions where horizontal space is available.",
|
||||
"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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"faqsAnimation": "'none' | 'opacity' | 'slide-up' | 'blur-reveal' (required)",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"animationType?": "'smooth' | 'instant' (default: 'smooth')",
|
||||
"ariaLabel?": "string (default: 'FAQ section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"titleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"faqsContainerClassName?": "string",
|
||||
"columnClassName?": "string",
|
||||
"accordionClassName?": "string",
|
||||
"accordionTitleClassName?": "string",
|
||||
"accordionIconContainerClassName?": "string",
|
||||
"accordionIconClassName?": "string",
|
||||
"accordionContentClassName?": "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={false} />",
|
||||
"do": [
|
||||
"Use for help pages",
|
||||
"Use for support sections",
|
||||
"Requires faqs[]",
|
||||
"Requires titleSegments?[]",
|
||||
"Requires buttons?[]"
|
||||
],
|
||||
"dont": [],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
123
registry/components/FaqSplitMedia.json
Normal file
123
registry/components/FaqSplitMedia.json
Normal file
@@ -0,0 +1,123 @@
|
||||
{
|
||||
"name": "FaqSplitMedia",
|
||||
"description": "FAQ section with split layout featuring media (image/video) on one side and accordion list on the other.",
|
||||
"details": "Use for displaying FAQs with visual context. Layout: Optional TextBox Header → Grid with Media (2/5 width) + Accordions (3/5 width). Media can be positioned left or right via mediaPosition prop. Uses CSS Grid with auto-rows-fr to ensure media and FAQ content match height exactly. Media container has fixed height on mobile (h-80) and auto height on desktop to match FAQ content. Supports both images and videos. Only one accordion item can be open at a time. Supports two animation types: 'smooth' (height transition) and 'instant' (immediate show/hide). Each FAQ requires unique id, title (question), and content (answer with HTML support). Best for FAQ pages where visual elements enhance understanding.",
|
||||
"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. Either imageSrc or videoSrc should be provided. Image is recommended if no videoSrc."
|
||||
},
|
||||
"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')",
|
||||
"mediaAnimation": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"faqsAnimation": "'none' | 'opacity' | 'slide-up' | 'blur-reveal' (required)",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"animationType?": "'smooth' | 'instant' (default: 'smooth')",
|
||||
"showCard?": "boolean (default: true)",
|
||||
"ariaLabel?": "string (default: 'FAQ section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"titleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"contentClassName?": "string",
|
||||
"mediaWrapperClassName?": "string",
|
||||
"mediaClassName?": "string",
|
||||
"faqsContainerClassName?": "string",
|
||||
"accordionClassName?": "string",
|
||||
"accordionTitleClassName?": "string",
|
||||
"accordionIconContainerClassName?": "string",
|
||||
"accordionIconClassName?": "string",
|
||||
"accordionContentClassName?": "string",
|
||||
"separatorClassName?": "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={false} 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
|
||||
}
|
||||
}
|
||||
89
registry/components/FaqSplitText.json
Normal file
89
registry/components/FaqSplitText.json
Normal file
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"name": "FaqSplitText",
|
||||
"description": "FAQ section with split layout featuring animated text on one side and accordion list on the other.",
|
||||
"details": "Use for displaying FAQs with a prominent title and optional description. Layout: Animated Title + Description (2/5 width) | Accordions (3/5 width). Text can be positioned left or right via textPosition prop. Text animations are controlled by ThemeProvider's defaultTextAnimation. Only one accordion item can be open at a time. Supports two animation types for accordions: 'smooth' (height transition) and 'instant' (immediate show/hide). Each FAQ requires unique id, title (question), and content (answer with HTML support). Best for FAQ pages with emphasis on section branding or when media isn't needed.",
|
||||
"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}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"faqsAnimation": "'none' | 'opacity' | 'slide-up' | 'blur-reveal' (required)",
|
||||
"textPosition?": "'left' | 'right' (default: 'left')",
|
||||
"useInvertedBackground": "boolean",
|
||||
"animationType?": "'smooth' | 'instant' (default: 'smooth')",
|
||||
"showCard?": "boolean (default: true)",
|
||||
"ariaLabel?": "string (default: 'FAQ section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"contentClassName?": "string",
|
||||
"textContainerClassName?": "string",
|
||||
"sideTitleClassName?": "string",
|
||||
"sideDescriptionClassName?": "string",
|
||||
"buttonContainerClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "string",
|
||||
"faqsContainerClassName?": "string",
|
||||
"accordionClassName?": "string",
|
||||
"accordionTitleClassName?": "string",
|
||||
"accordionIconContainerClassName?": "string",
|
||||
"accordionIconClassName?": "string",
|
||||
"accordionContentClassName?": "string",
|
||||
"separatorClassName?": "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={false} />",
|
||||
"do": [
|
||||
"Use for help pages",
|
||||
"Use for support sections",
|
||||
"Requires faqs[]",
|
||||
"Requires buttons?[]"
|
||||
],
|
||||
"dont": [],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
113
registry/components/FeatureBento.json
Normal file
113
registry/components/FeatureBento.json
Normal file
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"name": "FeatureBento",
|
||||
"description": "Feature section with bento-style cards displaying interactive visualizations (globe, charts, 3D cards, map).",
|
||||
"details": "Use for feature showcases with rich interactive content. Each feature card contains a bento component visualization. Supports 11 bento types: globe (3D rotating globe), icon-info-cards (scrolling metric cards), animated-bar-chart (animated chart), 3d-stack-cards (three stacked notification cards), 3d-task-list (rotated task list card), orbiting-icons (orbiting integration icons on rings), map (world map with animated location markers), marquee (scrolling text/icon rows with centered icon), line-chart (area line chart with gradient fill), phone (interactive phone mockup with notification animation), or media-stack (three stacked images/videos that fan out on hover). Automatically switches between grid (1-4 items) and carousel (5+ items). Carousel offers auto-scroll or button controls (recommended: keep default buttons). Optional header with title, description, tag, and buttons. Supports centered or split textbox layouts. Best for modern landing pages showcasing platform capabilities with visual flair.",
|
||||
"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
|
||||
}
|
||||
},
|
||||
"bentoComponentRules": {
|
||||
"note": "CRITICAL: Each feature MUST use a DIFFERENT bentoComponent type. Never repeat the same type across features (e.g., don't use 'globe' twice). Requirements vary by type:",
|
||||
"types": {
|
||||
"globe": "{ bentoComponent: 'globe' } - No additional fields required",
|
||||
"animated-bar-chart": "{ bentoComponent: 'animated-bar-chart' } - No additional fields required",
|
||||
"map": "{ bentoComponent: 'map' } - No additional fields required",
|
||||
"line-chart": "{ bentoComponent: 'line-chart' } - No additional fields required",
|
||||
"icon-info-cards": "{ bentoComponent: 'icon-info-cards', items: Array<{ icon: LucideIcon, label: string, value: string }> } - Requires items array",
|
||||
"3d-stack-cards": "{ bentoComponent: '3d-stack-cards', items: [Bento3DItem, Bento3DItem, Bento3DItem] } - Requires exactly 3 items. Each item: { icon: LucideIcon, title: string, subtitle: string, detail: string }",
|
||||
"3d-task-list": "{ bentoComponent: '3d-task-list', title: string, items: Array<{ icon: LucideIcon, label: string, time: string }> } - Requires title and items array",
|
||||
"orbiting-icons": "{ bentoComponent: 'orbiting-icons', centerIcon: LucideIcon, items: Array<{ icon: LucideIcon, ring?: 1 | 2 | 3, duration?: number }> } - Requires centerIcon and items array. ring defaults to 2, duration defaults to 10s",
|
||||
"marquee": "{ bentoComponent: 'marquee', centerIcon: LucideIcon, variant: 'text' | 'icon', texts?: string[], icons?: LucideIcon[] } - Requires centerIcon and variant. If variant='text', requires texts array. If variant='icon', requires icons array. Shows scrolling rows with centered icon",
|
||||
"phone": "{ bentoComponent: 'phone', statusIcon: LucideIcon, alertIcon: LucideIcon, alertTitle: string, alertMessage: string, apps: PhoneApps8 } - Requires all fields. statusIcon is displayed at top (e.g. Lock), alertIcon for notification, alertTitle/alertMessage for notification content, apps is exactly 8 items Array<{ name: string, icon: LucideIcon }>. Interactive phone mockup with notification slide-in animation and app grid on hover",
|
||||
"chat": "{ bentoComponent: 'chat', aiIcon: LucideIcon, userIcon: LucideIcon, exchanges: Array<{ userMessage: string, aiResponse: string }>, placeholder: string } - Requires aiIcon, userIcon, exchanges array, and placeholder. Each exchange contains a user message and AI response pair. Chat interface with vertical marquee animation",
|
||||
"3d-card-grid": "{ bentoComponent: '3d-card-grid', items: [GridCardItem, GridCardItem, GridCardItem, GridCardItem], centerIcon: LucideIcon } - Requires exactly 4 items and centerIcon. Each item: { name: string, icon: LucideIcon }. 3D perspective grid with cards at corners and center icon",
|
||||
"reveal-icon": "{ bentoComponent: 'reveal-icon', icon: LucideIcon } - Requires icon. Animated doors that slide open on hover revealing center icon with glow effect",
|
||||
"timeline": "{ bentoComponent: 'timeline', heading: string, subheading: string, items: [TimelineItem, TimelineItem, TimelineItem], completedLabel: string } - Requires heading, subheading, exactly 3 items, and completedLabel. Each item: { label: string, detail: string }. Animated timeline with staggered reveal on hover",
|
||||
"media-stack": "{ bentoComponent: 'media-stack', items: [MediaStackItem, MediaStackItem, MediaStackItem] } - Requires exactly 3 items. Each item: { imageSrc?: string, videoSrc?: string, imageAlt?: string }. Three stacked images/videos with rotation that fan out on hover"
|
||||
}
|
||||
}
|
||||
},
|
||||
"propsSchema": {
|
||||
"features": "Array<FeatureCard> - Each card has { title: string, description: string, button?: ButtonConfig } and one of: { bentoComponent: 'globe' } | { bentoComponent: 'animated-bar-chart' } | { bentoComponent: 'map' } | { bentoComponent: 'line-chart' } | { bentoComponent: 'phone', statusIcon: LucideIcon, alertIcon: LucideIcon, alertTitle: string, alertMessage: string, apps: Array<{ name: string, icon: LucideIcon }> (exactly 8 items) } | { bentoComponent: 'chat', aiIcon: LucideIcon, userIcon: LucideIcon, exchanges: Array<{ userMessage: string, aiResponse: string }>, placeholder: string } | { bentoComponent: 'icon-info-cards', items: Array<{ icon: LucideIcon, label: string, value: string }> } | { bentoComponent: '3d-stack-cards', items: [{ icon: LucideIcon, title: string, subtitle: string, detail: string }, { icon: LucideIcon, title: string, subtitle: string, detail: string }, { icon: LucideIcon, title: string, subtitle: string, detail: string }] } | { bentoComponent: '3d-task-list', title: string, items: Array<{ icon: LucideIcon, label: string, time: string }> } | { bentoComponent: 'orbiting-icons', centerIcon: LucideIcon, items: Array<{ icon: LucideIcon, ring?: 1 | 2 | 3, duration?: number }> } | { bentoComponent: 'marquee', centerIcon: LucideIcon, variant: 'text', texts: string[] } | { bentoComponent: 'marquee', centerIcon: LucideIcon, variant: 'icon', icons: LucideIcon[] } | { bentoComponent: '3d-card-grid', items: [{ name: string, icon: LucideIcon }, { name: string, icon: LucideIcon }, { name: string, icon: LucideIcon }, { name: string, icon: LucideIcon }], centerIcon: LucideIcon } | { bentoComponent: 'reveal-icon', icon: LucideIcon } | { bentoComponent: 'timeline', heading: string, subheading: string, items: [{ label: string, detail: string }, { label: string, detail: string }, { label: string, detail: string }], completedLabel: string } | { bentoComponent: 'media-stack', items: [{ imageSrc?: string, videoSrc?: string, imageAlt?: string }, { imageSrc?: string, videoSrc?: string, imageAlt?: string }, { imageSrc?: string, videoSrc?: string, imageAlt?: string }] }",
|
||||
"carouselMode?": "'auto' | 'buttons' (default: 'buttons')",
|
||||
"animationType": "'none' | 'opacity' | 'slide-up' | 'blur-reveal' (required)",
|
||||
"title": "string (required)",
|
||||
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
|
||||
"description": "string (required)",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean (required)",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxTitleImageWrapperClassName?": "string",
|
||||
"textBoxTitleImageClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"cardButtonClassName?": "string",
|
||||
"cardButtonTextClassName?": "string",
|
||||
"gridClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"controlsClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureBento features={[{ title: 'Global Reach', description: 'Worldwide presence', bentoComponent: 'globe' }, { title: 'Integrations', description: 'Connect your tools', bentoComponent: 'orbiting-icons', centerIcon: Shield, items: [{ icon: Users, ring: 1 }, { icon: Zap, ring: 2 }] }]} title=\"Features\" description=\"Discover our platform\" textboxLayout=\"default\" animationType=\"slide-up\" useInvertedBackground={false} />",
|
||||
"do": [
|
||||
"Use for showcasing features with interactive visualizations",
|
||||
"Use appropriate bentoComponent for each feature type",
|
||||
"Provide all required props for each bentoComponent type",
|
||||
"Best for modern landing pages showcasing platform capabilities"
|
||||
],
|
||||
"dont": [
|
||||
"CRITICAL: NEVER use the same bentoComponent type for multiple features - each feature MUST have a unique/different bento type (e.g., if one uses 'globe', others must use 'map', 'timeline', 'chat', etc.)",
|
||||
"Do not use without proper items for bento types that require them",
|
||||
"Do not use for simple text-only feature lists"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
104
registry/components/FeatureBorderGlow.json
Normal file
104
registry/components/FeatureBorderGlow.json
Normal file
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"name": "FeatureBorderGlow",
|
||||
"description": "CardStack feature section with animated glowing border effect that follows cursor/scroll.",
|
||||
"details": "Use for feature showcases with premium animated border effect. Uses CardStack with uniform-all-items-equal grid (hardcoded). Each card displays an icon at top, title and description below, with an animated glowing border overlay using Motion React. The border glow dynamically follows mouse position on desktop (within proximity threshold of 64px), or activates on scroll for mobile. Effect uses CSS variables (accent, background-accent) for theme-aware colors. Border width is 1.5px with 40deg spread and smooth angle transitions (2s duration). Desktop: Glowing effect tracks mouse movement with conic gradient mask following cursor angle. Mobile: Effect centers on viewport when card enters view. Each card uses primary-button styling for icon container (3.75rem square) with card styling and rounded-theme-capped borders. All cards have min-h-75 2xl:min-h-85 default height. The glowing effect has inactive zone of 0.01 (nearly no dead zone in center). Best for 2-6 features to showcase premium product benefits with elegant visual polish.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Powerful Features with Border Glow",
|
||||
"minChars": 2,
|
||||
"maxChars": 35
|
||||
},
|
||||
"description": {
|
||||
"required": true,
|
||||
"example": "Hover over each card to reveal the glowing border effect",
|
||||
"minChars": 5,
|
||||
"maxChars": 250
|
||||
},
|
||||
"tag": {
|
||||
"required": false,
|
||||
"example": "Features",
|
||||
"minChars": 2,
|
||||
"maxChars": 30
|
||||
}
|
||||
},
|
||||
"featureCardRules": {
|
||||
"icon": {
|
||||
"required": true,
|
||||
"example": "Zap",
|
||||
"note": "LucideIcon component displayed at top of card with glowing border"
|
||||
},
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Lightning Fast",
|
||||
"minChars": 2,
|
||||
"maxChars": 40
|
||||
},
|
||||
"description": {
|
||||
"required": true,
|
||||
"example": "Optimized for performance with minimal overhead and blazing fast load times",
|
||||
"minChars": 10,
|
||||
"maxChars": 200
|
||||
}
|
||||
},
|
||||
"itemRules": {
|
||||
"minItems": 2,
|
||||
"maxItems": 6,
|
||||
"recommendedItems": "2-6",
|
||||
"note": "Works best with 2-6 features for optimal grid layout"
|
||||
}
|
||||
},
|
||||
"propsSchema": {
|
||||
"features": "Array<{ icon: LucideIcon, title: string, description: string }> (required)",
|
||||
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' (required)",
|
||||
"title": "string (required)",
|
||||
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
|
||||
"description": "string (required)",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean (required)",
|
||||
"carouselMode?": "'auto' | 'buttons' (default: 'buttons' - for 5+ items)",
|
||||
"uniformGridCustomHeightClasses?": "string (default: 'min-h-75 2xl:min-h-85')",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"iconContainerClassName?": "string",
|
||||
"iconClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxTitleImageWrapperClassName?": "string",
|
||||
"textBoxTitleImageClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"gridClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"controlsClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureBorderGlow features={[{ icon: Zap, title: 'Lightning Fast', description: 'Optimized for performance with minimal overhead' }, { icon: Shield, title: 'Secure by Default', description: 'Built with security best practices' }]} title=\"Powerful Features with Border Glow\" description=\"Hover over each card to reveal the glowing border effect\" textboxLayout=\"default\" animationType=\"slide-up\" useInvertedBackground={false} />",
|
||||
"do": [
|
||||
"Use for premium feature showcases with elegant visual polish",
|
||||
"Best for 2-6 features",
|
||||
"Each feature requires icon, title, and description",
|
||||
"Use for modern landing pages"
|
||||
],
|
||||
"dont": [
|
||||
"Do not use for simple text-only feature lists",
|
||||
"Do not use without icons for each feature"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
125
registry/components/FeatureCardEight.json
Normal file
125
registry/components/FeatureCardEight.json
Normal file
@@ -0,0 +1,125 @@
|
||||
{
|
||||
"name": "FeatureCardEight",
|
||||
"description": "Horizontal timeline feature section with auto-advancing progress bars, numbered step badges, and shared media display.",
|
||||
"details": "Use for sequential feature presentations or process flows in a horizontal timeline layout. Displays 2-4 feature cards in a grid (2-4 columns on desktop, stacked on mobile) with auto-advancing progress bars that fill over 5 seconds. Each card shows a numbered step badge, title, and description. The shared media area above cards displays images/videos that smoothly transition (opacity fade) as cards advance. Media uses aspect-square on mobile and aspect-video on desktop. Active and previous cards are fully visible (opacity-100), future cards are dimmed (opacity-50). Users can click any card to jump to that step. Grid adapts: 2 items = 2 columns, 3 items = 3 columns, 4+ items = 4 columns. Automatically loops back to first card. Optional header with title, description, tag, and buttons. Header supports centered or split textbox layout (split: tag + title + description left, buttons right; split-actions: tag + title left, buttons only right; split-description: tag + title left, description only right).",
|
||||
"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": {
|
||||
"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) Either imageSrc or videoSrc should be provided. Image is recommended if no videoSrc."
|
||||
},
|
||||
"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<{ 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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"titleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"progressBarClassName?": "string",
|
||||
"cardContentClassName?": "string",
|
||||
"stepNumberClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"mediaContainerClassName?": "string",
|
||||
"mediaClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureCardEight features={[{ 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={false} />",
|
||||
"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
|
||||
}
|
||||
}
|
||||
96
registry/components/FeatureCardMedia.json
Normal file
96
registry/components/FeatureCardMedia.json
Normal file
@@ -0,0 +1,96 @@
|
||||
{
|
||||
"name": "FeatureCardMedia",
|
||||
"description": "Feature section with media cards displaying tag overlay, title, description, and optional buttons.",
|
||||
"details": "Displays feature cards in a responsive grid or carousel layout. Each card shows media (image/video) with required tag overlay positioned top-right, followed by title, description, and optional action buttons. Uses CardStack for layout management with grid (1-4 items) and carousel (5+ items) modes.",
|
||||
"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) Image is recommended if no videoSrc.",
|
||||
"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": "boolean",
|
||||
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }>",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "ButtonConfig[]",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"carouselMode?": "'auto' | 'buttons' (default: 'buttons')",
|
||||
"uniformGridCustomHeightClasses?": "string",
|
||||
"ariaLabel?": "string (default: 'Features section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"itemClassName?": "string",
|
||||
"mediaWrapperClassName?": "string",
|
||||
"mediaClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"contentClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"cardButtonContainerClassName?": "string",
|
||||
"cardButtonClassName?": "string",
|
||||
"cardButtonTextClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxTitleImageWrapperClassName?": "string",
|
||||
"textBoxTitleImageClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"gridClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"controlsClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "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={false} />",
|
||||
"do": [
|
||||
"Use for feature showcases",
|
||||
"Use for capability displays",
|
||||
"Requires features[]",
|
||||
"Requires titleSegments?[]"
|
||||
],
|
||||
"dont": [],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
150
registry/components/FeatureCardNine.json
Normal file
150
registry/components/FeatureCardNine.json
Normal file
@@ -0,0 +1,150 @@
|
||||
{
|
||||
"name": "FeatureCardNine",
|
||||
"description": "Scroll-based timeline feature section with two animated phone frames and centered content.",
|
||||
"details": "Use for mobile-first feature presentations with visual phone mockups. Creates a vertical scroll-based timeline where each feature takes up 100vh of height. Features are displayed with title and description in the center, flanked by two animated phone frames (left and right) that slide in and rotate on scroll. Phone frames use GSAP ScrollTrigger animations: start from off-screen with rotation (-200% left, 200% right with 45deg rotation), then animate to center position with subtle rotation tilt. Desktop phones are 20 (w-20) 2xl:25 (2xl:w-25) in width and 70vh in height. Mobile phones are 45 (w-45) in width and 100 (h-100) in height. Phones display as card with rounded-theme-capped and p-1 padding. Each phone can show either an image or video (discriminated union). Feature content displays in the center with large text (5xl md:6xl title, xl description). Section has py-20 spacing. Mobile layout stacks feature content above phone pairs vertically. Desktop layout uses sticky positioning for phones while content scrolls through. Best for 2-4 features to avoid excessive scroll height.",
|
||||
"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": {
|
||||
"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) Either imageSrc or videoSrc should be provided. Image is recommended if no videoSrc."
|
||||
},
|
||||
"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) Either imageSrc or videoSrc should be provided. Image is recommended if no videoSrc."
|
||||
},
|
||||
"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<{ title: string, description: string, buttons?: ButtonConfig[], 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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' (required)",
|
||||
"textboxLayout": "'default' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"titleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"desktopContainerClassName?": "string",
|
||||
"mobileContainerClassName?": "string",
|
||||
"desktopContentClassName?": "string",
|
||||
"desktopWrapperClassName?": "string",
|
||||
"mobileWrapperClassName?": "string",
|
||||
"phoneFrameClassName?": "string",
|
||||
"mobilePhoneFrameClassName?": "string",
|
||||
"featureContentClassName?": "string",
|
||||
"stepNumberClassName?": "string",
|
||||
"featureTitleClassName?": "string",
|
||||
"featureDescriptionClassName?": "string",
|
||||
"cardButtonClassName?": "string",
|
||||
"cardButtonTextClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureCardNine features={[{ 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={false} />",
|
||||
"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
|
||||
}
|
||||
}
|
||||
127
registry/components/FeatureCardNineteen.json
Normal file
127
registry/components/FeatureCardNineteen.json
Normal file
@@ -0,0 +1,127 @@
|
||||
{
|
||||
"name": "FeatureCardNineteen",
|
||||
"description": "Timeline feature section with full-width cards showing step numbers and rotated media.",
|
||||
"details": "Use for process or step-by-step showcases with large visual impact. Layout: TextBox Header → Full-width timeline cards with scroll-triggered stacking. Each card has: Tag + Large title (left), Subtitle + Description + Buttons (bottom left), Step number (top right), Rotated image/video (right). Mobile: Single column with divider line, step number hidden. Best for showcasing 3-6 step processes or service phases.",
|
||||
"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": {
|
||||
"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": 50,
|
||||
"maxChars": 350
|
||||
},
|
||||
"imageSrc": {
|
||||
"required": false,
|
||||
"example": "/images/strategy.webp",
|
||||
"note": "Image source URL (either imageSrc or videoSrc) Either imageSrc or videoSrc should be provided. Image is recommended if no 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<{ 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": "boolean",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string",
|
||||
"titleImageClassName?": "string",
|
||||
"cardContentClassName?": "string",
|
||||
"cardTagClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"cardButtonClassName?": "string",
|
||||
"cardButtonTextClassName?": "string",
|
||||
"imageContainerClassName?": "string",
|
||||
"imageClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureCardNineteen features={[{ 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={false} />",
|
||||
"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
|
||||
}
|
||||
}
|
||||
96
registry/components/FeatureCardOne.json
Normal file
96
registry/components/FeatureCardOne.json
Normal file
@@ -0,0 +1,96 @@
|
||||
{
|
||||
"name": "FeatureCardOne",
|
||||
"description": "Adaptive feature section with image/video-based cards in customizable bento grid layouts or carousel.",
|
||||
"details": "Use for visually-rich feature showcases with images or videos. Each card displays media (image/video), title, description, and optional button. Automatically switches between grid (1-4 items) and carousel (5+ items). For grid layouts, choose from 9 bento variants: uniform-all-items-equal, 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. Carousel offers auto-scroll or button controls (recommended: keep default buttons for better UX). Optional header with title, description, tag, and buttons. Header supports centered or split textbox layout (split: tag + title + description left, buttons right; split-actions: tag + title left, buttons only right; split-description: tag + title left, description only right).",
|
||||
"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' | 'two-items-per-row'",
|
||||
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' | 'depth-3d'",
|
||||
"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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"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",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"mediaClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxTitleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"textBoxTitleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"cardButtonClassName?": "string",
|
||||
"cardButtonTextClassName?": "string",
|
||||
"gridClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"controlsClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"useInvertedBackground": "boolean",
|
||||
"showVerifiedBadge?": "boolean"
|
||||
},
|
||||
"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={false} />",
|
||||
"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
|
||||
}
|
||||
}
|
||||
118
registry/components/FeatureCardSeven.json
Normal file
118
registry/components/FeatureCardSeven.json
Normal file
@@ -0,0 +1,118 @@
|
||||
{
|
||||
"name": "FeatureCardSeven",
|
||||
"description": "Vertical stack feature section with alternating left/right layouts and numbered step cards with square images.",
|
||||
"details": "Use for sequential feature presentations or process flows in a vertical layout. Each card displays a numbered step badge, title, description, and square aspect ratio media (image or video) in a two-column layout. On desktop, the layout alternates between text-left/image-right (even indices) and image-left/text-right (odd indices) creating a zigzag pattern. On mobile, always displays as flex-col (text on top, image below). Uses CardList component with GSAP scroll animations and stagger effect. Optional header with title, description, tag, and buttons. Header supports centered or split textbox layout (split: tag + title + description left, buttons right; split-actions: tag + title left, buttons only right; split-description: tag + title left, description only right).",
|
||||
"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": {
|
||||
"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 Either imageSrc or videoSrc should be provided. Image is recommended if no videoSrc."
|
||||
},
|
||||
"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<{ title: string, description: string, buttons?: ButtonConfig[] } & ({ 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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"titleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"cardContentClassName?": "string",
|
||||
"stepNumberClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"imageContainerClassName?": "string",
|
||||
"imageClassName?": "string",
|
||||
"cardButtonClassName?": "string",
|
||||
"cardButtonTextClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureCardSeven features={[{ 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={false} />",
|
||||
"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
|
||||
}
|
||||
}
|
||||
116
registry/components/FeatureCardSix.json
Normal file
116
registry/components/FeatureCardSix.json
Normal file
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"name": "FeatureCardSix",
|
||||
"description": "Timeline-based feature section with scroll-triggered stacking animations and numbered step cards.",
|
||||
"details": "Use for process flows, roadmaps, or sequential feature presentations. Each card displays a numbered step badge, title, description, and media (image or video) in a two-column layout. As you scroll, cards stack on top of each other with fade animations. The timeline layout provides a clear visual progression through steps or stages. No grid/carousel modes - uses fixed timeline stacking layout with GSAP ScrollTrigger. Optional header with title, description, tag, and buttons. Header supports centered or split textbox layout (split: tag + title + description left, buttons right; split-actions: tag + title left, buttons only right; split-description: tag + title left, description only right).",
|
||||
"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": {
|
||||
"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 Either imageSrc or videoSrc should be provided. Image is recommended if no videoSrc."
|
||||
},
|
||||
"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<{ title: string, description: string, buttons?: ButtonConfig[] } & ({ 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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"titleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"cardContentClassName?": "string",
|
||||
"stepNumberClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"imageContainerClassName?": "string",
|
||||
"imageClassName?": "string",
|
||||
"cardButtonClassName?": "string",
|
||||
"cardButtonTextClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureCardSix features={[{ 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={false} />",
|
||||
"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
|
||||
}
|
||||
}
|
||||
99
registry/components/FeatureCardSixteen.json
Normal file
99
registry/components/FeatureCardSixteen.json
Normal file
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"name": "FeatureCardSixteen",
|
||||
"description": "Comparison section with negative and positive cards showing contrasting features.",
|
||||
"details": "Use for before/after comparisons, pros vs cons, or contrasting two approaches. Layout: TextBox Header → Two side-by-side cards (negative with X icons at 50% opacity, positive with Check icons). Always requires exactly one negative and one positive card. Best for comparison marketing or highlighting advantages over alternatives.",
|
||||
"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'",
|
||||
"title": "string",
|
||||
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
|
||||
"description": "string",
|
||||
"textboxLayout": "'default' | 'inline-image' (required)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"ariaLabel?": "string (default: 'Feature comparison section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string",
|
||||
"titleImageClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"gridClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"itemsListClassName?": "string",
|
||||
"itemClassName?": "string",
|
||||
"itemIconClassName?": "string",
|
||||
"itemTextClassName?": "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={false} />",
|
||||
"do": [
|
||||
"Use for feature showcases",
|
||||
"Use for capability displays",
|
||||
"Requires titleSegments?[]",
|
||||
"Requires buttons?[]"
|
||||
],
|
||||
"dont": [],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
143
registry/components/FeatureCardTen.json
Normal file
143
registry/components/FeatureCardTen.json
Normal file
@@ -0,0 +1,143 @@
|
||||
{
|
||||
"name": "FeatureCardTen",
|
||||
"description": "Timeline process flow feature section with numbered steps, alternating layout, and list items.",
|
||||
"details": "Use for step-by-step process showcases with detailed feature lists. Creates a vertical timeline with a progress line that fills on scroll. Each feature displays as a horizontal layout with media (image/video card) on one side and content (title, description, icon list) on the other. Numbered badges appear on the timeline. Layout alternates between left/right based on reverse property. Desktop: centered vertical line with 30% width columns. Mobile: right-aligned vertical line with 70% width columns. Media displays in aspect-square on mobile, aspect-[16/10] on desktop with card styling. Each feature has a list of items with icons displayed in rounded icon containers. Best for 3-6 step processes to showcase detailed features with visual support.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Powerful Features",
|
||||
"minChars": 2,
|
||||
"maxChars": 35
|
||||
},
|
||||
"description": {
|
||||
"required": true,
|
||||
"example": "Everything you need to build and scale your business with confidence",
|
||||
"minChars": 5,
|
||||
"maxChars": 250
|
||||
},
|
||||
"tag": {
|
||||
"required": false,
|
||||
"example": "Features",
|
||||
"minChars": 2,
|
||||
"maxChars": 30
|
||||
}
|
||||
},
|
||||
"featureCardRules": {
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Advanced Analytics Dashboard",
|
||||
"minChars": 2,
|
||||
"maxChars": 60
|
||||
},
|
||||
"description": {
|
||||
"required": true,
|
||||
"example": "Get comprehensive insights into your business performance with our powerful analytics tools and real-time reporting.",
|
||||
"minChars": 10,
|
||||
"maxChars": 300
|
||||
},
|
||||
"reverse": {
|
||||
"required": true,
|
||||
"example": "false",
|
||||
"note": "Controls whether media and content positions are swapped (alternating layout)"
|
||||
}
|
||||
},
|
||||
"mediaRules": {
|
||||
"imageSrc": {
|
||||
"required": true,
|
||||
"example": "/feature.webp",
|
||||
"note": "Either imageSrc or videoSrc required (discriminated union) Either imageSrc or videoSrc should be provided. Image is recommended if no videoSrc."
|
||||
},
|
||||
"videoSrc": {
|
||||
"required": true,
|
||||
"example": "/feature.mp4",
|
||||
"note": "Either imageSrc or videoSrc required (discriminated union)"
|
||||
},
|
||||
"imageAlt": {
|
||||
"required": false,
|
||||
"example": "Analytics dashboard interface",
|
||||
"note": "Falls back to feature title if not provided"
|
||||
},
|
||||
"videoAriaLabel": {
|
||||
"required": false,
|
||||
"example": "Analytics dashboard video",
|
||||
"note": "Falls back to '[title] video' if not provided"
|
||||
}
|
||||
},
|
||||
"listItemRules": {
|
||||
"icon": {
|
||||
"required": true,
|
||||
"example": "Check",
|
||||
"note": "LucideIcon component for list item"
|
||||
},
|
||||
"text": {
|
||||
"required": true,
|
||||
"example": "Real-time data visualization",
|
||||
"minChars": 2,
|
||||
"maxChars": 100
|
||||
},
|
||||
"minItems": 1,
|
||||
"maxItems": 5,
|
||||
"recommendedItems": "2-4"
|
||||
},
|
||||
"itemRules": {
|
||||
"minItems": 3,
|
||||
"maxItems": 6,
|
||||
"recommendedItems": "3-6",
|
||||
"note": "Works best with 3-6 features for optimal timeline length"
|
||||
}
|
||||
},
|
||||
"propsSchema": {
|
||||
"features": "Array<{ title: string, description: string, media: ({ imageSrc: string, imageAlt?: string } | { videoSrc: string, videoAriaLabel?: string }), items: Array<{ icon: LucideIcon, text: string }>, reverse: boolean }>",
|
||||
"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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' (required)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string",
|
||||
"titleImageClassName?": "string",
|
||||
"itemClassName?": "string",
|
||||
"mediaWrapperClassName?": "string",
|
||||
"mediaCardClassName?": "string",
|
||||
"numberClassName?": "string",
|
||||
"contentWrapperClassName?": "string",
|
||||
"featureTitleClassName?": "string",
|
||||
"featureDescriptionClassName?": "string",
|
||||
"listItemClassName?": "string",
|
||||
"iconContainerClassName?": "string",
|
||||
"iconClassName?": "string",
|
||||
"gapClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureCardTen features={[{ title: 'Advanced Analytics Dashboard', description: 'Get comprehensive insights into your business performance', media: { imageSrc: '/placeholder1.webp' }, items: [{ icon: Check, text: 'Real-time data visualization' }, { icon: Check, text: 'Custom report generation' }], reverse: false }]} title=\"Powerful Features\" description=\"Everything you need to build and scale your business\" textboxLayout=\"default\" animationType=\"slide-up\" useInvertedBackground={false} />",
|
||||
"do": [
|
||||
"Use for step-by-step process showcases",
|
||||
"Best for 3-6 step processes",
|
||||
"Alternate reverse property for visual variety",
|
||||
"Include relevant icons for list items"
|
||||
],
|
||||
"dont": [
|
||||
"Do not use without media for each feature",
|
||||
"Do not use without list items"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
103
registry/components/FeatureCardThree.json
Normal file
103
registry/components/FeatureCardThree.json
Normal file
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"name": "FeatureCardThree",
|
||||
"description": "Adaptive feature section with hover-reveal cards displaying numbered features with images.",
|
||||
"details": "Use for interactive feature showcases with hover effects. Each card displays a numbered ID badge that flips to an info icon on hover, image background, title, and description that reveals with a slide-up background animation. Automatically switches between grid (1-4 items) and carousel (5+ items). Carousel offers auto-scroll or button controls (recommended: keep default buttons for better UX). Optional header with title, description, tag, and buttons. Header supports centered or split textbox layout (split: tag + title + description left, buttons right; split-actions: tag + title left, buttons only right; split-description: tag + title left, description only right).",
|
||||
"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": {
|
||||
"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<{ 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' (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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxTitleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"textBoxTitleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"gridClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"controlsClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"itemContentClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureCardThree features={[{ 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={false} />",
|
||||
"do": [
|
||||
"Use for feature showcases",
|
||||
"Use for capability displays",
|
||||
"Requires features[]",
|
||||
"Requires titleSegments?[]",
|
||||
"Requires buttons?[]"
|
||||
],
|
||||
"dont": [],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
119
registry/components/FeatureCardTwelve.json
Normal file
119
registry/components/FeatureCardTwelve.json
Normal file
@@ -0,0 +1,119 @@
|
||||
{
|
||||
"name": "FeatureCardTwelve",
|
||||
"description": "List-based feature section with large label on left and content with bullet points on right.",
|
||||
"details": "Use for feature comparisons, tier showcases, or service level displays. Uses CardList with variant system for card or border layouts. Layout: Optional TextBox Header → Vertical Stack of Features. Each feature card has horizontal split (md breakpoint): Left side (50%): Large label text (5xl mobile / 6xl desktop). Right side (50%): Title + inline bullet list with accent-colored dots (•) + optional buttons (0-2). Card variant: Items wrapped in cards with full padding (p-6 md:p-15) and mobile divider line. Border variant: Items separated by accent divider lines with bottom padding (pb-6 md:pb-10), no mobile divider. Text colors conditional on variant: border uses useInvertedBackground directly, card uses shouldUseLightText. Supports 0-2 buttons per feature with automatic primary/secondary styling via getButtonProps. Best for pricing tiers, service levels, or feature breakdowns with clear labeling.",
|
||||
"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": "boolean",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"titleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"cardContentClassName?": "string",
|
||||
"labelClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"itemsContainerClassName?": "string",
|
||||
"itemTextClassName?": "string",
|
||||
"cardButtonClassName?": "string",
|
||||
"cardButtonTextClassName?": "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\" variant=\"border\" title=\"Choose Your Plan\" description=\"Find the perfect fit for your needs\" textboxLayout=\"default\" useInvertedBackground={false} />",
|
||||
"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
|
||||
}
|
||||
}
|
||||
130
registry/components/FeatureCardTwentyEight.json
Normal file
130
registry/components/FeatureCardTwentyEight.json
Normal file
@@ -0,0 +1,130 @@
|
||||
{
|
||||
"name": "FeatureCardTwentyEight",
|
||||
"description": "Job listing style feature cards with title, subtitle, category indicator, value, and optional footer buttons.",
|
||||
"details": "Use for job listings, pricing tiers, or any feature display with detailed information. Layout: Title (job title/name) → Subtitle (location/details) → Bottom row with category indicator (dot + label, truncates) on left and value (salary/price) on right → Optional footer with accent background containing up to 2 buttons. Uses CardStack with hardcoded uniform-all-items-equal grid and carousel threshold of 4 (switches to carousel with 4+ items). Supports card or default container styles with inverted text logic.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Open Positions",
|
||||
"minChars": 2,
|
||||
"maxChars": 50
|
||||
},
|
||||
"description": {
|
||||
"required": true,
|
||||
"example": "Join our team and help shape the future of AI",
|
||||
"minChars": 5,
|
||||
"maxChars": 250
|
||||
},
|
||||
"tag": {
|
||||
"required": false,
|
||||
"example": "Careers",
|
||||
"minChars": 2,
|
||||
"maxChars": 30
|
||||
}
|
||||
},
|
||||
"featureRules": {
|
||||
"id": {
|
||||
"required": true,
|
||||
"example": "1",
|
||||
"minChars": 1,
|
||||
"maxChars": 20
|
||||
},
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Senior Software Engineer, Platform",
|
||||
"minChars": 5,
|
||||
"maxChars": 80,
|
||||
"note": "Main title displayed at top of card, truncates if too long"
|
||||
},
|
||||
"subtitle": {
|
||||
"required": true,
|
||||
"example": "San Francisco, CA · Full-time · Remote eligible",
|
||||
"minChars": 5,
|
||||
"maxChars": 100,
|
||||
"note": "Secondary info like location, type, or details"
|
||||
},
|
||||
"category": {
|
||||
"required": true,
|
||||
"example": "Engineering",
|
||||
"minChars": 2,
|
||||
"maxChars": 30,
|
||||
"note": "Category label with dot indicator, truncates on overflow"
|
||||
},
|
||||
"value": {
|
||||
"required": true,
|
||||
"example": "$185K – $265K",
|
||||
"minChars": 1,
|
||||
"maxChars": 25,
|
||||
"note": "Value displayed on bottom right (salary, price, etc.)"
|
||||
},
|
||||
"buttons": {
|
||||
"required": false,
|
||||
"maxItems": 2,
|
||||
"note": "Optional buttons in footer section with accent background"
|
||||
}
|
||||
},
|
||||
"itemRules": {
|
||||
"minItems": 1,
|
||||
"maxItems": 12,
|
||||
"recommendedItems": "3-6"
|
||||
}
|
||||
},
|
||||
"propsSchema": {
|
||||
"features": "Array<{ id: string, title: string, subtitle: string, category: string, value: string, buttons?: Array<{text: string, onClick?: () => void, href?: string}> }>",
|
||||
"carouselMode?": "'auto' | 'buttons' (default: 'buttons')",
|
||||
"uniformGridCustomHeightClasses?": "string",
|
||||
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal'",
|
||||
"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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image'",
|
||||
"useInvertedBackground": "boolean",
|
||||
"ariaLabel?": "string (default: 'Features section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxTitleImageWrapperClassName?": "string",
|
||||
"textBoxTitleImageClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"subtitleClassName?": "string",
|
||||
"categoryClassName?": "string",
|
||||
"valueClassName?": "string",
|
||||
"footerClassName?": "string",
|
||||
"cardButtonClassName?": "string",
|
||||
"cardButtonTextClassName?": "string",
|
||||
"gridClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"controlsClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureCardTwentyEight features={[{ id: '1', title: 'Senior Software Engineer, Platform', subtitle: 'San Francisco, CA · Full-time · Remote eligible', category: 'Engineering', value: '$185K – $265K', buttons: [{ text: 'Apply Now', href: '#' }] }, { id: '2', title: 'Product Designer, Enterprise', subtitle: 'New York, NY · Full-time', category: 'Design', value: '$145K – $195K', buttons: [{ text: 'Apply Now', href: '#' }] }, { id: '3', title: 'Data Scientist, ML Platform', subtitle: 'Remote · Full-time', category: 'Data Science', value: '$168K – $238K', buttons: [{ text: 'Apply Now', href: '#' }] }]} title=\"Open Positions\" description=\"Join our team and help shape the future of AI\" textboxLayout=\"default\" useInvertedBackground={false} animationType=\"slide-up\" />",
|
||||
"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 12 items"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
97
registry/components/FeatureCardTwentyFive.json
Normal file
97
registry/components/FeatureCardTwentyFive.json
Normal file
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"name": "FeatureCardTwentyFive",
|
||||
"description": "Two-column grid feature cards with icon, title, description, and dual media items per card.",
|
||||
"details": "Use for showcasing services or features with visual emphasis. Each card displays an icon in a primary button style box, title, description, and two side-by-side images/videos at the bottom. Uses fixed 'two-items-per-row' grid layout on desktop (2 cards per row), button carousel on mobile. Cards have flexible height with images filling remaining space.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Our Features",
|
||||
"minChars": 2,
|
||||
"maxChars": 50
|
||||
},
|
||||
"description": {
|
||||
"required": true,
|
||||
"example": "Discover what makes us different",
|
||||
"minChars": 5,
|
||||
"maxChars": 300
|
||||
},
|
||||
"tag": {
|
||||
"required": false,
|
||||
"example": "Services",
|
||||
"minChars": 2,
|
||||
"maxChars": 30
|
||||
}
|
||||
},
|
||||
"featureRules": {
|
||||
"minItems": 2,
|
||||
"maxItems": 8,
|
||||
"recommendedItems": "4",
|
||||
"structure": {
|
||||
"title": "string - Feature card title (required)",
|
||||
"description": "string - Feature card description (required)",
|
||||
"icon": "LucideIcon - Icon displayed in primary button box (required)",
|
||||
"mediaItems": "[MediaItem, MediaItem] - Tuple of exactly 2 media items (required)"
|
||||
},
|
||||
"mediaItemStructure": {
|
||||
"imageSrc": "string - Path to image (optional if videoSrc provided) Image is recommended if no videoSrc.",
|
||||
"videoSrc": "string - Path to video (optional if imageSrc provided)",
|
||||
"imageAlt": "string - Alt text for image",
|
||||
"videoAriaLabel": "string - Aria label for video"
|
||||
}
|
||||
}
|
||||
},
|
||||
"propsSchema": {
|
||||
"features": "Array<{ title: string, description: string, icon: LucideIcon, mediaItems: [MediaItem, MediaItem] }> - Feature cards with dual media",
|
||||
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' | 'depth-3d' (required)",
|
||||
"title": "string (required)",
|
||||
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
|
||||
"description": "string (required)",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required)",
|
||||
"useInvertedBackground": "boolean (required)",
|
||||
"carouselMode?": "'auto' | 'buttons' (default: 'buttons')",
|
||||
"uniformGridCustomHeightClasses?": "string",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"mediaClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxTitleImageWrapperClassName?": "string",
|
||||
"textBoxTitleImageClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"cardIconClassName?": "string",
|
||||
"cardIconWrapperClassName?": "string",
|
||||
"gridClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"controlsClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureCardTwentyFive features={[{ title: 'Business Strategy', description: 'Crafting clear strategies for growth.', icon: Target, mediaItems: [{ imageSrc: '/img1.jpg', imageAlt: 'Strategy 1' }, { imageSrc: '/img2.jpg', imageAlt: 'Strategy 2' }] }]} animationType=\"depth-3d\" title=\"Our Features\" description=\"Discover what makes us different\" textboxLayout=\"default\" useInvertedBackground={false} />",
|
||||
"do": [
|
||||
"Use for features with visual examples",
|
||||
"Each feature requires exactly 2 media items",
|
||||
"Use relevant icons for each feature",
|
||||
"Supports 3D animations"
|
||||
],
|
||||
"dont": [
|
||||
"Do not use without 2 media items per feature",
|
||||
"Do not use without icons"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
84
registry/components/FeatureCardTwentyFour.json
Normal file
84
registry/components/FeatureCardTwentyFour.json
Normal file
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"name": "FeatureCardTwentyFour",
|
||||
"description": "Two-column feature card list with title, author, description, tags, and media.",
|
||||
"details": "Use for feature articles, case studies, or content with author attribution. Uses CardList component with card or border variants. Layout: CardStackTextBox header → Vertical list of items. Each card uses 10-column grid on desktop (6/10 text, 4/10 media). Text area includes title with inline author (lighter opacity), tags using Tag components, and description. Media on right side. Text colors adapt based on variant and useInvertedBackground settings. Best for featured content, case studies, or highlighted features.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Latest Features",
|
||||
"minChars": 2,
|
||||
"maxChars": 50
|
||||
},
|
||||
"description": {
|
||||
"required": true,
|
||||
"example": "Stay updated with our latest announcements",
|
||||
"minChars": 5,
|
||||
"maxChars": 300
|
||||
},
|
||||
"tag": {
|
||||
"required": false,
|
||||
"example": "Features",
|
||||
"minChars": 2,
|
||||
"maxChars": 30
|
||||
}
|
||||
},
|
||||
"itemRules": {
|
||||
"minItems": 1,
|
||||
"maxItems": 10,
|
||||
"recommendedItems": "2-4",
|
||||
"note": "Each feature requires id, title, author, description, tags array. Media uses discriminated union: either imageSrc (with optional imageAlt) OR videoSrc (with optional videoAriaLabel)."
|
||||
}
|
||||
},
|
||||
"propsSchema": {
|
||||
"features": "Array<{ id: string, title: string, author: string, description: string, tags: string[], imageSrc?: string, imageAlt?: string, videoSrc?: string, videoAriaLabel?: string, onFeatureClick?: () => void }> - Feature card items (requires imageSrc or videoSrc)",
|
||||
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' (required)",
|
||||
"title": "string (required)",
|
||||
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
|
||||
"description": "string (required)",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required)",
|
||||
"useInvertedBackground": "boolean (required)",
|
||||
"ariaLabel?": "string (default: 'Features section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string",
|
||||
"titleImageClassName?": "string",
|
||||
"cardContentClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"authorClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"tagsContainerClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"mediaWrapperClassName?": "string",
|
||||
"mediaClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureCardTwentyFour features={[{ id: '1', title: 'New Genre Featured in Fonts in Use', author: 'Leon Brown', description: 'We have been featured in Fonts in Use for our typography choices.', tags: ['Feature', 'Design'], imageSrc: '/feature1.jpg' }]} animationType=\"slide-up\" title=\"Latest Features\" description=\"Stay updated with our latest announcements\" textboxLayout=\"default\" useInvertedBackground={false} />",
|
||||
"do": [
|
||||
"Use for feature articles, case studies, or content with author attribution",
|
||||
"Best for 2-4 featured items",
|
||||
"Include relevant tags for each feature",
|
||||
"Use high-quality images or videos"
|
||||
],
|
||||
"dont": [
|
||||
"Do not use without author attribution",
|
||||
"Do not use for simple feature lists without descriptions"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
114
registry/components/FeatureCardTwentyNine.json
Normal file
114
registry/components/FeatureCardTwentyNine.json
Normal file
@@ -0,0 +1,114 @@
|
||||
{
|
||||
"name": "FeatureCardTwentyNine",
|
||||
"description": "Adaptive feature section with hover-reveal cards displaying features with title icons, verified badges, and action buttons.",
|
||||
"details": "Use for interactive feature showcases with hover effects. Each card displays a title icon, title with verified badge, image background, and description that reveals with a slide-up background animation. Each card has an action button in the top-right corner. Automatically switches between grid (1-4 items) and carousel (5+ items). Carousel offers auto-scroll or button controls (recommended: keep default buttons for better UX). Optional header with title, description, tag, and buttons. Header supports centered or split textbox layout.",
|
||||
"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": {
|
||||
"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
|
||||
},
|
||||
"buttonText": {
|
||||
"required": true,
|
||||
"example": "Learn More",
|
||||
"minChars": 2,
|
||||
"maxChars": 20
|
||||
}
|
||||
},
|
||||
"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)"
|
||||
},
|
||||
"titleIconSrc": {
|
||||
"required": true,
|
||||
"example": "/icon.jpg",
|
||||
"note": "Icon displayed next to the title"
|
||||
}
|
||||
}
|
||||
},
|
||||
"propsSchema": {
|
||||
"features": "Array<{ title: string, description: string, imageSrc: string, imageAlt?: string, titleIconSrc: string, buttonText: string, buttonHref?: 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' (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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxTitleImageWrapperClassName?": "string - For styling image wrapper in inline-image layout",
|
||||
"textBoxTitleImageClassName?": "string - For styling images in inline-image layout",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"gridClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"controlsClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"itemContentClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureCardTwentyNine features={[{ title: 'Analytics', description: 'Track performance with detailed insights', imageSrc: '/feature.jpg', titleIconSrc: '/icon.jpg', buttonText: 'Learn More', buttonHref: 'analytics' }]} title=\"Our Features\" description=\"Discover what makes us different\" textboxLayout=\"default\" gridVariant=\"uniform-all-items-equal\" animationType=\"slide-up\" useInvertedBackground={false} />",
|
||||
"do": [
|
||||
"Use for feature showcases with action buttons",
|
||||
"Use for capability displays with brand icons",
|
||||
"Requires features[]",
|
||||
"Requires titleSegments?[]",
|
||||
"Requires buttons?[]"
|
||||
],
|
||||
"dont": [],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
109
registry/components/FeatureCardTwentyOne.json
Normal file
109
registry/components/FeatureCardTwentyOne.json
Normal file
@@ -0,0 +1,109 @@
|
||||
{
|
||||
"name": "FeatureCardTwentyOne",
|
||||
"description": "Split layout with media on one side and TextBox with accordion items on the other.",
|
||||
"details": "Use for feature sections that need expandable content areas. Layout: 50/50 split with image/video on one side and TextBox + accordion on the other. Media position configurable (left/right). First accordion item open by default. Accordion items have divider lines between them. Mobile: stacked vertically with centered text. Supports inverted backgrounds.",
|
||||
"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",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"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",
|
||||
"mediaAnimation": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"useInvertedBackground": "boolean",
|
||||
"mediaPosition?": "'left' | 'right' (default: 'left')",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"mediaWrapperClassName?": "string",
|
||||
"mediaClassName?": "string",
|
||||
"contentClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"descriptionClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"buttonContainerClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string",
|
||||
"titleImageClassName?": "string",
|
||||
"accordionContainerClassName?": "string",
|
||||
"accordionClassName?": "string",
|
||||
"accordionTitleClassName?": "string",
|
||||
"accordionContentClassName?": "string",
|
||||
"accordionIconContainerClassName?": "string",
|
||||
"accordionIconClassName?": "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={false} 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
|
||||
}
|
||||
}
|
||||
87
registry/components/FeatureCardTwentySeven.json
Normal file
87
registry/components/FeatureCardTwentySeven.json
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"name": "FeatureCardTwentySeven",
|
||||
"description": "Interactive flip cards with 3D rotation effect. Front shows title, icon, and media; back reveals multiple descriptions.",
|
||||
"details": "Use for interactive feature showcases where users can explore details by clicking. Each card flips 180 degrees on Y-axis with 3D perspective. Front side displays title with Plus icon button and media content (image/video). Back side shows same title with X icon (rotated Plus) and multiple description texts. Uses CardStack for grid/carousel layout. Best for 3-6 items where engagement and exploration is desired.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Our Services",
|
||||
"minChars": 2,
|
||||
"maxChars": 50
|
||||
},
|
||||
"description": {
|
||||
"required": true,
|
||||
"example": "Discover what makes us different",
|
||||
"minChars": 5,
|
||||
"maxChars": 300
|
||||
},
|
||||
"tag": {
|
||||
"required": false,
|
||||
"example": "Services",
|
||||
"minChars": 2,
|
||||
"maxChars": 30
|
||||
}
|
||||
},
|
||||
"featureRules": {
|
||||
"minItems": 3,
|
||||
"maxItems": 8,
|
||||
"recommendedItems": "4",
|
||||
"structure": {
|
||||
"id": "string - Unique identifier (required)",
|
||||
"title": "string - Card title on both sides (required)",
|
||||
"descriptions": "string[] - Array of descriptions shown on back side (min: 1, recommended: 3, max: 5)",
|
||||
"imageSrc": "string - Path to image (optional if videoSrc provided) Image is recommended if no videoSrc.",
|
||||
"videoSrc": "string - Path to video (optional if imageSrc provided)",
|
||||
"imageAlt": "string - Alt text for image"
|
||||
},
|
||||
"note": "Each feature requires id, title, descriptions array (1-5 items, recommended 3), and media (image or video). Cards flip to reveal descriptions on click."
|
||||
}
|
||||
},
|
||||
"propsSchema": {
|
||||
"features": "Array<{ id: string, title: string, descriptions: string[], imageSrc?: string, videoSrc?: string, imageAlt?: string }>",
|
||||
"animationType": "CardAnimationType (required)",
|
||||
"title": "string (required)",
|
||||
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
|
||||
"description": "string (required)",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required)",
|
||||
"useInvertedBackground": "'noInvert' | 'invertDefault' (required)",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxTitleImageWrapperClassName?": "string",
|
||||
"textBoxTitleImageClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureCardTwentySeven features={[{ id: '1', title: 'Web Development', descriptions: ['Custom websites built with modern technologies', 'Best practices for optimal performance', 'Responsive design for all devices'], imageSrc: '/service1.jpg', imageAlt: 'Web Development' }]} animationType=\"slide-up\" title=\"Our Services\" description=\"Discover what makes us different\" textboxLayout=\"default\" useInvertedBackground={false} />",
|
||||
"do": [
|
||||
"Use for interactive feature showcases where exploration is desired",
|
||||
"Best for 3-6 items (4 recommended)",
|
||||
"Use high-quality images or videos for the front side",
|
||||
"Keep descriptions concise for back side readability"
|
||||
],
|
||||
"dont": [
|
||||
"Do not use without media for each feature",
|
||||
"Do not use for text-heavy content on front side",
|
||||
"Do not use for more than 8 items"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
93
registry/components/FeatureCardTwentySix.json
Normal file
93
registry/components/FeatureCardTwentySix.json
Normal file
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"name": "FeatureCardTwentySix",
|
||||
"description": "Full-bleed media carousel feature cards with bottom text overlay and arrow navigation.",
|
||||
"details": "Use for showcasing features or courses with strong visual media. Each card has full-bleed image/video with a frosted glass gradient overlay at the bottom containing title, description, and an icon button. Uses ArrowCarousel layout with centered alignment, looping, prev/next arrow controls, and mask-fade-x edges. Active item is full opacity and scale, inactive items are reduced.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Featured Courses",
|
||||
"minChars": 2,
|
||||
"maxChars": 50
|
||||
},
|
||||
"description": {
|
||||
"required": true,
|
||||
"example": "Handpicked by our team to help you start strong",
|
||||
"minChars": 5,
|
||||
"maxChars": 300
|
||||
},
|
||||
"tag": {
|
||||
"required": false,
|
||||
"example": "Popular",
|
||||
"minChars": 2,
|
||||
"maxChars": 30
|
||||
}
|
||||
},
|
||||
"featureRules": {
|
||||
"minItems": 4,
|
||||
"maxItems": 12,
|
||||
"recommendedItems": "6",
|
||||
"note": "MINIMUM 4 ITEMS REQUIRED - carousel needs at least 4 items for proper display",
|
||||
"structure": {
|
||||
"title": "string - Card title displayed over media (required)",
|
||||
"description": "string - Card description displayed over media (required)",
|
||||
"imageSrc": "string - Path to background image (optional if videoSrc provided) Image is recommended if no videoSrc.",
|
||||
"videoSrc": "string - Path to background video (optional if imageSrc provided)",
|
||||
"imageAlt": "string - Alt text for background image",
|
||||
"videoAriaLabel": "string - Aria label for background video",
|
||||
"buttonIcon": "LucideIcon - Icon inside the card action button (required)",
|
||||
"buttonHref": "string - Navigation target for button (optional)",
|
||||
"buttonOnClick": "() => void - Click handler for button (optional)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"propsSchema": {
|
||||
"features": "Array<{ title: string, description: string, imageSrc?: string, videoSrc?: string, imageAlt?: string, videoAriaLabel?: string, buttonIcon: LucideIcon, buttonHref?: string, buttonOnClick?: () => void }> (MINIMUM 4 ITEMS REQUIRED)",
|
||||
"title": "string (required)",
|
||||
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
|
||||
"description": "string (required)",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'inline-image' (required)",
|
||||
"useInvertedBackground": "boolean (required)",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"controlsClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxTitleImageWrapperClassName?": "string",
|
||||
"textBoxTitleImageClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"cardButtonClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureCardTwentySix features={[{ title: 'UX Design Fundamentals', description: 'Learn user-centered design from scratch', imageSrc: '/course1.jpg', imageAlt: 'UX Design course', buttonIcon: ArrowRight, buttonHref: '#courses' }]} title=\"Featured Courses\" description=\"Handpicked by our team\" textboxLayout=\"default\" useInvertedBackground={false} />",
|
||||
"do": [
|
||||
"Use for showcasing features or courses with strong visual media",
|
||||
"Best for 4-12 items (6 recommended)",
|
||||
"Use high-quality images or videos for full-bleed display",
|
||||
"Each card requires a buttonIcon for the action button"
|
||||
],
|
||||
"dont": [
|
||||
"Do not use with fewer than 4 items - carousel requires minimum 4 items",
|
||||
"Do not use without media for each feature",
|
||||
"Do not use without buttonIcon",
|
||||
"Do not use for text-heavy content"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
123
registry/components/FeatureCardTwentyThree.json
Normal file
123
registry/components/FeatureCardTwentyThree.json
Normal file
@@ -0,0 +1,123 @@
|
||||
{
|
||||
"name": "FeatureCardTwentyThree",
|
||||
"description": "Feature section with separate media and card layout, featuring tags and arrow navigation.",
|
||||
"details": "Use for feature listings with prominent imagery. Layout: CardStackTextBox header → Grid of feature items. Each item has separate media (aspect-square) above a card containing title, tags row, and arrow icon. Media and card are visually distinct with gap-6 spacing. Tags use the Tag component and arrow rotates -45deg on hover. Best for visual-focused feature listings with clean separation between imagery and content.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Our Features",
|
||||
"minChars": 2,
|
||||
"maxChars": 50
|
||||
},
|
||||
"description": {
|
||||
"required": true,
|
||||
"example": "Stay updated with the latest trends and insights",
|
||||
"minChars": 5,
|
||||
"maxChars": 300
|
||||
},
|
||||
"tag": {
|
||||
"required": false,
|
||||
"example": "Features",
|
||||
"minChars": 2,
|
||||
"maxChars": 30
|
||||
}
|
||||
},
|
||||
"featureRules": {
|
||||
"id": {
|
||||
"required": true,
|
||||
"example": "1",
|
||||
"note": "Unique identifier for the feature item"
|
||||
},
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Discover the essential features of our app",
|
||||
"minChars": 10,
|
||||
"maxChars": 100
|
||||
},
|
||||
"tags": {
|
||||
"required": true,
|
||||
"minItems": 1,
|
||||
"maxItems": 4,
|
||||
"structure": "string[]",
|
||||
"example": "['Features', 'Jan 29, 2025']",
|
||||
"note": "Array of tag strings displayed using Tag component"
|
||||
},
|
||||
"imageSrc": {
|
||||
"required": false,
|
||||
"example": "/feature-1.jpg",
|
||||
"note": "Either imageSrc or videoSrc should be provided Either imageSrc or videoSrc should be provided. Image is recommended if no videoSrc."
|
||||
},
|
||||
"videoSrc": {
|
||||
"required": false,
|
||||
"example": "/feature-1.mp4",
|
||||
"note": "Either imageSrc or videoSrc should be provided"
|
||||
},
|
||||
"imageAlt": {
|
||||
"required": false,
|
||||
"example": "Feature preview image",
|
||||
"note": "Falls back to feature title if not provided"
|
||||
},
|
||||
"videoAriaLabel": {
|
||||
"required": false,
|
||||
"example": "Feature video",
|
||||
"note": "Falls back to feature title if not provided"
|
||||
}
|
||||
}
|
||||
},
|
||||
"propsSchema": {
|
||||
"features": "Array<{ id: string, title: string, tags: string[], imageSrc?: string, videoSrc?: string, imageAlt?: string, videoAriaLabel?: string, onFeatureClick?: () => void }>",
|
||||
"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)",
|
||||
"useInvertedBackground": "boolean",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"carouselMode?": "'auto' | 'buttons' (default: 'buttons')",
|
||||
"uniformGridCustomHeightClasses?": "string",
|
||||
"ariaLabel?": "string (default: 'Features section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"itemClassName?": "string",
|
||||
"mediaWrapperClassName?": "string",
|
||||
"mediaClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"tagsContainerClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"arrowClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxTitleImageWrapperClassName?": "string",
|
||||
"textBoxTitleImageClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"gridClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"controlsClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureCardTwentyThree features={[{ id: '1', title: 'Discover the essential features of our app', tags: ['Features', 'Jan 29, 2025'], imageSrc: '/feature1.jpg' }, { id: '2', title: 'How to organize your tasks effectively', tags: ['Guides', 'Feb 03, 2025'], imageSrc: '/feature2.jpg' }]} animationType=\"slide-up\" title=\"Our Features\" description=\"Stay updated with the latest trends and insights\" textboxLayout=\"default\" useInvertedBackground={false} />",
|
||||
"do": [
|
||||
"Use for visual-focused feature listings",
|
||||
"Include 1-4 tags per feature",
|
||||
"Use high-quality square images",
|
||||
"Best for feature showcases with clean separation between imagery and content"
|
||||
],
|
||||
"dont": [
|
||||
"Do not use without tags",
|
||||
"Do not use for text-heavy features"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
107
registry/components/FeatureHoverPattern.json
Normal file
107
registry/components/FeatureHoverPattern.json
Normal file
@@ -0,0 +1,107 @@
|
||||
{
|
||||
"name": "FeatureHoverPattern",
|
||||
"description": "CardStack feature section with interactive hover pattern effect revealing behind centered icons.",
|
||||
"details": "Use for feature showcases with visual engagement through hover interactions. Uses CardStack with uniform-all-items-equal grid (hardcoded). Each card displays a centered icon in a container with hover-triggered pattern reveal using GSAP ScrollTrigger. Pattern appears on mouse movement (desktop) or scroll viewport visibility (mobile). Desktop: Mouse movement reveals radial gradient pattern with random character overlay. Mobile: Pattern activates when card enters viewport (20% threshold for pattern, 40% for icon). Each card has icon in center with card styling, title and description below. Icon containers have backdrop-blur-sm with border. Pattern uses Framer Motion with useMotionValue for smooth tracking. Supports custom gradient colors via gradientClassName. All cards have min-h-80 2xl:min-h-90 default height. Best for 2-6 features to showcase key product benefits with interactive visual appeal.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Powerful Features",
|
||||
"minChars": 2,
|
||||
"maxChars": 35
|
||||
},
|
||||
"description": {
|
||||
"required": true,
|
||||
"example": "Hover over each card to reveal the interactive pattern",
|
||||
"minChars": 5,
|
||||
"maxChars": 250
|
||||
},
|
||||
"tag": {
|
||||
"required": false,
|
||||
"example": "Features",
|
||||
"minChars": 2,
|
||||
"maxChars": 30
|
||||
}
|
||||
},
|
||||
"featureCardRules": {
|
||||
"icon": {
|
||||
"required": true,
|
||||
"example": "Zap",
|
||||
"note": "LucideIcon component displayed in center of card with hover pattern"
|
||||
},
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Lightning Fast",
|
||||
"minChars": 2,
|
||||
"maxChars": 40
|
||||
},
|
||||
"description": {
|
||||
"required": true,
|
||||
"example": "Optimized for performance with minimal overhead and blazing fast load times",
|
||||
"minChars": 10,
|
||||
"maxChars": 200
|
||||
}
|
||||
},
|
||||
"itemRules": {
|
||||
"minItems": 2,
|
||||
"maxItems": 6,
|
||||
"recommendedItems": "2-6",
|
||||
"note": "Works best with 2-6 features for optimal grid layout"
|
||||
}
|
||||
},
|
||||
"propsSchema": {
|
||||
"features": "Array<{ icon: LucideIcon, title: string, description: string, button?: ButtonConfig }> (required)",
|
||||
"animationType": "'none' | 'opacity' | 'slide-up' | 'scale-rotate' | 'blur-reveal' (required)",
|
||||
"title": "string (required)",
|
||||
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
|
||||
"description": "string (required)",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required - 'inline-image' uses titleSegments for rich text with images)",
|
||||
"useInvertedBackground": "boolean (required)",
|
||||
"carouselMode?": "'auto' | 'buttons' (default: 'buttons' - for 5+ items)",
|
||||
"uniformGridCustomHeightClasses?": "string (default: 'min-h-80 2xl:min-h-90')",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"iconContainerClassName?": "string",
|
||||
"iconClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string",
|
||||
"titleImageClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"gradientClassName?": "string - Custom gradient for hover pattern (default: 'bg-gradient-to-r from-accent to-background-accent')",
|
||||
"gridClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"controlsClassName?": "string",
|
||||
"cardButtonClassName?": "string",
|
||||
"cardButtonTextClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureHoverPattern features={[{ icon: Zap, title: 'Lightning Fast', description: 'Optimized for performance with minimal overhead' }, { icon: Shield, title: 'Secure by Default', description: 'Built with security best practices' }]} title=\"Powerful Features\" description=\"Hover over each card to reveal the interactive pattern\" textboxLayout=\"default\" animationType=\"slide-up\" useInvertedBackground={false} />",
|
||||
"do": [
|
||||
"Use for feature showcases with visual engagement",
|
||||
"Best for 2-6 features",
|
||||
"Each feature requires an icon",
|
||||
"Supports custom gradient colors via gradientClassName"
|
||||
],
|
||||
"dont": [
|
||||
"Do not use without icons for each feature",
|
||||
"Do not use for simple text-only feature lists"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
111
registry/components/FeatureTimelineBento.json
Normal file
111
registry/components/FeatureTimelineBento.json
Normal file
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"name": "FeatureTimelineBento",
|
||||
"description": "Timeline-based feature section with scroll-triggered stacking animations and bento component visualizations instead of images.",
|
||||
"details": "Use for process flows, roadmaps, or sequential feature presentations with interactive visualizations. Each card displays a numbered step badge, title, description, and a bento component visualization in a two-column layout. As you scroll, cards stack on top of each other with fade animations. The timeline layout provides a clear visual progression through steps or stages. Supports 15 bento types: globe, icon-info-cards, animated-bar-chart, 3d-stack-cards, 3d-task-list, orbiting-icons, map, marquee, line-chart, 3d-card-grid, phone, chat, reveal-icon, timeline, media-stack. No grid/carousel modes - uses fixed timeline stacking layout with GSAP ScrollTrigger. Optional header with title, description, tag, and buttons. Header supports centered or split textbox layout.",
|
||||
"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": {
|
||||
"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
|
||||
}
|
||||
},
|
||||
"bentoComponentRules": {
|
||||
"note": "CRITICAL: Each feature MUST use a DIFFERENT bentoComponent type. Never repeat the same type across features (e.g., don't use 'timeline' twice). Requirements vary by type:",
|
||||
"types": {
|
||||
"globe": "{ bentoComponent: 'globe' } - No additional fields required",
|
||||
"animated-bar-chart": "{ bentoComponent: 'animated-bar-chart' } - No additional fields required",
|
||||
"map": "{ bentoComponent: 'map' } - No additional fields required",
|
||||
"line-chart": "{ bentoComponent: 'line-chart' } - No additional fields required",
|
||||
"icon-info-cards": "{ bentoComponent: 'icon-info-cards', items: Array<{ icon: LucideIcon, label: string, value: string }> } - Requires items array",
|
||||
"3d-stack-cards": "{ bentoComponent: '3d-stack-cards', items: [Bento3DItem, Bento3DItem, Bento3DItem] } - Requires exactly 3 items. Each item: { icon: LucideIcon, title: string, subtitle: string, detail: string }",
|
||||
"3d-task-list": "{ bentoComponent: '3d-task-list', bentoTitle: string, items: Array<{ icon: LucideIcon, label: string, time: string }> } - Requires bentoTitle (not title) and items array",
|
||||
"orbiting-icons": "{ bentoComponent: 'orbiting-icons', centerIcon: LucideIcon, items: Array<{ icon: LucideIcon, ring?: 1 | 2 | 3, duration?: number }> } - Requires centerIcon and items array",
|
||||
"marquee": "{ bentoComponent: 'marquee', centerIcon: LucideIcon, variant: 'text' | 'icon', texts?: string[], icons?: LucideIcon[] } - Requires centerIcon and variant",
|
||||
"phone": "{ bentoComponent: 'phone', statusIcon: LucideIcon, alertIcon: LucideIcon, alertTitle: string, alertMessage: string, apps: PhoneApps8 } - Requires all fields",
|
||||
"chat": "{ bentoComponent: 'chat', aiIcon: LucideIcon, userIcon: LucideIcon, exchanges: Array<{ userMessage: string, aiResponse: string }>, placeholder: string } - Requires all fields",
|
||||
"3d-card-grid": "{ bentoComponent: '3d-card-grid', items: [GridCardItem x4], centerIcon: LucideIcon } - Requires exactly 4 items and centerIcon",
|
||||
"reveal-icon": "{ bentoComponent: 'reveal-icon', icon: LucideIcon } - Requires icon",
|
||||
"timeline": "{ bentoComponent: 'timeline', heading: string, subheading: string, items: [TimelineItem x3], completedLabel: string } - Requires exactly 3 items",
|
||||
"media-stack": "{ bentoComponent: 'media-stack', items: [MediaStackItem x3] } - Requires exactly 3 items"
|
||||
}
|
||||
}
|
||||
},
|
||||
"propsSchema": {
|
||||
"features": "Array<{ title: string, description: string, buttons?: ButtonConfig[] } & BentoComponentVariant> - Each card has title, description, optional buttons, and one bentoComponent type with its required props",
|
||||
"title": "string (required)",
|
||||
"titleSegments?": "Array<{ type: 'text', content: string } | { type: 'image', src: string, alt?: string }> - For inline images in title",
|
||||
"description": "string (required)",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"textboxLayout": "'default' | 'split' | 'split-actions' | 'split-description' | 'inline-image' (required)",
|
||||
"useInvertedBackground": "boolean (required)",
|
||||
"ariaLabel?": "string (default: 'Feature section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxTitleClassName?": "string",
|
||||
"textBoxDescriptionClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"textBoxTagClassName?": "string",
|
||||
"textBoxButtonContainerClassName?": "string",
|
||||
"textBoxButtonClassName?": "string",
|
||||
"textBoxButtonTextClassName?": "string",
|
||||
"titleImageWrapperClassName?": "string",
|
||||
"titleImageClassName?": "string",
|
||||
"cardContentClassName?": "string",
|
||||
"stepNumberClassName?": "string",
|
||||
"cardTitleClassName?": "string",
|
||||
"cardDescriptionClassName?": "string",
|
||||
"bentoContainerClassName?": "string",
|
||||
"cardButtonClassName?": "string",
|
||||
"cardButtonTextClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FeatureTimelineBento features={[{ title: 'Global Analytics', description: 'Track performance worldwide', bentoComponent: 'globe' }, { title: 'Team Metrics', description: 'Monitor team performance', bentoComponent: 'icon-info-cards', items: [{icon: Users, label: 'Active', value: '1,234'}] }]} title=\"Our Process\" description=\"See how it works\" textboxLayout=\"default\" useInvertedBackground={false} />",
|
||||
"do": [
|
||||
"Use for process flows with interactive visualizations",
|
||||
"Use for roadmaps with rich content",
|
||||
"Use for step-by-step explanations with visual aids",
|
||||
"Use appropriate bentoComponent for each step",
|
||||
"Requires features[]"
|
||||
],
|
||||
"dont": [
|
||||
"CRITICAL: NEVER use the same bentoComponent type for multiple features - each feature MUST have a unique/different bento type (e.g., if one uses 'timeline', others must use 'reveal-icon', 'chat', 'globe', etc.)",
|
||||
"Do not use for non-sequential content",
|
||||
"Do not use with single item"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
20
registry/components/FloatingGradientBackground.json
Normal file
20
registry/components/FloatingGradientBackground.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "FloatingGradientBackground",
|
||||
"description": "Five animated gradient circles with CSS animations and vertical gradient mask.",
|
||||
"details": "Use for dynamic, engaging backgrounds with subtle motion. Features 5 circles with different animations (moveVertical, moveInCircle, moveHorizontal) using primary-cta and accent colors. Includes 40px blur and linear gradient mask (transparent → visible 20-80% → transparent). Circles have varying opacities (0.1-0.2) and use hard-light blend mode.",
|
||||
"constraints": {},
|
||||
"propsSchema": {
|
||||
"className?": "string"
|
||||
},
|
||||
"usageExample": "<FloatingGradientBackground />",
|
||||
"do": [
|
||||
"Use for feature showcases",
|
||||
"Use for capability displays"
|
||||
],
|
||||
"dont": [],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
20
registry/components/FluidBackground.json
Normal file
20
registry/components/FluidBackground.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "FluidBackground",
|
||||
"description": "Generative fluid patterns using CPPN shader with theme color integration.",
|
||||
"details": "Use for modern, dynamic backgrounds with organic fluid patterns. Features real-time WebGL shader animation using CPPN (Compositional Pattern Producing Networks) that creates continuously morphing, fluid-like patterns. Automatically adapts to theme colors by reading CSS variables (--background, --color-primary-cta, --color-accent, --color-secondary-cta) and blending them with generated patterns. Uses React Three Fiber for 3D rendering with dynamic viewport sizing. Performance optimized with React.memo and responsive to window resizing. Best for contemporary, premium designs where subtle motion adds visual interest without distraction.",
|
||||
"constraints": {},
|
||||
"propsSchema": {
|
||||
"className?": "string"
|
||||
},
|
||||
"usageExample": "<FluidBackground />",
|
||||
"do": [
|
||||
"Use for feature showcases",
|
||||
"Use for capability displays"
|
||||
],
|
||||
"dont": [],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
84
registry/components/FooterBase.json
Normal file
84
registry/components/FooterBase.json
Normal file
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"name": "FooterBase",
|
||||
"description": "Classic footer with logo, multi-column navigation, copyright text, and privacy policy link.",
|
||||
"details": "Use for standard website footers with organized navigation. Features logoText as h2 heading on left, flexible column layout for navigation links, copyright text, and privacy policy button. All links use ButtonTextUnderline component. Footer uses primary-button background with text-background color scheme.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"logoText": {
|
||||
"required": true,
|
||||
"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)",
|
||||
"logoSrc?": "string",
|
||||
"logoAlt?": "string",
|
||||
"logoText": "string (required)",
|
||||
"copyrightText?": "string (default: '© 2025 | Webild')",
|
||||
"onPrivacyClick?": "() => void",
|
||||
"ariaLabel?": "string (default: 'Site footer')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"logoClassName?": "string",
|
||||
"logoImageClassName?": "string",
|
||||
"logoTextClassName?": "string",
|
||||
"columnsClassName?": "string",
|
||||
"columnClassName?": "string",
|
||||
"columnTitleClassName?": "string",
|
||||
"columnItemClassName?": "string",
|
||||
"copyrightContainerClassName?": "string",
|
||||
"copyrightTextClassName?": "string",
|
||||
"privacyButtonClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FooterBase logoText=\"Company Name\" 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
|
||||
}
|
||||
}
|
||||
69
registry/components/FooterBaseCard.json
Normal file
69
registry/components/FooterBaseCard.json
Normal file
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"name": "FooterBaseCard",
|
||||
"description": "Card-wrapped footer with logo, navigation columns, copyright, and privacy policy link.",
|
||||
"details": "Use for footers that need comprehensive navigation within a card container. Layout: Section wrapper (py-20) → Card container (w-content-width, rounded-theme-capped, p-10) → Top section (logo + FooterColumns in flex-row) → Border divider (border-t, border-foreground/20) → Bottom section (copyright + privacy button). Logo supports either image (logoSrc with Next.js Image) or text heading (logoText, text-4xl). Navigation organized via FooterColumns component accepting array of column objects with title and items. Bottom section displays copyright text (text-foreground/50, text-sm) on left and privacy policy button (ButtonTextUnderline) on right in flex row. Card wrapper provides unified, elevated appearance compared to FooterBase. Text colors use foreground variants since content is within card element. Best for comprehensive footer navigation with modern card styling. Uses semantic footer tag with contentinfo role.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"copyrightText": {
|
||||
"required": false,
|
||||
"example": "© 2025 | Webild",
|
||||
"minChars": 5,
|
||||
"maxChars": 100,
|
||||
"note": "Copyright text displayed at bottom left"
|
||||
},
|
||||
"logoText": {
|
||||
"required": true,
|
||||
"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": {
|
||||
"logoSrc?": "string",
|
||||
"logoAlt?": "string",
|
||||
"logoText": "string (required)",
|
||||
"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",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"logoClassName?": "string",
|
||||
"logoImageClassName?": "string",
|
||||
"logoTextClassName?": "string",
|
||||
"columnsClassName?": "string",
|
||||
"columnClassName?": "string",
|
||||
"columnTitleClassName?": "string",
|
||||
"columnItemClassName?": "string",
|
||||
"copyrightContainerClassName?": "string",
|
||||
"copyrightTextClassName?": "string",
|
||||
"privacyButtonClassName?": "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
|
||||
}
|
||||
}
|
||||
80
registry/components/FooterBaseReveal.json
Normal file
80
registry/components/FooterBaseReveal.json
Normal file
@@ -0,0 +1,80 @@
|
||||
{
|
||||
"name": "FooterBaseReveal",
|
||||
"description": "Animated footer reveal wrapper that creates a fixed footer with scroll-triggered reveal effect.",
|
||||
"details": "Use when you want the footer to stay fixed at the bottom and reveal as users scroll. Wraps FooterBase component with fixed positioning and dynamic height calculation using ResizeObserver. Creates a reveal animation effect as content scrolls up. Ideal for modern, engaging scroll experiences.",
|
||||
"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": {
|
||||
"logoSrc?": "string",
|
||||
"logoAlt?": "string",
|
||||
"logoText": "string (required)",
|
||||
"columns": "Array<{ title: string, items: Array<{ label: string, href: string }> }> - Footer navigation columns (required)",
|
||||
"copyrightText?": "string",
|
||||
"onPrivacyClick?": "() => void",
|
||||
"ariaLabel?": "string",
|
||||
"className?": "string",
|
||||
"wrapperClassName?": "string",
|
||||
"containerClassName?": "string",
|
||||
"footerClassName?": "string",
|
||||
"footerContainerClassName?": "string",
|
||||
"logoClassName?": "string",
|
||||
"logoImageClassName?": "string",
|
||||
"logoTextClassName?": "string",
|
||||
"columnsClassName?": "string",
|
||||
"columnClassName?": "string",
|
||||
"columnTitleClassName?": "string",
|
||||
"columnItemClassName?": "string",
|
||||
"copyrightContainerClassName?": "string",
|
||||
"copyrightTextClassName?": "string",
|
||||
"privacyButtonClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FooterBaseReveal logoText=\"Company Name\" 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
|
||||
}
|
||||
}
|
||||
64
registry/components/FooterCard.json
Normal file
64
registry/components/FooterCard.json
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"name": "FooterCard",
|
||||
"description": "Minimalist footer with card wrapper containing logo, divider, copyright, and optional social links.",
|
||||
"details": "Use for simple, clean footer layouts with card styling. Layout: Section wrapper (py-20) → Card container (w-content-width, rounded-theme-capped, px-10) → FooterLogo → Divider line (h-px, bg-accent/20) → Bottom section (copyright text + optional social links). Logo supports either image (logoSrc) or SVG text (logoText via FooterLogo component). Divider uses accent color with 20% opacity. Bottom section displays copyright (text-accent/75, text-sm) on left and optional social icons on right in flex row (mobile: stacks vertically). Social links are conditionally rendered only when provided. All elements contained within card for unified appearance. Best for simple, modern footer designs without extensive navigation. Uses semantic footer tag with contentinfo role.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"copyrightText": {
|
||||
"required": false,
|
||||
"example": "© 2025 | Webild",
|
||||
"minChars": 5,
|
||||
"maxChars": 100,
|
||||
"note": "Copyright text displayed at bottom left"
|
||||
},
|
||||
"logoText": {
|
||||
"required": true,
|
||||
"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": {
|
||||
"logoSrc?": "string",
|
||||
"logoAlt?": "string",
|
||||
"logoText": "string (required)",
|
||||
"copyrightText?": "string (default: '© 2025 | Webild')",
|
||||
"socialLinks?": "Array<{ icon: LucideIcon, href: string, ariaLabel: string }> - Social media links",
|
||||
"ariaLabel?": "string (default: 'Site footer')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"cardClassName?": "string",
|
||||
"logoClassName?": "string",
|
||||
"logoImageClassName?": "string",
|
||||
"dividerClassName?": "string",
|
||||
"copyrightContainerClassName?": "string",
|
||||
"copyrightTextClassName?": "string",
|
||||
"socialContainerClassName?": "string",
|
||||
"socialIconClassName?": "string"
|
||||
},
|
||||
"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
|
||||
}
|
||||
}
|
||||
72
registry/components/FooterLogoEmphasis.json
Normal file
72
registry/components/FooterLogoEmphasis.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"name": "FooterLogoEmphasis",
|
||||
"description": "Footer with prominent centered logo emphasis and grid-based navigation layout with chevron icons.",
|
||||
"details": "Use when logo branding is primary focus in footer. Features large centered logo at top (image or SVG text), followed by responsive grid of navigation links (1-5 columns max) with ChevronRight icons. Grid columns automatically adjust based on number of column arrays provided. No column titles - just clean link lists. Uses primary-button background with rounded-t-theme-capped styling.",
|
||||
"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": {
|
||||
"logoSrc?": "string",
|
||||
"logoAlt?": "string",
|
||||
"columns": "Array<{ items: Array<{ label: string, href?: string, onClick?: () => void }> }> - Footer navigation columns (required, max 5)",
|
||||
"logoText": "string (required)",
|
||||
"ariaLabel?": "string (default: 'Site footer')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"logoClassName?": "string",
|
||||
"logoImageClassName?": "string",
|
||||
"columnsClassName?": "string",
|
||||
"columnClassName?": "string",
|
||||
"itemClassName?": "string",
|
||||
"iconClassName?": "string",
|
||||
"buttonClassName?": "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
|
||||
}
|
||||
}
|
||||
72
registry/components/FooterLogoEmphasisReveal.json
Normal file
72
registry/components/FooterLogoEmphasisReveal.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"name": "FooterLogoEmphasisReveal",
|
||||
"description": "Footer with prominent centered logo emphasis that reveals from behind content as user scrolls (sticky reveal effect).",
|
||||
"details": "Use when logo branding is primary focus and you want a sticky reveal effect. Wraps FooterLogoEmphasis with scroll-based reveal animation - footer stays fixed at bottom and reveals as content scrolls past. Features large centered logo at top, followed by responsive grid of navigation links (1-5 columns max) with ChevronRight icons. Grid columns automatically adjust based on number of column arrays provided. No column titles - just clean link lists. Uses primary-button background with rounded-t-theme-capped styling.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"logoText": {
|
||||
"required": true,
|
||||
"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 (required)",
|
||||
"ariaLabel?": "string (default: 'Site footer')",
|
||||
"className?": "string",
|
||||
"wrapperClassName?": "string",
|
||||
"containerClassName?": "string",
|
||||
"footerClassName?": "string",
|
||||
"footerContainerClassName?": "string",
|
||||
"logoClassName?": "string",
|
||||
"columnsClassName?": "string",
|
||||
"columnClassName?": "string",
|
||||
"itemClassName?": "string",
|
||||
"iconClassName?": "string",
|
||||
"buttonClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FooterLogoEmphasisReveal columns={[{ items: [{ label: 'Features', href: 'features' }] }, { items: [{ label: 'About', href: 'about' }] }]} logoText=\"Company\" />",
|
||||
"do": [
|
||||
"Use for feature showcases",
|
||||
"Use for capability displays",
|
||||
"Use for sticky reveal footer effect",
|
||||
"Requires columns[]"
|
||||
],
|
||||
"dont": [
|
||||
"Do not use more than 5 columns"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
46
registry/components/FooterLogoReveal.json
Normal file
46
registry/components/FooterLogoReveal.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "FooterLogoReveal",
|
||||
"description": "Minimalist footer with logo that reveals on scroll using fixed positioning and clip-path.",
|
||||
"details": "Use for minimal, logo-only footers with scroll reveal effect. Footer stays fixed at bottom and reveals as user scrolls down the page using clip-path animation. Contains only FooterLogo component (supports image or SVG text logo) centered with card styling. Uses ResizeObserver to dynamically track footer height for proper reveal effect. Best for clean, modern designs where footer should not distract from content. Uses semantic section and footer tags with contentinfo role.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"logoText": {
|
||||
"required": true,
|
||||
"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": {
|
||||
"logoSrc?": "string",
|
||||
"logoAlt?": "string",
|
||||
"logoText": "string (required)",
|
||||
"leftLink": "{ text: string, onClick?: () => void, href?: string } (required)",
|
||||
"rightLink": "{ text: string, onClick?: () => void, href?: string } (required)",
|
||||
"ariaLabel?": "string (default: 'Site footer')",
|
||||
"className?": "string",
|
||||
"wrapperClassName?": "string",
|
||||
"containerClassName?": "string",
|
||||
"logoClassName?": "string",
|
||||
"logoImageClassName?": "string",
|
||||
"linkClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FooterLogoReveal logoText=\"Webild\" leftLink={{ text: 'Privacy Policy', href: '/privacy' }} rightLink={{ text: 'Terms of Service', href: '/terms' }} />",
|
||||
"do": [
|
||||
"Use for general use"
|
||||
],
|
||||
"dont": [],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
102
registry/components/FooterMedia.json
Normal file
102
registry/components/FooterMedia.json
Normal file
@@ -0,0 +1,102 @@
|
||||
{
|
||||
"name": "FooterMedia",
|
||||
"description": "Footer with full-width media (image/video) above classic navigation layout.",
|
||||
"details": "Use for visually impactful footers with media. Features full-width image or video at top with mask-fade-top-long effect (fades from top), followed by standard footer layout: logoText as h2 heading, multi-column navigation, copyright, and privacy policy. Media is required (either imageSrc or videoSrc). Same navigation structure as FooterBase.",
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"logoText": {
|
||||
"required": true,
|
||||
"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",
|
||||
"note": "Either imageSrc or videoSrc should be provided. Image is recommended if no videoSrc."
|
||||
},
|
||||
"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')",
|
||||
"logoSrc?": "string",
|
||||
"logoAlt?": "string",
|
||||
"logoText": "string (required)",
|
||||
"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",
|
||||
"containerClassName?": "string",
|
||||
"mediaWrapperClassName?": "string",
|
||||
"mediaClassName?": "string",
|
||||
"logoClassName?": "string",
|
||||
"logoImageClassName?": "string",
|
||||
"logoTextClassName?": "string",
|
||||
"columnsClassName?": "string",
|
||||
"columnClassName?": "string",
|
||||
"columnTitleClassName?": "string",
|
||||
"columnItemClassName?": "string",
|
||||
"copyrightContainerClassName?": "string",
|
||||
"copyrightTextClassName?": "string",
|
||||
"privacyButtonClassName?": "string"
|
||||
},
|
||||
"usageExample": "<FooterMedia logoText=\"Company Name\" 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
|
||||
}
|
||||
}
|
||||
78
registry/components/FooterSimple.json
Normal file
78
registry/components/FooterSimple.json
Normal file
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"name": "FooterSimple",
|
||||
"description": "Minimal footer with navigation columns, divider, and bottom text row.",
|
||||
"details": "Use for clean, simple footers without card styling or logo emphasis. Features navigation columns spread across the top, a horizontal divider line, and a bottom row with left and right text (e.g., copyright and credits). No card wrapper, no logo section. Best for minimal designs where footer should be functional but unobtrusive.",
|
||||
"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",
|
||||
"containerClassName?": "string",
|
||||
"columnsClassName?": "string",
|
||||
"columnClassName?": "string",
|
||||
"columnTitleClassName?": "string",
|
||||
"columnItemClassName?": "string",
|
||||
"dividerClassName?": "string",
|
||||
"bottomContainerClassName?": "string",
|
||||
"bottomLeftTextClassName?": "string",
|
||||
"bottomRightTextClassName?": "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
|
||||
}
|
||||
}
|
||||
27
registry/components/GradientBarsBackground.json
Normal file
27
registry/components/GradientBarsBackground.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "GradientBarsBackground",
|
||||
"description": "Gradient bars on left and right edges with fade masks creating a spotlight center effect.",
|
||||
"details": "Use for modern backgrounds with vertical gradient bars positioned on left and right sides. Features two groups of bars (8 per side by default) that fade towards the center using CSS masks. Main container has vertical fade from bottom to top. Left bars fade towards center (270deg mask), right bars fade towards center (90deg mask). Creates an open center area (30% by default) for content. Each bar has horizontal gradient using theme primary color. Perfect for hero sections or landing pages where center content needs visual framing.",
|
||||
"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} 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
|
||||
}
|
||||
}
|
||||
24
registry/components/GridBackround.json
Normal file
24
registry/components/GridBackround.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "GridBackround",
|
||||
"description": "Grid pattern background with line-based grid and optional 3D perspective effect.",
|
||||
"details": "Use for technical or structured layouts. Features adjustable grid size (small: 16 cells, medium: 10 cells, large: 5 cells per 100vw). Optional perspectiveThreeD adds skew transform and radial mask for depth. Uses background-accent color at 10% opacity.",
|
||||
"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
|
||||
}
|
||||
}
|
||||
142
registry/components/HeroBillboard.json
Normal file
142
registry/components/HeroBillboard.json
Normal file
@@ -0,0 +1,142 @@
|
||||
{
|
||||
"name": "HeroBillboard",
|
||||
"description": "Full-width hero section with centered text content, configurable background, optional tag, buttons, avatar group, single image/video below in a card frame, and optional logo marquee.",
|
||||
"details": "Use for simple, impactful landing page hero sections. Features centered title and description with TextBox animations, required background variant (choose from animated grids, gradient effects, or 'plain' for no background), optional tag with icon, up to 2 CTA buttons, optional avatar group with text displayed above the tag, a single image or video media content below the text in a card wrapper with padding, and an optional logo marquee below the media. Background variants include preset options for zero-config usage.",
|
||||
"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 Either imageSrc or videoSrc should be provided. Image is recommended if no videoSrc."
|
||||
},
|
||||
"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."
|
||||
},
|
||||
"avatarRules": {
|
||||
"avatars": {
|
||||
"required": false,
|
||||
"example": "[{ src: '/avatar1.jpg', alt: 'User 1' }, { src: '/avatar2.jpg', alt: 'User 2' }]",
|
||||
"note": "Array of Avatar objects with src and alt. Displayed above the tag in a centered group."
|
||||
},
|
||||
"avatarText": {
|
||||
"required": false,
|
||||
"example": "Trusted by 10,000+ users",
|
||||
"note": "Text displayed next to the avatar group"
|
||||
}
|
||||
},
|
||||
"marqueeRules": {
|
||||
"marqueeItems": {
|
||||
"required": false,
|
||||
"example": "[{ type: 'image', src: '/logo1.svg', alt: 'Partner 1' }, { type: 'text', text: 'Partner Name' }]",
|
||||
"note": "Array of MarqueeItem objects. Rendered below the media content (not absolute positioned)."
|
||||
},
|
||||
"marqueeSpeed": {
|
||||
"required": false,
|
||||
"default": 30,
|
||||
"note": "Speed of the marquee animation"
|
||||
},
|
||||
"showMarqueeCard": {
|
||||
"required": false,
|
||||
"default": true,
|
||||
"note": "Whether to show the card wrapper around marquee items"
|
||||
}
|
||||
}
|
||||
},
|
||||
"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' }",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"avatars?": "Array<{src: string, alt: string}>",
|
||||
"avatarText?": "string",
|
||||
"imageSrc?": "string",
|
||||
"videoSrc?": "string",
|
||||
"imageAlt?": "string (default: '')",
|
||||
"videoAriaLabel?": "string (default: 'Hero video')",
|
||||
"mediaAspectRatio?": "string (default: 'aspect-square md:aspect-video')",
|
||||
"mediaAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"marqueeItems?": "Array<MarqueeItem>",
|
||||
"marqueeSpeed?": "number (default: 30)",
|
||||
"showMarqueeCard?": "boolean (default: true)",
|
||||
"ariaLabel?": "string (default: 'Hero section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"descriptionClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"avatarGroupClassName?": "string",
|
||||
"buttonContainerClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "string",
|
||||
"mediaWrapperClassName?": "string",
|
||||
"imageClassName?": "string",
|
||||
"marqueeClassName?": "string",
|
||||
"marqueeItemClassName?": "string",
|
||||
"marqueeCardClassName?": "string",
|
||||
"marqueeImageClassName?": "string",
|
||||
"marqueeTextClassName?": "string",
|
||||
"marqueeIconClassName?": "string"
|
||||
},
|
||||
"usageExample": "<ThemeProvider defaultButtonVariant=\"text-stagger\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"rounded\">\n <HeroBillboard \n background={{ variant: 'sparkles-gradient' }}\n title=\"Welcome to Our Platform\" \n description=\"Create beautiful, responsive web experiences\" \n tag=\"New Release\" \n tagIcon={Sparkles}\n avatars={[\n { src: '/avatar1.jpg', alt: 'User 1' },\n { src: '/avatar2.jpg', alt: 'User 2' },\n { src: '/avatar3.jpg', alt: 'User 3' },\n ]}\n avatarText=\"Trusted by 10,000+ users\"\n imageSrc=\"/hero.jpg\" \n imageAlt=\"Hero banner\"\n buttons={[{ text: 'Get Started', href: 'https://example.com' }, { text: 'Learn More', href: 'about' }]}\n marqueeItems={[\n { type: 'image', src: '/logo1.svg', alt: 'Partner 1' },\n { type: 'image', src: '/logo2.svg', alt: 'Partner 2' },\n ]}\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
|
||||
}
|
||||
}
|
||||
88
registry/components/HeroBillboardCarousel.json
Normal file
88
registry/components/HeroBillboardCarousel.json
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"name": "HeroBillboardCarousel",
|
||||
"description": "Full-width hero section with centered text, configurable background, and 5+ auto-scrolling images in carousel layout.",
|
||||
"details": "Use for showcasing large collections or portfolios. Features centered title and description with TextBox animations, required background variant (choose from animated grids, gradient effects, or 'plain' for no background), optional tag with icon, up to 2 CTA buttons. Displays 5 or more images in auto-scrolling carousel on both mobile and desktop. Full viewport height with vertical centering on desktop. Background variants include preset options for zero-config usage.",
|
||||
"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' }",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"mediaItems": "Array<{ imageSrc?: string, videoSrc?: string, imageAlt?: string, videoAriaLabel?: string }> - Each item requires either imageSrc or videoSrc",
|
||||
"ariaLabel?": "string (default: 'Hero section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"descriptionClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"buttonContainerClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "string",
|
||||
"mediaWrapperClassName?": "string"
|
||||
},
|
||||
"usageExample": "<ThemeProvider defaultButtonVariant=\"text-stagger\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"rounded\">\n <HeroBillboardCarousel \n background={{ variant: 'sparkles-gradient' }}\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
|
||||
}
|
||||
}
|
||||
114
registry/components/HeroBillboardDashboard.json
Normal file
114
registry/components/HeroBillboardDashboard.json
Normal file
@@ -0,0 +1,114 @@
|
||||
{
|
||||
"name": "HeroBillboardDashboard",
|
||||
"description": "Full-width hero section with centered text content and an interactive Dashboard component below instead of a static image/video.",
|
||||
"details": "Based on HeroBillboard layout — centered TextBox with title, description, tag, and buttons on top, with a full Dashboard component below. The Dashboard includes icon sidebar, search bar, avatar, action buttons, 3 stat cards with animated number cycling (values rotate every 3s via TextNumberCount), a BentoLineChart, and a vertically auto-scrolling list. On mobile, stat cards become a carousel with arrow navigation. Desktop stat cards have staggered GSAP scroll entrance. All Dashboard props are passed via a single 'dashboard' object prop.",
|
||||
"requiredImports": {
|
||||
"lucide-react": ["Sparkles", "Hexagon", "House", "MessageSquareText", "Settings", "CircleDollarSign", "ArrowLeftRight", "Send"],
|
||||
"note": "Import all icons used in tagIcon, dashboard.logoIcon, dashboard.sidebarItems[].icon, dashboard.listItems[].icon. Use component names, not strings."
|
||||
},
|
||||
"typeDefinitions": {
|
||||
"DashboardStat": {
|
||||
"title": "string (required)",
|
||||
"values": "[number, number, number] - exactly 3 numbers, cycled every 3s (required)",
|
||||
"valuePrefix": "string (optional, e.g. '$')",
|
||||
"valueSuffix": "string (optional, e.g. 'M')",
|
||||
"description": "string (required)",
|
||||
"titleMobile": "string (optional, shorter label for mobile)"
|
||||
},
|
||||
"DashboardSidebarItem": {
|
||||
"icon": "LucideIcon - import from lucide-react (required)",
|
||||
"active": "boolean (optional, default false)"
|
||||
},
|
||||
"DashboardListItem": {
|
||||
"icon": "LucideIcon - import from lucide-react (required)",
|
||||
"title": "string (required)",
|
||||
"status": "string (required)"
|
||||
},
|
||||
"ChartDataItem": {
|
||||
"value": "number (required)"
|
||||
}
|
||||
},
|
||||
"constraints": {
|
||||
"textRules": {
|
||||
"title": {
|
||||
"required": true,
|
||||
"example": "Real-Time On-Chain Intelligence",
|
||||
"minChars": 2,
|
||||
"maxChars": 40
|
||||
},
|
||||
"description": {
|
||||
"required": true,
|
||||
"example": "Monitor protocol revenue, trading volume, and wallet activity.",
|
||||
"minChars": 5,
|
||||
"maxChars": 200
|
||||
},
|
||||
"tag": {
|
||||
"required": false,
|
||||
"example": "Live Analytics",
|
||||
"minChars": 2,
|
||||
"maxChars": 30
|
||||
}
|
||||
},
|
||||
"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: 'View Docs', href: 'docs' }"
|
||||
],
|
||||
"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."
|
||||
},
|
||||
"dashboardRules": {
|
||||
"required": ["title", "stats", "logoIcon", "sidebarItems", "buttons", "listItems", "imageSrc"],
|
||||
"stats": "Exactly 3 DashboardStat objects. See typeDefinitions.DashboardStat.",
|
||||
"sidebarItems": "Array of DashboardSidebarItem. At least 1 item. See typeDefinitions.DashboardSidebarItem.",
|
||||
"listItems": "Array of DashboardListItem. At least 1 item. See typeDefinitions.DashboardListItem.",
|
||||
"buttons": "Array of ButtonConfig. Max 2. Same structure as hero buttons.",
|
||||
"chartData": "Optional. Array of ChartDataItem. See typeDefinitions.ChartDataItem.",
|
||||
"imageSrc": "string - URL for avatar image in dashboard header"
|
||||
}
|
||||
},
|
||||
"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' }",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"dashboard": "Object. Required: title, stats (exactly 3), logoIcon, sidebarItems, buttons, listItems, imageSrc. Optional: searchPlaceholder, chartTitle, chartData, listTitle, videoSrc, imageAlt, videoAriaLabel, className, containerClassName, sidebarClassName, statClassName, chartClassName, listClassName. See typeDefinitions for DashboardStat, DashboardSidebarItem, DashboardListItem, ChartDataItem.",
|
||||
"ariaLabel?": "string (default: 'Hero section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"descriptionClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"buttonContainerClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "string",
|
||||
"dashboardClassName?": "string"
|
||||
},
|
||||
"usageExample": "import { Sparkles, Hexagon, House, MessageSquareText, Settings, CircleDollarSign, ArrowLeftRight, Send } from 'lucide-react';\nimport HeroBillboardDashboard from '@/components/sections/hero/HeroBillboardDashboard';\n\n<HeroBillboardDashboard\n background={{ variant: 'radial-gradient' }}\n tag=\"Live Analytics\"\n tagIcon={Sparkles}\n title=\"Real-Time On-Chain Intelligence\"\n description=\"Monitor protocol revenue, trading volume, and wallet activity.\"\n buttons={[{ text: 'Get Started', href: '#' }, { text: 'View Docs', href: '#' }]}\n dashboard={{\n title: \"On-Chain Metrics Hub\",\n logoIcon: Hexagon,\n imageSrc: \"https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=100&h=100&fit=crop&crop=face\",\n buttons: [{ text: \"Dashboard\", href: \"#\" }, { text: \"Export CSV\", href: \"#\" }],\n sidebarItems: [{ icon: House, active: true }, { icon: MessageSquareText }, { icon: Settings }],\n stats: [\n { title: \"Revenue\", values: [178425, 245890, 312750], valuePrefix: \"$\", description: \"Protocol fees.\" },\n { title: \"Volume\", values: [7.84, 12.5, 9.32], valuePrefix: \"$\", valueSuffix: \"M\", description: \"Transaction flow.\" },\n { title: \"Wallets\", values: [11240, 15680, 13450], description: \"Active wallets.\" },\n ],\n chartTitle: \"Staking Rewards\",\n chartData: [{ value: 50 }, { value: 30 }, { value: 70 }, { value: 40 }, { value: 90 }],\n listTitle: \"Treasury Transfers\",\n listItems: [\n { icon: CircleDollarSign, title: \"$12,000 USDC\", status: \"Confirmed\" },\n { icon: ArrowLeftRight, title: \"Swap: 5 ETH\", status: \"Executed\" },\n { icon: Send, title: \"Transfer: 2,500 DAI\", status: \"Confirmed\" },\n ],\n }}\n/>",
|
||||
"do": [
|
||||
"Use for SaaS landing pages",
|
||||
"Use for analytics/dashboard product showcases",
|
||||
"Use for data visualization platforms",
|
||||
"Requires dashboard prop with all nested properties"
|
||||
],
|
||||
"dont": [
|
||||
"Do not use without dashboard data",
|
||||
"Do not use for simple hero sections without interactive elements"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
94
registry/components/HeroBillboardGallery.json
Normal file
94
registry/components/HeroBillboardGallery.json
Normal file
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"name": "HeroBillboardGallery",
|
||||
"description": "Full-width hero section with centered text, configurable background, and 3-5 overlapping rotated images in gallery layout.",
|
||||
"details": "Use for visually rich landing pages showcasing multiple images. Features centered title and description with TextBox animations, required background variant (choose from animated grids, gradient effects, or 'plain' for no background), optional tag with icon, up to 2 CTA buttons. Gallery shows 3-5 overlapping images with rotation effects. Mobile displays AutoCarousel, desktop shows overlapping rotated images. Full viewport height with vertical centering on desktop. Background variants include preset options for zero-config usage.",
|
||||
"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": {
|
||||
"minItems": 3,
|
||||
"maxItems": 5,
|
||||
"note": "MINIMUM 3 ITEMS REQUIRED - gallery needs at least 3 items for proper display",
|
||||
"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."
|
||||
}
|
||||
},
|
||||
"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' }",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"mediaItems": "Array<{ imageSrc?: string, videoSrc?: string, imageAlt?: string, videoAriaLabel?: string }> (MINIMUM 3 ITEMS REQUIRED, max 5)",
|
||||
"mediaAnimation": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"ariaLabel?": "string (default: 'Hero section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"descriptionClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"buttonContainerClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "string",
|
||||
"mediaWrapperClassName?": "string",
|
||||
"imageClassName?": "string"
|
||||
},
|
||||
"usageExample": "<ThemeProvider defaultButtonVariant=\"text-stagger\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"rounded\">\n <HeroBillboardGallery \n background={{ variant: 'radial-gradient' }}\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 with fewer than 3 items - gallery requires minimum 3 items",
|
||||
"Do not use more than 5 items"
|
||||
],
|
||||
"editRules": {
|
||||
"textOnly": true,
|
||||
"layoutLocked": true,
|
||||
"styleLocked": true
|
||||
}
|
||||
}
|
||||
102
registry/components/HeroBillboardRotatedCarousel.json
Normal file
102
registry/components/HeroBillboardRotatedCarousel.json
Normal file
@@ -0,0 +1,102 @@
|
||||
{
|
||||
"name": "HeroBillboardRotatedCarousel",
|
||||
"description": "Hero section with centered text content and angled/rotated carousel below. Features auto-playing carousel with scaled and rotated side cards.",
|
||||
"details": "Use for product showcases, portfolios, or visual-heavy landing pages. Features centered title, description, optional tag with icon, and action buttons via TextBox component. Below is an AngledCarousel showing rotated preview cards on sides (88% scale, 2deg rotation) with center card at full scale. Carousel auto-advances every 4 seconds. Side cards have backdrop blur overlay. Requires minimum 6 carousel items to avoid duplicate key warnings (carousel shows 5 positions: -2, -1, 0, 1, 2). Uses full viewport height with custom spacing.",
|
||||
"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) Image is recommended if no videoSrc.",
|
||||
"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' }",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"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)",
|
||||
"marqueeItems?": "Array<{ type: 'image', src: string, alt?: string } | { type: 'text', text: string } | { type: 'text-icon', text: string, icon: LucideIcon }> - Logo marquee items",
|
||||
"marqueeSpeed?": "number (default: 30)",
|
||||
"showMarqueeCard?": "boolean (default: true)",
|
||||
"ariaLabel?": "string (default: 'Hero section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"descriptionClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"buttonContainerClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "string",
|
||||
"carouselClassName?": "string",
|
||||
"marqueeClassName?": "string",
|
||||
"marqueeItemClassName?": "string",
|
||||
"marqueeCardClassName?": "string",
|
||||
"marqueeImageClassName?": "string",
|
||||
"marqueeTextClassName?": "string",
|
||||
"marqueeIconClassName?": "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 background={{ variant: \"glowing-orb\" }}\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
|
||||
}
|
||||
}
|
||||
125
registry/components/HeroBillboardScroll.json
Normal file
125
registry/components/HeroBillboardScroll.json
Normal file
@@ -0,0 +1,125 @@
|
||||
{
|
||||
"name": "HeroBillboardScroll",
|
||||
"description": "Full-screen hero section with centered text, configurable background, and media card that animates with 3D perspective transforms on scroll (desktop only).",
|
||||
"details": "Use for modern, interactive landing pages showcasing products, dashboards, or applications with scroll-triggered effects. Features required background variant (choose from animated grids, gradient effects, or 'plain' for no background), centered TextBox, and animated media card. On desktop, the media card animates from rotated (20deg X-axis) and scaled (1.05) to flat and normal scale as user scrolls down. Mobile displays a static 3D-rotated card without animation to avoid performance issues. Background variants include preset options for zero-config usage. Requires ReactLenis for smooth scroll tracking.",
|
||||
"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 Either imageSrc or videoSrc should be provided. Image is recommended if no videoSrc."
|
||||
},
|
||||
"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' }",
|
||||
"tag?": "string",
|
||||
"tagIcon?": "LucideIcon",
|
||||
"tagAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"buttons?": "Array<{text: string, onClick?: () => void, href?: string}>",
|
||||
"buttonAnimation?": "'none' | 'opacity' | 'slide-up' | 'blur-reveal'",
|
||||
"imageSrc?": "string",
|
||||
"videoSrc?": "string",
|
||||
"imageAlt?": "string (default: '')",
|
||||
"videoAriaLabel?": "string (default: 'Hero video')",
|
||||
"mediaAspectRatio?": "string (default: 'aspect-[4/3] md:aspect-[16/9]')",
|
||||
"marqueeItems?": "Array<MarqueeItem>",
|
||||
"marqueeSpeed?": "number (default: 30)",
|
||||
"showMarqueeCard?": "boolean (default: true)",
|
||||
"ariaLabel?": "string (default: 'Hero section')",
|
||||
"className?": "string",
|
||||
"containerClassName?": "string",
|
||||
"textBoxClassName?": "string",
|
||||
"titleClassName?": "string",
|
||||
"descriptionClassName?": "string",
|
||||
"tagClassName?": "string",
|
||||
"buttonContainerClassName?": "string",
|
||||
"buttonClassName?": "string",
|
||||
"buttonTextClassName?": "string",
|
||||
"cardWrapperClassName?": "string",
|
||||
"cardInnerClassName?": "string",
|
||||
"imageClassName?": "string",
|
||||
"marqueeClassName?": "string",
|
||||
"marqueeItemClassName?": "string",
|
||||
"marqueeCardClassName?": "string",
|
||||
"marqueeImageClassName?": "string",
|
||||
"marqueeTextClassName?": "string",
|
||||
"marqueeIconClassName?": "string"
|
||||
},
|
||||
"usageExample": "<ThemeProvider defaultButtonVariant=\"hover-bubble\" defaultTextAnimation=\"entrance-slide\" borderRadius=\"pill\">\n <HeroBillboardScroll \n background={{ variant: 'canvas-reveal' }}\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
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user