Initial commit

This commit is contained in:
kudinDmitriyUp
2026-05-10 11:26:23 +00:00
commit 45c34cdf29
260 changed files with 29556 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
---
paths:
- "src/components/**/*.tsx"
---
# Accessibility Patterns
## Interactive Components
### ariaLabel Prop
Always include `ariaLabel` prop with sensible fallback:
```typescript
interface Props {
ariaLabel?: string;
}
<section aria-label={ariaLabel || "Default section label"}>
```
### Disabled States
```tsx
<button
disabled={isDisabled}
className="disabled:cursor-not-allowed disabled:opacity-50"
>
```
### Focus Indicators
Custom focus indicators for consistent styling:
```tsx
<button className="focus:outline-none focus:ring-2 focus:ring-foreground/50">
```
---
## Media Components
### Images
Use `aria-hidden` for decorative images:
```tsx
<img
src={imageSrc}
alt={imageAlt}
aria-hidden={imageAlt === ""}
/>
```
### Videos
Always include `videoAriaLabel` prop:
```tsx
<video aria-label={videoAriaLabel || "Video content"}>
```
---
## Semantic HTML
### Heading Hierarchy
- `h1` - Page title (one per page)
- `h2` - Section headings
- `h3` - Subsection headings
- `h4` - Card titles
### Semantic Elements
Use appropriate semantic elements:
- `<section>` - Thematic groupings of content
- `<nav>` - Navigation blocks
- `<article>` - Self-contained content
- `<aside>` - Tangentially related content
- `<main>` - Primary content area
- `<header>` / `<footer>` - Section headers/footers

View File

@@ -0,0 +1,95 @@
---
paths:
- "src/components/text/**/*.tsx"
- "src/components/hooks/**/*.ts"
- "src/components/sections/**/*.tsx"
---
# Animation Patterns
## Button Animation Types
Apply to `tagAnimation` or `buttonAnimation` props:
```typescript
type ButtonAnimationType = "none" | "opacity" | "slide-up" | "blur-reveal";
```
- `none` - No animation
- `opacity` - Fade in
- `slide-up` - Fade + slide from bottom
- `blur-reveal` - Fade with blur clearing
---
## Text Animation Types
Set via `defaultTextAnimation` in ThemeProvider or `type` prop in TextAnimation:
```typescript
type AnimationType = "entrance-slide" | "reveal-blur" | "background-highlight";
```
- `entrance-slide` - Characters slide up from bottom
- `reveal-blur` - Text appears with blur clearing
- `background-highlight` - Text highlights from dim to full opacity
---
## Animation Hooks
```typescript
import { useButtonAnimation } from "@/components/hooks/useButtonAnimation";
// Animate children on scroll
const { containerRef } = useButtonAnimation({ animationType: "slide-up" });
<div ref={containerRef}>
<button>Animates on scroll</button>
</div>
```
---
## CardStack Animation Types
- `none` - No animation
- `opacity` - Fade in
- `slide-up` - Slide with stagger
- `scale-rotate` - Scale + rotate with stagger
- `blur-reveal` - Blur to clear with stagger
- `depth-3d` - 3D perspective (grid only, desktop)
---
## GSAP Best Practices
### Plugin Registration
Register plugins at file level, not in useEffect:
```typescript
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
```
### Cleanup with gsap.context()
Always use gsap.context() for proper cleanup:
```typescript
useEffect(() => {
const ctx = gsap.context(() => {
gsap.to(".element", { opacity: 1 });
}, containerRef);
return () => ctx.revert();
}, []);
```
### Performance
- Use `force3D: true` for GPU acceleration
- Prefer transform properties (x, y, scale, rotation)
- Consider disabling complex animations on mobile

159
.claude/rules/components.md Normal file
View File

