546 lines
15 KiB
Markdown
546 lines
15 KiB
Markdown
# 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
|
|
|
|
**`"invertCard"`** - Card-style inverted background
|
|
- Section gets `bg-foreground` background
|
|
- Section is constrained to `w-content-width-expanded` width
|
|
- Centered with `mx-auto`
|
|
- Rounded corners with `rounded-theme-capped`
|
|
- Text uses `text-background` color for contrast
|
|
|
|
### Implementation Pattern
|
|
|
|
```tsx
|
|
import { cls } from "@/lib/utils";
|
|
import { useTheme } from "@/providers/themeProvider/ThemeProvider";
|
|
|
|
interface SectionProps {
|
|
title: string;
|
|
description: string;
|
|
useInvertedBackground: "noInvert" | "invertDefault" | "invertCard"; // Required
|
|
// ... other props
|
|
}
|
|
|
|
const Section = ({
|
|
title,
|
|
description,
|
|
useInvertedBackground,
|
|
className = "",
|
|
// ... other props
|
|
}: SectionProps) => {
|
|
const theme = useTheme();
|
|
|
|
return (
|
|
<section
|
|
className={cls(
|
|
"relative py-20",
|
|
useInvertedBackground === "invertCard"
|
|
? "w-content-width-expanded mx-auto rounded-theme-capped bg-foreground"
|
|
: "w-full",
|
|
useInvertedBackground === "invertDefault" && "bg-foreground",
|
|
className
|
|
)}
|
|
>
|
|
<div className="w-content-width mx-auto">
|
|
<h1 className={cls(
|
|
"text-6xl font-medium",
|
|
(useInvertedBackground === "invertDefault" || useInvertedBackground === "invertCard") && "text-background",
|
|
titleClassName
|
|
)}>
|
|
{title}
|
|
</h1>
|
|
<p className={cls(
|
|
"text-lg",
|
|
(useInvertedBackground === "invertDefault" || useInvertedBackground === "invertCard")
|
|
? "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. **Three Modes**: `"noInvert"`, `"invertDefault"`, `"invertCard"`
|
|
3. **Section Width**:
|
|
- `"invertCard"` → `w-content-width-expanded mx-auto`
|
|
- `"noInvert"` or `"invertDefault"` → `w-full`
|
|
4. **Background Color**:
|
|
- `"invertCard"` → `bg-foreground rounded-theme-capped`
|
|
- `"invertDefault"` → `bg-foreground`
|
|
- `"noInvert"` → no background
|
|
5. **Text Colors**: Apply `text-background` or `text-background/75` for `"invertDefault"` and `"invertCard"` modes
|
|
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",
|
|
useInvertedBackground === "invertCard"
|
|
? "w-content-width-expanded mx-auto rounded-theme-capped bg-foreground"
|
|
: "w-full",
|
|
useInvertedBackground === "invertDefault" && "bg-foreground",
|
|
className
|
|
)}
|
|
>
|
|
```
|
|
|
|
### Text Color Pattern
|
|
|
|
**For text elements:**
|
|
|
|
```tsx
|
|
// Single check for both invert modes:
|
|
(useInvertedBackground === "invertDefault" || useInvertedBackground === "invertCard") && "text-background"
|
|
|
|
// Ternary for opacity variants:
|
|
(useInvertedBackground === "invertDefault" || useInvertedBackground === "invertCard")
|
|
? "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",
|
|
useInvertedBackground === "invertCard"
|
|
? "w-content-width-expanded mx-auto rounded-theme-capped bg-foreground"
|
|
: "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"` or `"invertCard"` 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
|
|
|
|
**`w-content-width-expanded`** - Expanded card-style width
|
|
- Used only for `"invertCard"` mode on the `<section>` element
|
|
- Wider than `w-content-width` for visual card effect
|
|
- Combined with `mx-auto` and `rounded-theme-capped`
|
|
|
|
## 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" | "invertCard"`
|
|
- [ ] Add `relative` class to section
|
|
- [ ] Implement three-mode section className pattern (invertCard with expanded width, invertDefault full-width, noInvert standard)
|
|
- [ ] Apply `text-background` to text for `"invertDefault"` and `"invertCard"` modes (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
|