Initial commit
This commit is contained in:
83
.claude/rules/accessibility.md
Normal file
83
.claude/rules/accessibility.md
Normal 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
|
||||
95
.claude/rules/animations.md
Normal file
95
.claude/rules/animations.md
Normal 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
159
.claude/rules/components.md
Normal 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
123
.claude/rules/registry.md
Normal 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
188
.claude/rules/styling.md
Normal 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)]" />
|
||||
```
|
||||
69
.claude/rules/transformation.md
Normal file
69
.claude/rules/transformation.md
Normal 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
|
||||
41
.claude/skills/add-animation/SKILL.md
Normal file
41
.claude/skills/add-animation/SKILL.md
Normal file
@@ -0,0 +1,41 @@
|
||||
---
|
||||
name: add-animation
|
||||
description: Add animation to a component with proper setup and cleanup
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
# Add Animation
|
||||
|
||||
Add animation to: $ARGUMENTS
|
||||
|
||||
## Process
|
||||
|
||||
1. **Choose animation library**
|
||||
- GSAP: Complex timelines, ScrollTrigger, text splitting
|
||||
- Framer Motion: Simple component animations, gestures, layout
|
||||
- CSS: Basic transitions, hover states
|
||||
|
||||
2. **For GSAP animations**
|
||||
- Register plugins at file level
|
||||
- Use `gsap.context()` for cleanup
|
||||
- Return `() => ctx.revert()` from useEffect
|
||||
- Use refs for target elements
|
||||
|
||||
3. **For Framer Motion**
|
||||
- Wrap conditionally rendered elements in `AnimatePresence`
|
||||
- Add `key` prop for AnimatePresence children
|
||||
- Use `initial`, `animate`, `exit` props
|
||||
|
||||
4. **For scroll-triggered animations**
|
||||
- Set appropriate `start` and `end` points
|
||||
- Use `toggleActions` for replay behavior
|
||||
- Consider mobile: disable or simplify
|
||||
|
||||
5. **Performance considerations**
|
||||
- Use transform properties (x, y, scale, rotation)
|
||||
- Add `force3D: true` for GPU acceleration
|
||||
- Check if animation should be disabled on mobile
|
||||
|
||||
## Output
|
||||
|
||||
Show the implemented animation code with proper cleanup.
|
||||
47
.claude/skills/add-to-registry/SKILL.md
Normal file
47
.claude/skills/add-to-registry/SKILL.md
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
name: add-to-registry
|
||||
description: Add a component to the registry system for AI tooling
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
# Add to Registry
|
||||
|
||||
Add component to registry: $ARGUMENTS
|
||||
|
||||
## Process
|
||||
|
||||
1. **Identify component props**
|
||||
- Read the component's TypeScript interface
|
||||
- Note required vs optional props
|
||||
- Note default values
|
||||
|
||||
2. **Update registry.json**
|
||||
- Add full entry with constraints, propsSchema, usage example
|
||||
- Include textRules for text props (min/max chars)
|
||||
- Include do/dont guidelines
|
||||
|
||||
3. **Create component config**
|
||||
- Create `registry/components/[Name].json`
|
||||
- Match structure of existing component configs
|
||||
|
||||
4. **Create schema file**
|
||||
- Create `registry/schemas/[Name].schema.json`
|
||||
- Include name and propsSchema
|
||||
- Use `?` suffix for optional props
|
||||
- Include `(default: 'value')` for defaults
|
||||
|
||||
5. **Update index.json**
|
||||
- Add entry with category, intent, bestFor, avoidWhen
|
||||
- Include requires array and import path
|
||||
|
||||
6. **Update intents.json**
|
||||
- Add component to relevant intent arrays
|
||||
|
||||
7. **Verify consistency**
|
||||
- Props in schema match component interface exactly
|
||||
- Optional props marked with `?`
|
||||
- Default values documented
|
||||
|
||||
## Output
|
||||
|
||||
Report all updated registry files and confirm props match component.
|
||||
61
.claude/skills/code-review/SKILL.md
Normal file
61
.claude/skills/code-review/SKILL.md
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
name: code-review
|
||||
description: Frontend code review checklist for React, TypeScript, and Tailwind
|
||||
---
|
||||
|
||||
# Frontend Code Review
|
||||
|
||||
Review recently changed files against this checklist.
|
||||
|
||||
## Process
|
||||
|
||||
1. **Identify Changed Files**
|
||||
- Run `git diff --name-only` to find modified files
|
||||
- Focus on `.tsx`, `.ts` files in `src/`
|
||||
|
||||
2. **Review Each File**
|
||||
|
||||
### TypeScript
|
||||
|
||||
- [ ] No `any` types (use proper types or `unknown`)
|
||||
- [ ] Interfaces for component props
|
||||
- [ ] No unused imports or variables
|
||||
- [ ] Proper error handling (no silent catches)
|
||||
|
||||
### React Patterns
|
||||
|
||||
- [ ] `"use client"` only when needed (hooks, events, browser APIs)
|
||||
- [ ] No unnecessary `React.memo`
|
||||
- [ ] Stable callbacks with `useCallback` when passed as props
|
||||
- [ ] Cleanup in `useEffect` (event listeners, subscriptions, GSAP)
|
||||
- [ ] Keys on mapped elements (not index unless static list)
|
||||
|
||||
### Component Structure
|
||||
|
||||
- [ ] Logic extracted to hooks (if complex)
|
||||
- [ ] Props interface defined
|
||||
- [ ] Default export at bottom
|
||||
|
||||
### Tailwind/Styling
|
||||
|
||||
- [ ] Using `cls()` for conditional classes
|
||||
- [ ] Responsive classes (mobile-first)
|
||||
- [ ] No hardcoded colors (use CSS variables)
|
||||
- [ ] Proper z-index layering
|
||||
|
||||
### Performance
|
||||
|
||||
- [ ] Images use `next/image` with proper sizing
|
||||
- [ ] Heavy components use dynamic import if below fold
|
||||
- [ ] No unnecessary re-renders (check deps arrays)
|
||||
|
||||
### Accessibility
|
||||
|
||||
- [ ] Interactive elements are focusable
|
||||
- [ ] Images have alt text
|
||||
- [ ] Buttons have accessible names
|
||||
- [ ] `aria-hidden` on decorative elements
|
||||
|
||||
3. **Report Findings**
|
||||
- List issues grouped by severity: Critical, Warning, Suggestion
|
||||
- Provide specific line numbers and fixes
|
||||
47
.claude/skills/debug/SKILL.md
Normal file
47
.claude/skills/debug/SKILL.md
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
name: debug
|
||||
description: Systematic debugging workflow to find and fix issues
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
# Debug
|
||||
|
||||
Debug issue: $ARGUMENTS
|
||||
|
||||
## Process
|
||||
|
||||
1. **Understand the problem**
|
||||
- What is the expected behavior?
|
||||
- What is the actual behavior?
|
||||
- When did it start happening?
|
||||
- Is it reproducible?
|
||||
|
||||
2. **Gather information**
|
||||
- Check browser console for errors
|
||||
- Check terminal for server errors
|
||||
- Look at network requests
|
||||
- Check component props/state
|
||||
|
||||
3. **Isolate the cause**
|
||||
- Find the smallest reproduction
|
||||
- Identify which component/function is involved
|
||||
- Check recent changes to that area
|
||||
- Add console.logs or debugger statements
|
||||
|
||||
4. **Form hypothesis**
|
||||
- Based on evidence, what could cause this?
|
||||
- List possible causes in order of likelihood
|
||||
|
||||
5. **Test and fix**
|
||||
- Test most likely cause first
|
||||
- Make minimal change to fix
|
||||
- Verify fix doesn't break other things
|
||||
|
||||
6. **Verify**
|
||||
- Confirm original issue is resolved
|
||||
- Test related functionality
|
||||
- Remove debug statements
|
||||
|
||||
## Output
|
||||
|
||||
Report findings, root cause, and the fix applied.
|
||||
57
.claude/skills/performance/SKILL.md
Normal file
57
.claude/skills/performance/SKILL.md
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
name: performance
|
||||
description: Performance optimization workflow for frontend applications
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
# Performance
|
||||
|
||||
Optimize: $ARGUMENTS
|
||||
|
||||
## Process
|
||||
|
||||
1. **Identify the problem**
|
||||
- What is slow? (initial load, interaction, render)
|
||||
- Measure current performance
|
||||
- Set a target improvement
|
||||
|
||||
2. **Analyze causes**
|
||||
- Large bundle size?
|
||||
- Unnecessary re-renders?
|
||||
- Expensive calculations?
|
||||
- Network waterfalls?
|
||||
- Layout thrashing?
|
||||
|
||||
3. **React optimizations**
|
||||
- Add `memo()` for expensive list items
|
||||
- Use `useMemo` for costly computations
|
||||
- Use `useCallback` for stable function refs
|
||||
- Split components to isolate re-renders
|
||||
- Lazy load with `dynamic()` or `React.lazy()`
|
||||
|
||||
4. **Bundle optimizations**
|
||||
- Code split large dependencies
|
||||
- Dynamic imports for heavy features
|
||||
- Tree shake unused code
|
||||
- Analyze with bundle analyzer
|
||||
|
||||
5. **Render optimizations**
|
||||
- Virtualize long lists
|
||||
- Debounce/throttle frequent updates
|
||||
- Use CSS transforms over layout properties
|
||||
- Avoid layout shifts
|
||||
|
||||
6. **Network optimizations**
|
||||
- Preload critical resources
|
||||
- Cache API responses
|
||||
- Optimize images (WebP, lazy load)
|
||||
- Reduce request waterfalls
|
||||
|
||||
7. **Verify improvement**
|
||||
- Measure after changes
|
||||
- Compare to baseline
|
||||
- Test on slow devices/networks
|
||||
|
||||
## Output
|
||||
|
||||
Report optimizations applied and measured improvements.
|
||||
55
.claude/skills/refactor/SKILL.md
Normal file
55
.claude/skills/refactor/SKILL.md
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
name: refactor
|
||||
description: Systematic refactoring workflow for safe code improvements
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
# Refactor
|
||||
|
||||
Refactor: $ARGUMENTS
|
||||
|
||||
## Process
|
||||
|
||||
1. **Understand current state**
|
||||
- Read the code to refactor
|
||||
- Identify what it does and why
|
||||
- Note all usages/dependencies
|
||||
- Check for existing tests
|
||||
|
||||
2. **Define the goal**
|
||||
- What problem are we solving?
|
||||
- Readability? Performance? Maintainability?
|
||||
- What should NOT change? (behavior, API, **UI**)
|
||||
|
||||
3. **Plan changes**
|
||||
- Break into small, safe steps
|
||||
- Each step should leave code working
|
||||
- Identify risk points
|
||||
|
||||
4. **Execute incrementally**
|
||||
- One change at a time
|
||||
- Verify after each step
|
||||
- Keep commits atomic
|
||||
|
||||
5. **Common refactors**
|
||||
- Extract function/component
|
||||
- Rename for clarity
|
||||
- Simplify conditionals
|
||||
- Remove duplication
|
||||
- Split large files
|
||||
- Move code to better location
|
||||
|
||||
6. **Verify**
|
||||
- Run existing tests
|
||||
- Test affected functionality
|
||||
- Check for regressions
|
||||
- Ensure behavior unchanged
|
||||
|
||||
7. **UI Preservation (Critical)**
|
||||
- Compare CSS classes line by line before consolidating
|
||||
- Duplicate code may have subtle differences (sizes, colors)
|
||||
- Never assume - verify before merging branches
|
||||
|
||||
## Output
|
||||
|
||||
Report changes made, files affected, and verification steps taken.
|
||||
59
.claude/skills/scaffold-component/SKILL.md
Normal file
59
.claude/skills/scaffold-component/SKILL.md
Normal file
@@ -0,0 +1,59 @@
|
||||
---
|
||||
name: scaffold-component
|
||||
description: Generate a new React component following project conventions
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
# Scaffold Component
|
||||
|
||||
Generate a new component at the specified path with proper structure.
|
||||
|
||||
## Usage
|
||||
|
||||
`/scaffold-component ComponentName path/to/component`
|
||||
|
||||
## Process
|
||||
|
||||
1. **Parse Arguments**
|
||||
- First argument: Component name (PascalCase)
|
||||
- Second argument: Path relative to `src/components/`
|
||||
|
||||
2. **Create Component File**
|
||||
|
||||
```tsx
|
||||
"use client";
|
||||
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
interface $NAMEProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const $NAME = ({ className }: $NAMEProps) => {
|
||||
return <div className={cls("", className)}>{/* TODO: Implement */}</div>;
|
||||
};
|
||||
|
||||
export default $NAME;
|
||||
```
|
||||
|
||||
3. **Determine if Hook is Needed**
|
||||
- Ask user if component needs state/effects
|
||||
- If yes, create hook file at `src/hooks/{domain}/use{Name}.ts`
|
||||
|
||||
4. **Determine if Constants are Needed**
|
||||
- Ask user if component has static text
|
||||
- If yes, create constants file at `src/constants/{domain}/{name}.ts`
|
||||
|
||||
## File Naming
|
||||
|
||||
- Component: `ComponentName.tsx` (PascalCase)
|
||||
- Hook: `useComponentName.ts` (camelCase with use prefix)
|
||||
- Constants: `componentName.ts` (camelCase)
|
||||
|
||||
## Output
|
||||
|
||||
Report created files and remind user to:
|
||||
|
||||
1. Add necessary imports
|
||||
2. Implement the component logic
|
||||
3. Add to parent component/page
|
||||
Reference in New Issue
Block a user