@@ -0,0 +1,159 @@
---
paths:
- "src/components/**/*.tsx"
---
# Component Patterns
## Naming Conventions (CRITICAL)
### Prop Naming
| Use | Don't Use |
|-----|-----------|
| `title` | `heading`, `headline` |
| `description` | `subtitle`, `text`, `content` |
| `text` (for buttons) | `title`, `label`, `buttonText` |
### className Prop Pattern
- `className` - Main wrapper element
- `containerClassName` - Inner container
- `[element]ClassName` - Specific elements (titleClassName, imageClassName)
### ButtonConfig
```typescript
// CORRECT - variant controlled by ThemeProvider
{ text: "Get Started", href: "/start" }
// WRONG - never specify variant in config
{ text: "Get Started", variant: "primary" } // ❌
```
---
## Component Composition Principle (CRITICAL)
When creating new components, **ALWAYS base them on existing similar components** to maintain consistency.
### The Rule
1. **Identify the base component** - Find an existing component with similar layout/purpose
2. **Identify feature components** - Find existing implementations of any features you're adding
3. **Confirm with user** - Propose which components you'll use as references before implementing
4. **Compose, don't reinvent** - Use patterns, code structure, and styling from the base components
---
## Canonical Base Components
### Hero Sections
| Component | Use As Base When |
|-----------|------------------|
| `HeroSplit` | Split layouts with media left/right positioning |
| `HeroBillboard` | Full-width centered layouts with media below |
| `HeroOverlay` | Media backgrounds with text overlay |
### Feature Sections
| Component | Use As Base When |
|-----------|------------------|
| `FeatureBento` | Complex card layouts with multiple variants |
| `FeatureCardOne` | Simple media + text card grids |
| `FeatureCardSix` | Sequential process/step displays |
### Testimonial Sections
| Component | Use As Base When |
|-----------|------------------|
| `TestimonialCardThirteen` | Card-based testimonials with ratings |
| `TestimonialCardTen` | Testimonials with associated media |
### Other Sections
| Component | Use As Base When |
|-----------|------------------|
| `PricingCardThree` | Comparison tables with feature lists |
| `TeamCardOne` | Image-first cards with overlay text |
| `ContactSplitForm` | Forms with media split layout |
| `FaqDouble` | Two-column accordion layouts |
| `FooterBase` | Simple column-based footers |
| `MetricCardOne` | Large number displays with gradient effects |
| `BlogCardOne` | Content cards with metadata and images |
| `SplitAbout` | Split layouts with bullet points |
---
## Canonical Shared Components
Always use these existing implementations rather than creating new ones:
| Component | Purpose | File |
|-----------|---------|------|
| `MediaContent` | Image/video display | `/src/components/shared/MediaContent.tsx` |
| `AvatarGroup` | Avatar displays with overflow | `/src/components/shared/AvatarGroup.tsx` |
| `TestimonialAuthor` | Author/attribution cards | `/src/components/shared/TestimonialAuthor.tsx` |
| `LogoMarquee` | Scrolling logo displays | `/src/components/shared/LogoMarquee.tsx` |
| `Tag` | Theme-aware badges | `/src/components/shared/Tag.tsx` |
| `Badge` | Simple primary badges | `/src/components/shared/Badge.tsx` |
| `CardStack` | Grid/carousel layouts | `/src/components/cardStack/CardStack.tsx` |
| `CardStackTextBox` | Section headers | `/src/components/cardStack/CardStackTextBox.tsx` |
| `TextAnimation` | Animated text | `/src/components/text/TextAnimation.tsx` |
---
## Core Component Usage
### TextBox
```typescript
import TextBox from "@/components/Textbox";
// Default layout - centered stack
<TextBox
title="Your Title"
description="Your description text"
tag="Optional Tag"
tagIcon={Sparkles}
buttons={[{ text: "Primary", href: "/action" }]}
center={true}
/>
// Layout options: "default" | "split" | "split-actions" | "split-description" | "inline-image"
```
### Button
Buttons automatically get styling based on their index:
- **Index 0** = `primary-button` class with `text-primary-cta-text`
- **Index 1+** = `secondary-button` class with `text-secondary-cta-text`
### MediaContent
```typescript
import MediaContent from "@/components/shared/MediaContent";
<MediaContent
imageSrc="/image.jpg"
imageAlt="Description"
imageClassName="rounded-theme"
/>
// Video takes precedence over image when both provided
<MediaContent
videoSrc="/video.mp4"
videoAriaLabel="Video description"
/>
```
### AnimationContainer
```typescript
import AnimationContainer from "@/components/sections/AnimationContainer";
<AnimationContainer>
<div>Content animates in (fade + slide)</div>
</AnimationContainer>
<AnimationContainer animationType="fade">
<div>Fades in only</div>
</AnimationContainer>
```

123
.claude/rules/registry.md Normal file
View File

@@ -0,0 +1,123 @@
---
paths:
- "registry/**/*.json"
---
# Registry Patterns
The registry system enables AI tooling and code generation for components.
---
## Registry Files
| File | Purpose | When to Update |
|------|---------|----------------|
| `registry.json` | Full component configs with constraints | New component, prop changes |
| `registry/components/[Name].json` | Individual component config | New component, prop changes |
| `registry/schemas/[Name].schema.json` | Props schema for code gen | New component, prop changes |
| `registry/index.json` | Category/intent mapping | New component |
| `registry/intents.json` | Intent groupings | New component or intent |
---
## registry/index.json Entry
```json
{
"ComponentName": {
"category": "hero",
"intent": "hero with media",
"bestFor": ["landing pages", "product launches"],
"avoidWhen": ["simple text-only sections"],
"requires": ["title", "description", "background"],
"import": "@/components/sections/hero/ComponentName"
}
}
```
---
## registry/components/[Name].json Format
```json
{
"name": "ComponentName",
"description": "Brief description of the component",
"details": "Detailed usage information",
"constraints": {
"textRules": {
"title": {
"required": true,
"example": "Example title text",
"minChars": 4,
"maxChars": 50
},
"description": {
"required": true,
"example": "Example description text",
"minChars": 20,
"maxChars": 200
}
}
},
"propsSchema": {
"title": "string",
"description": "string",
"optionalProp?": "string (default: 'value')"
},
"usageExample": "<ComponentName title=\"...\" />",
"do": ["Use for X", "Use for Y"],
"dont": ["Don't use for Z"],
"editRules": {
"textOnly": true,
"layoutLocked": true,
"styleLocked": true
}
}
```
---
## registry/schemas/[Name].schema.json Format
```json
{
"name": "ComponentName",
"propsSchema": {
"title": "string",
"description": "string",
"optionalProp?": "string (default: 'value')"
}
}
```
---
## Props Schema Conventions
- Required props: `"propName": "type"`
- Optional props: `"propName?": "type (default: 'value')"`
- Arrays: `"items": "Array<{ name: string, value: string }>"`
- Complex types: Include description after type
Example:
```json
{
"title": "string",
"description": "string",
"inputs": "Array<{ name: string, type: string, placeholder: string }> - Form input fields",
"mediaPosition?": "'left' | 'right' (default: 'right')",
"onSubmit?": "(data: Record<string, string>) => void"
}
```
---
## Keeping Registry in Sync
**Critical**: Registry must exactly match component props.
1. Optional props in component → `"prop?"` in schema
2. Default values in component → `(default: 'value')` in schema
3. All prop types must match TypeScript interface

188
.claude/rules/styling.md Normal file
View File

@@ -0,0 +1,188 @@
---
paths:
- "src/**/*.tsx"
- "src/**/*.css"
---
# Styling Patterns
This codebase uses **custom-defined CSS variables** for all sizing, spacing, and dimensions. **DO NOT use default Tailwind classes** that are not defined in this system.
---
## What NOT to Use
These default Tailwind classes are **NOT defined** and will not work:
```tsx
// DO NOT USE - undefined width classes
w-xs, w-sm, w-md, w-lg, w-xl, w-2xl, w-3xl, w-4xl, w-5xl, w-6xl, w-7xl
w-screen, w-min, w-max, w-fit (except these work)
w-96, w-80, w-72, w-64, w-56, w-48 (fixed pixel widths)
// DO NOT USE - undefined height classes
h-screen (use h-svh instead), h-min, h-max
h-96, h-80, h-72, h-64, h-56, h-48 (fixed pixel widths except defined ones)
// DO NOT USE - undefined spacing beyond 8
p-9, p-10, p-11, p-12, p-14, p-16, p-20, p-24, etc.
m-9, m-10, m-11, m-12, m-14, m-16, m-20, m-24, etc.
gap-9, gap-10, gap-11, gap-12, etc.
// DO NOT USE - undefined border radius
rounded-2xl, rounded-3xl (use rounded-theme or rounded-theme-capped)
```
---
## What TO Use
| Category | Use These | Don't Use |
|----------|-----------|-----------|
| **Width** | `w-5` to `w-100`, `w-content-width`, fractions | `w-xs`, `w-md`, `w-lg`, `w-96` |
| **Height** | `h-4` to `h-12`, `h-30`, `h-90` to `h-150`, `h-svh` | `h-screen`, `h-96`, `h-80` |
| **Padding** | `p-1` to `p-8` | `p-9`, `p-10`, `p-12`, `p-16` |
| **Margin** | `m-1` to `m-8` | `m-9`, `m-10`, `m-12`, `m-16` |
| **Gap** | `gap-1` to `gap-8` | `gap-9`, `gap-10`, `gap-12` |
| **Text** | `text-2xs` to `text-9xl` | (all defined) |
| **Radius** | `rounded-theme`, `rounded-theme-capped` | `rounded-2xl`, `rounded-3xl` |
---
## Spacing Scale (1-8 ONLY)
All spacing uses VW-based fluid scaling. **Only values 1-8 are defined:**
- `p-1` to `p-8`, `m-1` to `m-8`, `gap-1` to `gap-8`
- Directional: `px-4`, `py-6`, `mx-2`, `my-4`, etc.
---
## Content Width (CRITICAL FOR SECTIONS)
**`w-content-width`** is the most important width class - use it for all section content containers:
```tsx
// ALWAYS use w-content-width for section containers
<section className="relative w-full">
<div className="w-content-width mx-auto">
{/* Section content goes here */}
</div>
</section>
<div className="w-content-width" /> // Main content width
<div className="w-content-width-expanded" /> // Expanded (for carousels)
```
---
## Width Scale
| Pattern | Values | Notes |
|---------|--------|-------|
| `w-5` to `w-100` | Increments of 5 (5vw to 100vw) | Main width classes |
| `w-7_5`, `w-12_5`, etc. | Increments of 2.5 | Half-step widths |
| `w-carousel-item-3`, `w-carousel-item-4` | Carousel widths | For carousel items |
| `w-full`, `w-1/2`, `w-1/3`, etc. | Standard fractions | Tailwind defaults work |
---
## Height Scale
Heights use standard rem on desktop, but become vw-based on mobile (< 768px).
- **Standard**: `h-4` to `h-12` (1rem to 3rem)
- **Large**: `h-30`, `h-90` to `h-150` (for larger containers)
- **Viewport**: Use `h-svh` instead of `h-screen`
---
## Text Sizes
`text-2xs` to `text-9xl` - all fluid (clamp-based).
Key sizes:
- `text-base` - body text
- `text-6xl` - section headings
- `text-7xl`/`text-8xl` - hero headings
---
## Border Radius
Use theme-aware classes:
- `rounded-theme` - uses ThemeProvider setting
- `rounded-theme-capped` - max xl
---
## Hero Page Padding
Special padding for hero sections that accounts for navbar:
```tsx
<section className="py-hero-page-padding" /> // Standard
<section className="py-hero-page-padding-half" /> // Half
<section className="py-hero-page-padding-1_5" /> // 1.5x
<section className="py-hero-page-padding-double" /> // Double
```
---
## Color Variables
Defined in `src/app/styles/variables.css`:
```css
--background: #f5f4ef /* Page background */
--card: #dad6cd /* Card backgrounds */
--foreground: #2a2928 /* Text color */
--primary-cta: #2a2928 /* Primary button background */
--primary-cta-text: #f5f4ef /* Primary button text */
--secondary-cta: #ecebea /* Secondary button background */
--secondary-cta-text: #2a2928 /* Secondary button text */
--accent: #ffffff /* Accent highlights, glows */
--background-accent: #c6b180 /* Accent variant */
```
Use as Tailwind classes: `bg-background`, `text-foreground`, etc.
---
## Dynamic CSS Classes
These classes are styled based on ThemeProvider configuration:
```tsx
<div className="card rounded-theme p-6">Card content</div>
<button className="primary-button rounded-theme px-6 py-3">Primary</button>
<button className="secondary-button rounded-theme px-6 py-3">Secondary</button>
```
---
## Inverted Background Pattern
For sections that need dark backgrounds:
```typescript
// Required prop - forces explicit choice
useInvertedBackground: boolean
// Usage in component
<section className={cls("w-full", useInvertedBackground && "bg-foreground")}>
<p className={useInvertedBackground ? "text-background" : "text-foreground"}>
Content
</p>
</section>
```
---
## Using CSS Variables Directly
When you need values not available as Tailwind classes:
```tsx
<div className="bottom-[calc(var(--spacing-4)+var(--spacing-4))]" />
<div className="left-[calc(var(--vw-1)*2)]" />
```

View File

@@ -0,0 +1,69 @@
---
paths:
- "src/components/**/*.tsx"
- "src/hooks/**/*.ts"
---
# v2 to v4 Transformation
## Quick Reference
| v2 | v4 |
|----|-----|
| GSAP + ScrollTrigger | `motion/react` with `whileInView` |
| Character-level text hooks | `TextAnimation` component (word-level) |
| `buttons: ButtonConfig[]` | `primaryButton` / `secondaryButton` objects |
| 10+ className props | Single `className` prop |
| CardStack/TextBox wrappers | Direct composition |
| Complex media props | Discriminated union: `{ imageSrc } \| { videoSrc }` |
## Animation Variants
| v2 | v4 |
|----|-----|
| `entrance-slide` | `slide-up` |
| `reveal-blur` | `fade-blur` |
| `background-highlight` | `fade` |
## Allowed Hooks
Only 2 custom hooks exist in v4:
- `useCarouselControls` - Embla carousel state
- `useButtonClick` - Navigation handling
All other animation hooks are replaced by `TextAnimation`, `Button animate`, or inline `motion`.
## Standard Motion Animation
```tsx
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-15%" }}
transition={{ duration: 0.6, ease: "easeOut" }}
>
```
## Props Pattern
```tsx
type SectionProps = {
tag: string;
title: string;
description: string;
primaryButton: { text: string; href: string };
secondaryButton: { text: string; href: string };
} & ({ imageSrc: string; videoSrc?: never } | { videoSrc: string; imageSrc?: never });
```
## Checklist
1. Replace GSAP with `motion/react`
2. Replace animation hooks with `TextAnimation` or `Button animate`
3. Use discriminated unions for media props
4. Use `primaryButton`/`secondaryButton` instead of buttons array
5. Remove all className props except single `className`
6. Replace CardStack with `GridOrCarousel`
7. Replace TextBox with direct `TextAnimation` + `Button` composition
8. Add `aria-label` to sections
9. Use `w-content-width` for containers