chore: install openagent opencode

Signed-off-by: Dmytro Stanchiev <git@dmytros.dev>
This commit is contained in:
2026-04-07 11:31:26 -04:00
parent b4c03ff25e
commit c2263602c4
204 changed files with 38010 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
<!-- Context: ui/navigation | Priority: critical | Version: 1.0 | Updated: 2026-02-15 -->
# UI Context
**Purpose**: User interface design patterns, standards, and best practices across all platforms
**Last Updated**: 2026-01-07
---
## Overview
This category contains UI/UX patterns, design systems, and interface standards for building user-facing applications across different platforms.
---
## Directory Structure
### 📁 Subcategories
| Subcategory | Description | Path |
|-------------|-------------|------|
| **web/** | Web UI patterns, animations, styling, React components | [web/navigation.md](web/navigation.md) |
| **terminal/** | Terminal UI (TUI) patterns for CLI applications | [terminal/navigation.md](terminal/navigation.md) |
### Future Subcategories
- **mobile/** - React Native, Flutter patterns (planned)
- **desktop/** - Electron, Tauri patterns (planned)
---
## Quick Navigation
### Web UI
- Animation patterns and micro-interactions
- CSS styling standards and design systems
- React component patterns
- Design assets and resources
- Scroll-linked animations (scrollytelling)
### Terminal UI
- CLI/TUI patterns (planned)
- Ink, Blessed component patterns (planned)
- Terminal animations and progress indicators (planned)
---
## Usage
**Web development**: Navigate to `web/` for browser-based UI patterns
**CLI/TUI development**: Navigate to `terminal/` for terminal interface patterns
**Cross-platform**: Consider patterns from multiple subcategories
---
## Scope
This category covers:
- ✅ Visual design patterns
- ✅ Animation and transitions
- ✅ Component architecture
- ✅ Styling standards
- ✅ Design systems
- ✅ Accessibility patterns
- ⏳ Platform-specific patterns (mobile, desktop)
---
## Related Categories
- `development/` - General development patterns (backend, APIs, clean code)
- `product/` - Product design and UX strategy
- `content/` - Content design and copywriting
---
## Used By
**Agents**: frontend-specialist, design-specialist, ui-developer, animation-expert

View File

@@ -0,0 +1,95 @@
<!-- Context: ui/navigation | Priority: critical | Version: 1.0 | Updated: 2026-02-15 -->
# Terminal UI Context
**Purpose**: Terminal UI (TUI) patterns, CLI animations, and command-line interface design
**Last Updated**: 2026-01-07
---
## Overview
This subcategory will contain patterns and best practices for building terminal user interfaces using libraries like Ink, Blessed, and native terminal capabilities.
---
## Planned Content
### Core Files (Future)
| File | Description | Priority |
|------|-------------|----------|
| `tui-patterns.md` | Terminal UI component patterns and layouts | high |
| `cli-animations.md` | Terminal animations, spinners, progress bars | high |
| `ink-components.md` | React Ink component patterns | medium |
| `blessed-patterns.md` | Blessed.js patterns and widgets | medium |
| `terminal-styling.md` | ANSI colors, chalk, terminal theming | medium |
### Planned Topics
- **Layout patterns**: Boxes, borders, flexbox-like layouts
- **Interactive components**: Menus, forms, selects, inputs
- **Progress indicators**: Spinners, progress bars, loading states
- **Terminal animations**: Frame-based animations, smooth transitions
- **Color and styling**: ANSI escape codes, chalk, gradient text
- **Keyboard handling**: Key bindings, shortcuts, navigation
- **Terminal detection**: Capability detection, fallbacks
---
## Example Libraries
### React-based TUI
- **Ink** - React for CLIs
- **Pastel** - React-like TUI framework
### Traditional TUI
- **Blessed** - High-level terminal interface library
- **Blessed-contrib** - Widgets for blessed (charts, gauges)
- **Terminal-kit** - Comprehensive terminal manipulation
### Styling
- **Chalk** - Terminal string styling
- **Gradient-string** - Gradient colors in terminal
- **Boxen** - Create boxes in terminal
### Progress/Animation
- **Ora** - Elegant terminal spinners
- **CLI-progress** - Progress bars
- **Listr** - Terminal task lists
---
## Usage
**When this subcategory is populated**, use it for:
- Building CLI tools with rich interfaces
- Creating terminal-based dashboards
- Implementing interactive command-line applications
- Adding animations and progress indicators to CLI tools
---
## Related Categories
- `ui/web/` - Web UI patterns
- `development/` - General development patterns
---
## Status
**Placeholder** - This subcategory is planned but not yet populated.
To contribute content here, follow the MVI principles:
1. Extract core concepts (1-3 sentences)
2. List key points (3-5 bullets)
3. Provide minimal example
4. Link to full documentation
---
## Used By
**Agents**: cli-developer, terminal-specialist, devops-specialist (future)

View File

@@ -0,0 +1,200 @@
<!-- Context: ui/web/animation-advanced | Priority: medium | Version: 1.0 | Updated: 2025-12-09 -->
# Advanced Animation Patterns
Recipes, best practices, micro-interactions, and accessibility considerations.
---
## Page Transitions
### Route Changes
```css
/* Page fade out */
.page-exit {
animation: fadeOut 200ms ease-in;
}
@keyframes fadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
/* Page fade in */
.page-enter {
animation: fadeIn 300ms ease-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
```
**Micro-syntax**:
```
pageExit: 200ms ease-in [α1→0]
pageEnter: 300ms ease-out [α0→1]
```
---
## Micro-Interactions
### Hover Effects
```css
/* Link underline slide */
.link {
position: relative;
}
.link::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 2px;
background: currentColor;
transition: width 250ms ease-out;
}
.link:hover::after {
width: 100%;
}
```
**Micro-syntax**:
```
linkHover: 250ms ease-out [width0→100%]
```
### Toggle Switches
```css
/* Toggle slide */
.toggle-switch {
transition: background-color 200ms ease-out;
}
.toggle-switch .thumb {
transition: transform 200ms ease-out;
}
.toggle-switch.on .thumb {
transform: translateX(20px);
}
```
**Micro-syntax**:
```
toggle: 200ms ease-out [X0→20, bg→accent]
```
---
## Animation Recipes
### Chat UI Complete Animation System
```
## Core Message Flow
userMsg: 400ms ease-out [Y+20→0, X+10→0, S0.9→1]
aiMsg: 600ms bounce [Y+15→0, S0.95→1] +200ms
typing: 1400ms ∞ [Y±8, α0.4→1] stagger+200ms
status: 300ms ease-out [α0.6→1, S1→1.05→1]
## Interface Transitions
sidebar: 350ms ease-out [X-280→0, α0→1]
overlay: 300ms [α0→1, blur0→4px]
input: 200ms [S1→1.01, shadow+ring] focus
input: 150ms [S1.01→1, shadow-ring] blur
## Button Interactions
sendBtn: 150ms [S1→0.95→1, R±2°] press
sendBtn: 200ms [S1→1.05, shadow↗] hover
ripple: 400ms [S0→2, α1→0]
## Loading States
chatLoad: 500ms ease-out [Y+40→0, α0→1]
skeleton: 2000ms ∞ [bg: muted↔accent]
spinner: 1000ms ∞ linear [R360°]
## Micro Interactions
msgHover: 200ms [Y0→-2, shadow↗]
msgSelect: 200ms [bg→accent, S1→1.02]
error: 400ms [X±5] shake
success: 600ms bounce [S0→1.2→1, R360°]
## Scroll & Navigation
autoScroll: 400ms smooth
scrollHint: 800ms ∞×3 [Y±5]
```
---
## Best Practices
### Do's ✅
- Keep animations under 400ms for most interactions
- Use `transform` and `opacity` for 60fps performance
- Provide purpose for every animation
- Use ease-out for entrances, ease-in for exits
- Test on low-end devices
- Respect `prefers-reduced-motion`
- Stagger animations for lists (50-100ms delay)
- Use consistent timing across similar interactions
### Don'ts ❌
- Don't animate width/height (use scale instead)
- Don't use animations longer than 800ms
- Don't animate too many elements at once
- Don't use animations without purpose
- Don't ignore accessibility preferences
- Don't use jarring/distracting animations
- Don't animate on every interaction
- Don't use complex easing for simple interactions
---
## Accessibility
### Reduced Motion
```css
/* Respect user preferences */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
```
### Focus Indicators
```css
/* Always animate focus states */
:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
transition: outline-offset 150ms ease-out;
}
```
---
## References
- [Web Animation API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API)
- [CSS Easing Functions](https://easings.net/)
- [Animation Performance](https://web.dev/animations-guide/)
- [Reduced Motion](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion)
---
## Related Files
- [Animation Basics](./animation-basics.md) - Fundamentals
- [Animation Components](./animation-components.md) - Common UI patterns
- [Loading Animations](./animation-loading.md) - Loading states

View File

@@ -0,0 +1,94 @@
<!-- Context: ui/web/animation-basics | Priority: high | Version: 1.0 | Updated: 2025-12-09 -->
# Animation Basics
## Overview
Standards and patterns for UI animations, micro-interactions, and transitions. Animations should feel natural, purposeful, and enhance user experience without causing distraction.
## Quick Reference
**Timing**: 150-400ms for most interactions
**Easing**: ease-out for entrances, ease-in for exits
**Purpose**: Every animation should have a clear purpose
**Performance**: Use transform and opacity for 60fps
---
## Animation Micro-Syntax
### Notation Guide
**Format**: `element: duration easing [properties] modifiers`
**Symbols**:
- `→` = transition from → to
- `±` = oscillate/shake
- `↗` = increase
- `↘` = decrease
- `∞` = infinite loop
- `×N` = repeat N times
- `+Nms` = delay N milliseconds
**Properties**:
- `Y` = translateY
- `X` = translateX
- `S` = scale
- `R` = rotate
- `α` = opacity
- `bg` = background
**Example**: `button: 200ms ease-out [S1→1.05, α0.8→1]`
- Button scales from 1 to 1.05 and fades from 0.8 to 1 over 200ms with ease-out
---
## Core Animation Principles
### Timing Standards
```
Ultra-fast: 100-150ms (micro-feedback, hover states)
Fast: 150-250ms (button clicks, toggles)
Standard: 250-350ms (modals, dropdowns, navigation)
Moderate: 350-500ms (page transitions, complex animations)
Slow: 500-800ms (dramatic reveals, storytelling)
```
### Easing Functions
```css
/* Entrances - start slow, end fast */
ease-out: cubic-bezier(0, 0, 0.2, 1);
/* Exits - start fast, end slow */
ease-in: cubic-bezier(0.4, 0, 1, 1);
/* Both - smooth throughout */
ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
/* Bounce - playful, attention-grabbing */
bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
/* Elastic - spring-like */
elastic: cubic-bezier(0.68, -0.6, 0.32, 1.6);
```
### Performance Guidelines
**60fps Animations** (GPU-accelerated):
-`transform` (translate, scale, rotate)
-`opacity`
-`filter` (with caution)
**Avoid** (causes reflow/repaint):
-`width`, `height`
-`top`, `left`, `right`, `bottom`
-`margin`, `padding`
---
## Related Files
- [Animation Components](./animation-components.md) - Common UI patterns
- [Loading Animations](./animation-loading.md) - Loading states
- [Advanced Animations](./animation-advanced.md) - Recipes & best practices

View File

@@ -0,0 +1,113 @@
<!-- Context: ui/web/animation-chat | Priority: medium | Version: 1.0 | Updated: 2025-12-09 -->
# Chat UI Animation Patterns
Animation patterns for message entrances, typing indicators, and chat interactions.
---
## Message Entrance
```css
/* User message - slide from right */
.message-user {
animation: slideInRight 400ms ease-out;
}
@keyframes slideInRight {
from {
transform: translateX(10px) translateY(20px);
opacity: 0;
scale: 0.9;
}
to {
transform: translateX(0) translateY(0);
opacity: 1;
scale: 1;
}
}
/* AI message - slide from left with bounce */
.message-ai {
animation: slideInLeft 600ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
animation-delay: 200ms;
}
@keyframes slideInLeft {
from {
transform: translateY(15px);
opacity: 0;
scale: 0.95;
}
to {
transform: translateY(0);
opacity: 1;
scale: 1;
}
}
```
**Micro-syntax**:
```
userMsg: 400ms ease-out [Y+20→0, X+10→0, S0.9→1]
aiMsg: 600ms bounce [Y+15→0, S0.95→1] +200ms
```
---
## Typing Indicator
```css
.typing-indicator span {
animation: typingDot 1400ms infinite;
}
.typing-indicator span:nth-child(2) { animation-delay: 200ms; }
.typing-indicator span:nth-child(3) { animation-delay: 400ms; }
@keyframes typingDot {
0%, 60%, 100% {
transform: translateY(0);
opacity: 0.4;
}
30% {
transform: translateY(-8px);
opacity: 1;
}
}
```
**Micro-syntax**:
```
typing: 1400ms ∞ [Y±8, α0.4→1] stagger+200ms
```
---
## Chat Message Micro-Interactions
```css
/* Message hover */
.message:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
transition: all 200ms ease-out;
}
/* Message selection */
.message.selected {
background-color: var(--accent);
transform: scale(1.02);
transition: all 200ms ease-out;
}
```
**Micro-syntax**:
```
msgHover: 200ms [Y0→-2, shadow↗]
msgSelect: 200ms [bg→accent, S1→1.02]
```
---
## Related Files
- [Animation Basics](./animation-basics.md) - Fundamentals
- [Component Animations](./animation-components.md) - UI components
- [Loading Animations](./animation-loading.md) - Loading states

View File

@@ -0,0 +1,137 @@
<!-- Context: ui/web/animation-components | Priority: high | Version: 1.0 | Updated: 2025-12-09 -->
# Component Animation Patterns
Animation patterns for buttons, cards, modals, dropdowns, and sidebars.
---
## Button Interactions
```css
.button {
transition: transform 200ms ease-out, box-shadow 200ms ease-out;
}
.button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.button:active {
transform: scale(0.95);
transition: transform 100ms ease-in;
}
@keyframes ripple {
from { transform: scale(0); opacity: 1; }
to { transform: scale(2); opacity: 0; }
}
.button::after { animation: ripple 400ms ease-out; }
```
**Micro-syntax**:
```
buttonHover: 200ms ease-out [Y0→-2, shadow↗]
buttonPress: 100ms ease-in [S1→0.95]
ripple: 400ms ease-out [S0→2, α1→0]
```
---
## Card Interactions
```css
.card {
transition: transform 300ms ease-out, box-shadow 300ms ease-out;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}
.card.selected {
transform: scale(1.02);
background-color: var(--accent);
transition: all 200ms ease-out;
}
```
**Micro-syntax**:
```
cardHover: 300ms ease-out [Y0→-4, shadow↗]
cardSelect: 200ms ease-out [S1→1.02, bg→accent]
```
---
## Modal/Dialog Animations
```css
.modal-backdrop { animation: fadeIn 300ms ease-out; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.modal { animation: slideUp 350ms ease-out; }
@keyframes slideUp {
from { transform: translateY(40px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.modal.closing { animation: slideDown 250ms ease-in; }
@keyframes slideDown {
from { transform: translateY(0); opacity: 1; }
to { transform: translateY(40px); opacity: 0; }
}
```
**Micro-syntax**:
```
backdrop: 300ms ease-out [α0→1]
modalEnter: 350ms ease-out [Y+40→0, α0→1]
modalExit: 250ms ease-in [Y0→+40, α1→0]
```
---
## Dropdown/Menu Animations
```css
.dropdown {
animation: dropdownOpen 200ms ease-out;
transform-origin: top;
}
@keyframes dropdownOpen {
from { transform: scaleY(0.95); opacity: 0; }
to { transform: scaleY(1); opacity: 1; }
}
```
**Micro-syntax**: `dropdown: 200ms ease-out [scaleY0.95→1, α0→1]`
---
## Sidebar/Drawer Animations
```css
.sidebar { animation: slideInLeft 350ms ease-out; }
@keyframes slideInLeft {
from { transform: translateX(-280px); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
.overlay { animation: overlayFade 300ms ease-out; }
@keyframes overlayFade {
from { opacity: 0; backdrop-filter: blur(0); }
to { opacity: 1; backdrop-filter: blur(4px); }
}
```
**Micro-syntax**:
```
sidebar: 350ms ease-out [X-280→0, α0→1]
overlay: 300ms ease-out [α0→1, blur0→4px]
```
---
## Related Files
- [Animation Basics](./animation-basics.md) - Fundamentals
- [Chat Animations](./animation-chat.md) - Message patterns
- [Loading Animations](./animation-loading.md) - Loading states

View File

@@ -0,0 +1,121 @@
<!-- Context: ui/web/animation-forms | Priority: medium | Version: 1.0 | Updated: 2025-12-09 -->
# Form Animation Patterns
Animation patterns for form inputs, validation states, and scroll animations.
---
## Focus States
```css
/* Input focus - ring and scale */
.input {
transition: all 200ms ease-out;
}
.input:focus {
transform: scale(1.01);
box-shadow: 0 0 0 3px var(--ring);
}
/* Input blur - return to normal */
.input:not(:focus) {
transition: all 150ms ease-in;
}
```
**Micro-syntax**:
```
inputFocus: 200ms ease-out [S1→1.01, shadow+ring]
inputBlur: 150ms ease-in [S1.01→1, shadow-ring]
```
---
## Validation States
```css
/* Error shake */
.input-error {
animation: shake 400ms ease-in-out;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
/* Success checkmark */
.input-success::after {
animation: checkmark 600ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
@keyframes checkmark {
from {
transform: scale(0) rotate(0deg);
opacity: 0;
}
to {
transform: scale(1.2) rotate(360deg);
opacity: 1;
}
}
```
**Micro-syntax**:
```
error: 400ms ease-in-out [X±5] shake
success: 600ms bounce [S0→1.2, R0→360°, α0→1]
```
---
## Scroll Animations
### Scroll-Triggered Fade In
```css
.fade-in-on-scroll {
opacity: 0;
transform: translateY(40px);
transition: opacity 500ms ease-out, transform 500ms ease-out;
}
.fade-in-on-scroll.visible {
opacity: 1;
transform: translateY(0);
}
```
**Micro-syntax**:
```
scrollFadeIn: 500ms ease-out [Y+40→0, α0→1]
```
### Auto-Scroll
```css
html {
scroll-behavior: smooth;
}
.scroll-hint {
animation: scrollHint 800ms infinite;
animation-iteration-count: 3;
}
@keyframes scrollHint {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(5px); }
}
```
**Micro-syntax**:
```
autoScroll: 400ms smooth
scrollHint: 800ms ∞×3 [Y±5]
```
---
## Related Files
- [Animation Basics](./animation-basics.md) - Fundamentals
- [Animation Components](./animation-components.md) - Common UI patterns
- [Loading Animations](./animation-loading.md) - Loading states

View File

@@ -0,0 +1,118 @@
<!-- Context: ui/web/animation-loading | Priority: medium | Version: 1.0 | Updated: 2025-12-09 -->
# Loading State Animations
Animation patterns for skeleton screens, spinners, progress bars, and status indicators.
---
## Skeleton Screens
```css
/* Skeleton shimmer */
.skeleton {
animation: shimmer 2000ms infinite;
background: linear-gradient(
90deg,
var(--muted) 0%,
var(--accent) 50%,
var(--muted) 100%
);
background-size: 200% 100%;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
```
**Micro-syntax**:
```
skeleton: 2000ms ∞ [bg: muted↔accent]
```
---
## Spinners
```css
/* Circular spinner */
.spinner {
animation: spin 1000ms linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* Pulsing dots */
.loading-dots span {
animation: dotPulse 1500ms infinite;
}
.loading-dots span:nth-child(2) { animation-delay: 200ms; }
.loading-dots span:nth-child(3) { animation-delay: 400ms; }
@keyframes dotPulse {
0%, 80%, 100% { opacity: 0.3; scale: 0.8; }
40% { opacity: 1; scale: 1; }
}
```
**Micro-syntax**:
```
spinner: 1000ms ∞ linear [R360°]
dotPulse: 1500ms ∞ [α0.3→1→0.3, S0.8→1→0.8] stagger+200ms
```
---
## Progress Bars
```css
/* Indeterminate progress */
.progress-bar {
animation: progress 2000ms ease-in-out infinite;
}
@keyframes progress {
0% { transform: translateX(-100%); }
50% { transform: translateX(0); }
100% { transform: translateX(100%); }
}
```
**Micro-syntax**:
```
progress: 2000ms ∞ ease-in-out [X-100%→0→100%]
```
---
## Status Indicators
```css
/* Online status pulse */
.status-online {
animation: pulse 2000ms infinite;
}
@keyframes pulse {
0%, 100% {
opacity: 1;
scale: 1;
}
50% {
opacity: 0.6;
scale: 1.05;
}
}
```
**Micro-syntax**:
```
status: 2000ms ∞ [α1→0.6→1, S1→1.05→1]
```
---
## Related Files
- [Animation Basics](./animation-basics.md) - Fundamentals
- [Form Animations](./animation-forms.md) - Form patterns
- [Advanced Animations](./animation-advanced.md) - Recipes & best practices

View File

@@ -0,0 +1,381 @@
<!-- Context: development/design-systems | Priority: high | Version: 1.0 | Updated: 2025-12-09 -->
# Design Systems
## Overview
This context file provides reusable design system patterns, theme templates, and color systems for frontend design work. Use these as starting points for creating cohesive, professional UI designs.
## Quick Reference
**Color Format**: OKLCH (perceptually uniform color space)
**Theme Variables**: CSS custom properties (--variable-name)
**Font Sources**: Google Fonts
**Responsive**: All designs must be mobile-first responsive
---
## Theme Patterns
### Neo-Brutalism Style
**Characteristics**: 90s web design aesthetic, bold borders, flat shadows, high contrast
**Use Cases**:
- Retro/vintage applications
- Bold, statement-making interfaces
- Art/creative portfolios
- Playful consumer apps
**Theme Template**:
```css
:root {
/* Colors - High contrast, bold */
--background: oklch(1.0000 0 0);
--foreground: oklch(0 0 0);
--card: oklch(1.0000 0 0);
--card-foreground: oklch(0 0 0);
--popover: oklch(1.0000 0 0);
--popover-foreground: oklch(0 0 0);
--primary: oklch(0.6489 0.2370 26.9728);
--primary-foreground: oklch(1.0000 0 0);
--secondary: oklch(0.9680 0.2110 109.7692);
--secondary-foreground: oklch(0 0 0);
--muted: oklch(0.9551 0 0);
--muted-foreground: oklch(0.3211 0 0);
--accent: oklch(0.5635 0.2408 260.8178);
--accent-foreground: oklch(1.0000 0 0);
--destructive: oklch(0 0 0);
--destructive-foreground: oklch(1.0000 0 0);
--border: oklch(0 0 0);
--input: oklch(0 0 0);
--ring: oklch(0.6489 0.2370 26.9728);
/* Chart colors */
--chart-1: oklch(0.6489 0.2370 26.9728);
--chart-2: oklch(0.9680 0.2110 109.7692);
--chart-3: oklch(0.5635 0.2408 260.8178);
--chart-4: oklch(0.7323 0.2492 142.4953);
--chart-5: oklch(0.5931 0.2726 328.3634);
/* Sidebar */
--sidebar: oklch(0.9551 0 0);
--sidebar-foreground: oklch(0 0 0);
--sidebar-primary: oklch(0.6489 0.2370 26.9728);
--sidebar-primary-foreground: oklch(1.0000 0 0);
--sidebar-accent: oklch(0.5635 0.2408 260.8178);
--sidebar-accent-foreground: oklch(1.0000 0 0);
--sidebar-border: oklch(0 0 0);
--sidebar-ring: oklch(0.6489 0.2370 26.9728);
/* Typography */
--font-sans: DM Sans, sans-serif;
--font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
--font-mono: Space Mono, monospace;
/* Border radius - Sharp corners */
--radius: 0px;
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
/* Shadows - Bold, offset shadows */
--shadow-2xs: 4px 4px 0px 0px hsl(0 0% 0% / 0.50);
--shadow-xs: 4px 4px 0px 0px hsl(0 0% 0% / 0.50);
--shadow-sm: 4px 4px 0px 0px hsl(0 0% 0% / 1.00), 4px 1px 2px -1px hsl(0 0% 0% / 1.00);
--shadow: 4px 4px 0px 0px hsl(0 0% 0% / 1.00), 4px 1px 2px -1px hsl(0 0% 0% / 1.00);
--shadow-md: 4px 4px 0px 0px hsl(0 0% 0% / 1.00), 4px 2px 4px -1px hsl(0 0% 0% / 1.00);
--shadow-lg: 4px 4px 0px 0px hsl(0 0% 0% / 1.00), 4px 4px 6px -1px hsl(0 0% 0% / 1.00);
--shadow-xl: 4px 4px 0px 0px hsl(0 0% 0% / 1.00), 4px 8px 10px -1px hsl(0 0% 0% / 1.00);
--shadow-2xl: 4px 4px 0px 0px hsl(0 0% 0% / 2.50);
/* Spacing */
--tracking-normal: 0em;
--spacing: 0.25rem;
}
```
---
### Modern Dark Mode Style
**Characteristics**: Clean, minimal, professional (Vercel/Linear aesthetic)
**Use Cases**:
- SaaS applications
- Developer tools
- Professional dashboards
- Enterprise applications
- Modern web apps
**Theme Template**:
```css
:root {
/* Colors - Subtle, professional */
--background: oklch(1 0 0);
--foreground: oklch(0.1450 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.1450 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.1450 0 0);
--primary: oklch(0.2050 0 0);
--primary-foreground: oklch(0.9850 0 0);
--secondary: oklch(0.9700 0 0);
--secondary-foreground: oklch(0.2050 0 0);
--muted: oklch(0.9700 0 0);
--muted-foreground: oklch(0.5560 0 0);
--accent: oklch(0.9700 0 0);
--accent-foreground: oklch(0.2050 0 0);
--destructive: oklch(0.5770 0.2450 27.3250);
--destructive-foreground: oklch(1 0 0);
--border: oklch(0.9220 0 0);
--input: oklch(0.9220 0 0);
--ring: oklch(0.7080 0 0);
/* Chart colors - Monochromatic blues */
--chart-1: oklch(0.8100 0.1000 252);
--chart-2: oklch(0.6200 0.1900 260);
--chart-3: oklch(0.5500 0.2200 263);
--chart-4: oklch(0.4900 0.2200 264);
--chart-5: oklch(0.4200 0.1800 266);
/* Sidebar */
--sidebar: oklch(0.9850 0 0);
--sidebar-foreground: oklch(0.1450 0 0);
--sidebar-primary: oklch(0.2050 0 0);
--sidebar-primary-foreground: oklch(0.9850 0 0);
--sidebar-accent: oklch(0.9700 0 0);
--sidebar-accent-foreground: oklch(0.2050 0 0);
--sidebar-border: oklch(0.9220 0 0);
--sidebar-ring: oklch(0.7080 0 0);
/* Typography - System fonts */
--font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
/* Border radius - Rounded */
--radius: 0.625rem;
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
/* Shadows - Subtle, soft */
--shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);
--shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);
--shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 2px 4px -1px hsl(0 0% 0% / 0.10);
--shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 4px 6px -1px hsl(0 0% 0% / 0.10);
--shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 8px 10px -1px hsl(0 0% 0% / 0.10);
--shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);
/* Spacing */
--tracking-normal: 0em;
--spacing: 0.25rem;
}
```
---
## Typography System
### Recommended Font Families
**Monospace Fonts** (Code, technical interfaces):
- JetBrains Mono
- Fira Code
- Source Code Pro
- IBM Plex Mono
- Roboto Mono
- Space Mono
- Geist Mono
**Sans-Serif Fonts** (UI, body text):
- Inter
- Roboto
- Open Sans
- Poppins
- Montserrat
- Outfit
- Plus Jakarta Sans
- DM Sans
- Geist
- Space Grotesk
**Display/Decorative Fonts**:
- Oxanium
- Architects Daughter
**Serif Fonts** (Editorial, formal):
- Merriweather
- Playfair Display
- Lora
- Source Serif Pro
- Libre Baskerville
### Font Loading
Always use Google Fonts for consistency and reliability:
```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
```
---
## Color System Guidelines
### OKLCH Color Space
Use OKLCH for perceptually uniform colors:
- **L** (Lightness): 0-1 (0 = black, 1 = white)
- **C** (Chroma): 0-0.4 (saturation)
- **H** (Hue): 0-360 (color angle)
**Format**: `oklch(L C H)`
**Example**: `oklch(0.6489 0.2370 26.9728)` = vibrant orange
### Color Palette Rules
1. **Avoid Bootstrap Blue**: Unless explicitly requested, avoid generic blue (#007bff)
2. **Semantic Colors**: Use meaningful color names (--primary, --destructive, --success)
3. **Contrast**: Ensure WCAG AA compliance (4.5:1 for text)
4. **Consistency**: Use theme variables, not hardcoded colors
### Background/Foreground Pairing
**Rule**: Background should contrast with content
- Light component → Dark background
- Dark component → Light background
- Ensures visibility and visual hierarchy
---
## Shadow System
### Shadow Scales
Shadows create depth and hierarchy:
- `--shadow-2xs`: Minimal elevation (1-2px)
- `--shadow-xs`: Subtle lift (2-3px)
- `--shadow-sm`: Small cards (3-4px)
- `--shadow`: Default elevation (4-6px)
- `--shadow-md`: Medium cards (6-8px)
- `--shadow-lg`: Modals, dropdowns (8-12px)
- `--shadow-xl`: Floating panels (12-16px)
- `--shadow-2xl`: Maximum elevation (16-24px)
### Shadow Styles
**Soft Shadows** (Modern):
```css
box-shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.10);
```
**Hard Shadows** (Neo-brutalism):
```css
box-shadow: 4px 4px 0px 0px hsl(0 0% 0% / 1.00);
```
---
## Spacing System
### Base Unit
Use `--spacing: 0.25rem` (4px) as base unit
### Scale
- 1x = 0.25rem (4px)
- 2x = 0.5rem (8px)
- 3x = 0.75rem (12px)
- 4x = 1rem (16px)
- 6x = 1.5rem (24px)
- 8x = 2rem (32px)
- 12x = 3rem (48px)
- 16x = 4rem (64px)
---
## Border Radius System
### Radius Scales
```css
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
```
### Common Values
- **Sharp** (Neo-brutalism): `--radius: 0px`
- **Subtle** (Modern): `--radius: 0.375rem` (6px)
- **Rounded** (Friendly): `--radius: 0.625rem` (10px)
- **Pill** (Buttons): `--radius: 9999px`
---
## Usage Guidelines
### When to Use Each Theme
**Neo-Brutalism**:
- ✅ Creative/artistic projects
- ✅ Retro/vintage aesthetics
- ✅ Bold, statement-making designs
- ❌ Enterprise/corporate applications
- ❌ Accessibility-critical interfaces
**Modern Dark Mode**:
- ✅ SaaS applications
- ✅ Developer tools
- ✅ Professional dashboards
- ✅ Enterprise applications
- ✅ Accessibility-critical interfaces
### Customization
1. Start with a base theme template
2. Adjust primary/accent colors for brand
3. Modify radius for desired feel
4. Adjust shadows for depth preference
5. Test contrast ratios for accessibility
---
## Best Practices
**Use CSS custom properties** for all theme values
**Test in light and dark modes** if applicable
**Validate color contrast** (WCAG AA minimum)
**Use semantic color names** (--primary, not --blue)
**Load fonts from Google Fonts** for reliability
**Apply consistent spacing** using the spacing scale
**Test responsive behavior** at all breakpoints
**Don't hardcode colors** in components
**Don't use generic blue** (#007bff) without reason
**Don't mix color formats** (stick to OKLCH)
**Don't skip contrast testing**
**Don't use too many font families** (2-3 max)
---
## References
- [OKLCH Color Picker](https://oklch.com/)
- [Google Fonts](https://fonts.google.com/)
- [WCAG Contrast Checker](https://webaim.org/resources/contrastchecker/)
- [Tailwind CSS Colors](https://tailwindcss.com/docs/customizing-colors)

View File

@@ -0,0 +1,54 @@
<!-- Context: ui/scroll-linked-animations | Priority: critical | Version: 1.0 | Updated: 2026-02-15 -->
# Concept: Scroll-Linked Animations
**Purpose**: Sync image sequences to scroll position for cinematic product reveals
**Last Updated**: 2026-01-07
---
## Core Idea
Map scroll position to video frames. As user scrolls, play through image sequence like a scrubbing timeline. Creates illusion of 3D animation controlled by scroll.
**Formula**: `scrollProgress (0→1) → frameIndex (0→N) → canvas.drawImage()`
---
## Essential Parts
1. **Image sequence** - 60-150 WebP frames from video/3D render
2. **Sticky canvas** - Fixed HTML5 canvas, always visible while scrolling
3. **Scroll tracker** - Framer Motion `useScroll` hook
4. **Preloader** - Load all frames upfront (prevents flicker)
5. **Background match** - Page BG = image BG (hides edges)
---
## Minimal Example
```tsx
const { scrollYProgress } = useScroll({ target: containerRef })
const frameIndex = useTransform(scrollYProgress, [0, 1], [0, 119])
useEffect(() => {
ctx.drawImage(images[Math.round(frameIndex)], 0, 0)
}, [frameIndex])
```
**Why canvas?** 10x faster than swapping `<img src>`. DOM updates are slow.
---
## Related
- examples/scrollytelling-headphone.md - Full code
- guides/building-scrollytelling-pages.md - Implementation
- lookup/scroll-animation-prompts.md - Generate sequences
---
## Reference
[Apple AirPods Pro](https://www.apple.com/airpods-pro/) - Production example

View File

@@ -0,0 +1,265 @@
<!-- Context: ui/scrollytelling-headphone | Priority: high | Version: 1.0 | Updated: 2026-02-15 -->
---
description: "Full Next.js implementation of scroll-linked image sequence animation"
---
# Example: Scrollytelling Headphone Animation
**Purpose**: Full Next.js implementation of scroll-linked image sequence animation
**Last Updated**: 2026-01-07
---
## Overview
Complete working example of "Zenith X" headphone scrollytelling page using Next.js 14, Framer Motion, and Canvas.
**Tech Stack**: Next.js 14 (App Router) + Framer Motion + Canvas + Tailwind CSS
---
## File Structure
```
app/
├── page.tsx
├── components/
│ └── HeadphoneScroll.tsx
└── globals.css
public/
└── frames/
└── frame_0001.webp through frame_0120.webp
```
---
## 1. globals.css
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
body {
@apply bg-[#050505] text-white antialiased;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}
}
```
---
## 2. app/page.tsx
```tsx
import HeadphoneScroll from './components/HeadphoneScroll'
export default function Home() {
return (
<main className="bg-[#050505]">
<HeadphoneScroll />
</main>
)
}
```
---
## 3. components/HeadphoneScroll.tsx
```tsx
'use client'
import { useEffect, useRef, useState } from 'react'
import { motion, useScroll, useTransform } from 'framer-motion'
const FRAME_COUNT = 120
export default function HeadphoneScroll() {
const containerRef = useRef<HTMLDivElement>(null)
const canvasRef = useRef<HTMLCanvasElement>(null)
const [images, setImages] = useState<HTMLImageElement[]>([])
const [loading, setLoading] = useState(true)
// Track scroll progress (0 to 1)
const { scrollYProgress } = useScroll({
target: containerRef,
offset: ['start start', 'end end']
})
// Map scroll progress to frame index
const frameIndex = useTransform(scrollYProgress, [0, 1], [0, FRAME_COUNT - 1])
const [currentFrame, setCurrentFrame] = useState(0)
// Update current frame
useEffect(() => {
return frameIndex.on('change', (latest) => {
setCurrentFrame(Math.round(latest))
})
}, [frameIndex])
// Preload all images
useEffect(() => {
const loadImages = async () => {
const promises = Array.from({ length: FRAME_COUNT }, (_, i) => {
return new Promise<HTMLImageElement>((resolve) => {
const img = new Image()
const frameNum = String(i + 1).padStart(4, '0')
img.src = `/frames/frame_${frameNum}.webp`
img.onload = () => resolve(img)
})
})
const loaded = await Promise.all(promises)
setImages(loaded)
setLoading(false)
}
loadImages()
}, [])
// Render current frame to canvas
useEffect(() => {
if (!canvasRef.current || !images.length) return
const canvas = canvasRef.current
const ctx = canvas.getContext('2d')
if (!ctx) return
const img = images[currentFrame]
// Set canvas size
canvas.width = window.innerWidth
canvas.height = window.innerHeight
// Clear and draw centered
ctx.clearRect(0, 0, canvas.width, canvas.height)
const scale = Math.min(
canvas.width / img.width,
canvas.height / img.height
)
const x = (canvas.width - img.width * scale) / 2
const y = (canvas.height - img.height * scale) / 2
ctx.drawImage(img, x, y, img.width * scale, img.height * scale)
}, [currentFrame, images])
// Text overlay opacity transforms
const title = useTransform(scrollYProgress, [0, 0.1, 0.2], [1, 1, 0])
const text1 = useTransform(scrollYProgress, [0.25, 0.3, 0.4], [0, 1, 0])
const text2 = useTransform(scrollYProgress, [0.55, 0.6, 0.7], [0, 1, 0])
const cta = useTransform(scrollYProgress, [0.85, 0.9, 1], [0, 1, 1])
if (loading) {
return (
<div className="fixed inset-0 flex items-center justify-center bg-[#050505]">
<div className="h-12 w-12 animate-spin rounded-full border-4 border-white/20 border-t-white" />
</div>
)
}
return (
<div ref={containerRef} className="relative h-[400vh]">
{/* Sticky Canvas */}
<canvas
ref={canvasRef}
className="sticky top-0 h-screen w-full"
style={{ willChange: 'transform' }}
/>
{/* Text Overlays */}
<motion.div
style={{ opacity: title }}
className="pointer-events-none fixed inset-0 flex items-center justify-center"
>
<div className="text-center">
<h1 className="text-7xl font-bold tracking-tight text-white/90">
Zenith X
</h1>
<p className="mt-4 text-xl text-white/60">Pure Sound.</p>
</div>
</motion.div>
<motion.div
style={{ opacity: text1 }}
className="pointer-events-none fixed inset-y-0 left-20 flex items-center"
>
<p className="text-4xl font-bold tracking-tight text-white/90">
Precision Engineering.
</p>
</motion.div>
<motion.div
style={{ opacity: text2 }}
className="pointer-events-none fixed inset-y-0 right-20 flex items-center"
>
<p className="text-4xl font-bold tracking-tight text-white/90">
Titanium Drivers.
</p>
</motion.div>
<motion.div
style={{ opacity: cta }}
className="pointer-events-none fixed inset-0 flex items-center justify-center"
>
<div className="text-center">
<h2 className="text-6xl font-bold tracking-tight text-white/90">
Hear Everything.
</h2>
<button className="pointer-events-auto mt-8 rounded-full bg-white px-8 py-3 text-lg font-semibold text-black transition hover:bg-white/90">
Pre-Order Now
</button>
</div>
</motion.div>
</div>
)
}
```
---
## Key Implementation Details
**Line 15-18**: `useScroll` tracks scroll progress from container start to end
**Line 21**: `useTransform` maps 0-1 scroll to 0-119 frame index
**Line 32-46**: Preload all 120 frames using Promise.all
**Line 49-70**: Draw current frame to canvas, scaled and centered
**Line 73-76**: Text opacity transforms for fade in/out at specific scroll positions
---
## Usage
1. Install dependencies: `bun --bun install framer-motion`
2. Place 120 WebP frames in `/public/frames/`
3. Copy code into respective files
4. Run: `bun --bun run dev`
---
## Customization
**Change frame count**: Update `FRAME_COUNT` constant (line 7)
**Adjust scroll length**: Change `h-[400vh]` to `h-[300vh]` or `h-[500vh]` (line 120)
**Modify text timing**: Update transform ranges in lines 73-76
**Change colors**: Update `bg-[#050505]` to match your image background
---
## Related
- concepts/scroll-linked-animations.md - Understanding the technique
- guides/scrollytelling-setup.md - Getting started
- lookup/scroll-animation-prompts.md - Generating image sequences
---
## References
- [Framer Motion Docs](https://www.framer.com/motion/)
- [Next.js App Router](https://nextjs.org/docs/app)

View File

@@ -0,0 +1,273 @@
<!-- Context: ui/building-scrollytelling-pages | Priority: high | Version: 1.0 | Updated: 2026-02-15 -->
---
description: "Step-by-step implementation of scroll-linked image sequence animations"
---
# Guide: Building Scrollytelling Pages
**Purpose**: Step-by-step implementation of scroll-linked image sequence animations
**Last Updated**: 2026-01-07
---
## Prerequisites
- Next.js 14+ project with App Router
- Framer Motion installed (`bun --bun i framer-motion`)
- Tailwind CSS configured
- Image sequence ready (60-240 WebP frames)
---
## Step 1: Generate Image Sequences
Use nano banana or AI image tools to create start/end frames, then generate interpolation:
**Start frame prompt**:
```
Ultra-premium product photography of [product] on matte black surface,
minimalistic studio shoot, deep black background with subtle gradient,
soft rim lighting, cinematic, high contrast, luxury aesthetic, sharp focus,
no clutter, DSLR 85mm f/1.8, photorealistic
```
**End frame prompt**:
```
Exploded technical diagram of same [product], every component separated
and floating in alignment, against deep black studio background, visible
internal structure, hyper-realistic, studio rim lighting, cinematic,
high contrast, no labels, photorealistic
```
**Generate video**: Use AI video tools (Runway, Pika) to interpolate between frames.
**Export frames**: Use ffmpeg or ezgif to split video into 120+ WebP images.
```bash
ffmpeg -i animation.mp4 -vf fps=30 frame_%04d.webp
```
---
## Step 2: Project Structure
```
app/
├── page.tsx # Main landing page
├── components/
│ └── HeadphoneScroll.tsx # Scroll animation component
└── globals.css # Dark theme, Inter font
public/
└── frames/
├── frame_0001.webp # 120+ frames
├── frame_0002.webp
└── ...
```
---
## Step 3: Setup globals.css
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
body {
@apply bg-[#050505] text-white antialiased;
font-family: 'Inter', -apple-system, sans-serif;
}
}
```
---
## Step 4: Create Scroll Component
**Key patterns**:
- Container with `h-[400vh]` for long scroll
- Canvas with `sticky top-0` stays fixed
- `useScroll` tracks scroll progress (0-1)
- `useTransform` maps progress to frame index
- `useEffect` preloads all images
**Core logic**:
```tsx
const { scrollYProgress } = useScroll({ target: containerRef })
const frameIndex = useTransform(scrollYProgress, [0, 1], [0, 119])
```
---
## Step 5: Implement Preloader
Always preload images before starting animation:
```tsx
useEffect(() => {
const loadImages = async () => {
const promises = Array.from({ length: 120 }, (_, i) => {
return new Promise((resolve) => {
const img = new Image()
img.src = `/frames/frame_${String(i + 1).padStart(4, '0')}.webp`
img.onload = () => resolve(img)
})
})
const loaded = await Promise.all(promises)
setImages(loaded)
setLoading(false)
}
loadImages()
}, [])
```
---
## Step 6: Canvas Rendering
Draw current frame to canvas on every scroll update:
```tsx
useEffect(() => {
if (!canvasRef.current || !images.length) return
const canvas = canvasRef.current
const ctx = canvas.getContext('2d')
const img = images[Math.round(currentFrame)]
// Scale canvas to window
canvas.width = window.innerWidth
canvas.height = window.innerHeight
// Draw centered
ctx.drawImage(img,
(canvas.width - img.width) / 2,
(canvas.height - img.height) / 2
)
}, [currentFrame, images])
```
---
## Step 7: Add Text Overlays
Fade text in/out at specific scroll positions:
```tsx
<motion.div
style={{
opacity: useTransform(scrollYProgress,
[0.25, 0.30, 0.35], // Fade in 25-30%, out 35%
[0, 1, 0]
)
}}
className="absolute left-20 text-4xl font-bold"
>
Precision Engineering.
</motion.div>
```
---
## Step 8: Match Backgrounds
**CRITICAL**: Page background MUST match image background exactly.
1. Open first frame in image editor
2. Use eyedropper tool on background (e.g., `#050505`)
3. Set page background to exact same color in globals.css
4. Test: Image edges should be invisible
---
## Step 9: Optimize Performance
```tsx
// Add GPU hint
<canvas
ref={canvasRef}
className="sticky top-0 h-screen w-full"
style={{ willChange: 'transform' }}
/>
// Throttle redraws on mobile
useEffect(() => {
let rafId
const render = () => {
// Draw logic here
rafId = requestAnimationFrame(render)
}
render()
return () => cancelAnimationFrame(rafId)
}, [])
```
---
## Step 10: Add Loading State
Show spinner while frames load:
```tsx
{loading && (
<div className="fixed inset-0 flex items-center justify-center bg-[#050505]">
<div className="animate-spin h-12 w-12 border-4 border-white/20 border-t-white rounded-full" />
</div>
)}
```
---
## Common Issues & Fixes
### Images not loading
- Check file paths match exactly (case-sensitive)
- Verify all frames exist in `/public/frames/`
- Open browser console for 404 errors
### Stuttering animation
- Ensure all images preloaded before starting
- Use WebP (not PNG/JPEG)
- Check canvas size isn't too large
### Visible image edges
- Background colors don't match exactly
- Use eyedropper tool, not guessing
- Check for gradients in image background
### Mobile performance
- Reduce frame count (use every 2nd frame)
- Debounce with requestAnimationFrame
- Consider disabling on small screens
---
## Testing Checklist
- [ ] All frames load without 404s
- [ ] Animation smooth from 0-100% scroll
- [ ] Text fades in/out at correct positions
- [ ] Background seamlessly blends with images
- [ ] Loading spinner shows before animation
- [ ] Works on mobile (or gracefully disabled)
- [ ] No console errors
---
## Related
- concepts/scroll-linked-animations.md - Understanding the technique
- examples/headphone-scrollytelling.md - Full code example
- lookup/animation-image-prompts.md - Prompts for frame generation
---
## References
- [Next.js Image Optimization](https://nextjs.org/docs/app/building-your-application/optimizing/images)
- [Framer Motion useScroll](https://www.framer.com/motion/use-scroll/)

View File

@@ -0,0 +1,215 @@
<!-- Context: ui/scroll-animation-prompts | Priority: high | Version: 1.0 | Updated: 2026-02-15 -->
---
description: "AI prompts for generating start/end frames and video sequences for scrollytelling"
---
# Lookup: Scroll Animation Image Generation Prompts
**Purpose**: AI prompts for generating start/end frames and video sequences for scrollytelling
**Last Updated**: 2026-01-07
---
## Overview
Use these prompts with nano banana, Runway, Pika, or other AI tools to create image sequences for scroll animations.
**Workflow**: Start frame → End frame → Video interpolation → Frame extraction
---
## Start Frame Prompts
### Product Hero Shot
```
Ultra-premium product photography of [PRODUCT NAME] placed on a matte black
surface, minimalistic studio photoshoot. Deep black background (#050505) with
subtle gradient falloff, soft rim lighting outlining edges, controlled
reflections on smooth textures. Cinematic lighting, high contrast, luxury tech
aesthetic, sharp focus, shallow depth of field. No clutter, no text, no logos
emphasized. Shot with professional DSLR, 85mm lens, f/1.8, ultra-high
resolution, photorealistic, Apple-level product shoot, dramatic mood, modern
and elegant.
```
**Variables**: Replace [PRODUCT NAME] with your product
**Output**: Starting position, fully assembled, hero angle
---
### Variations by Product Type
| Product Type | Additional Details |
|--------------|-------------------|
| **Headphones** | "over-ear headphones with leather cushions and metal headband" |
| **Smartphone** | "smartphone with edge-to-edge OLED display, aluminum frame" |
| **Watch** | "luxury smartwatch with titanium case and sapphire crystal" |
| **Laptop** | "thin laptop with aluminum unibody, open at 45 degrees" |
| **Camera** | "mirrorless camera with prime lens attached, side profile" |
---
## End Frame Prompts
### Exploded Technical View
```
Exploded technical diagram view of [PRODUCT NAME], every component precisely
separated and floating in perfect alignment, suspended in mid-air against deep
black studio background (#050505). Visible internal structure including
[INTERNAL COMPONENTS], all parts evenly spaced showing assembly order.
Hyper-realistic product visualization, ultra-sharp focus, studio rim lighting
identical to hero shot, soft highlights tracing each component, controlled
reflections on matte and metal surfaces. Cinematic lighting, high contrast,
luxury engineering aesthetic, no labels, no annotations, no text.
Photorealistic, ultra-high resolution, Apple-style industrial design render,
dramatic and clean.
```
**Variables**:
- [PRODUCT NAME]: Your product
- [INTERNAL COMPONENTS]: Specific parts to show
---
### Internal Components by Product
| Product | Internal Components Examples |
|---------|------------------------------|
| **Headphones** | "copper wiring, titanium drivers, magnets, circuit boards, padding layers, metal frame" |
| **Smartphone** | "battery, logic board, cameras, OLED panel, antenna bands, frame" |
| **Watch** | "watch movement, gears, battery, sensors, display, crown mechanism" |
| **Laptop** | "keyboard assembly, trackpad, battery cells, logic board, cooling fans, display panel" |
| **Camera** | "sensor, shutter mechanism, lens elements, mirror assembly, circuit boards" |
---
## Video Interpolation Prompts
### For Runway/Pika
```
Smoothly transition from fully assembled [PRODUCT] to exploded view.
Components separate slowly and precisely, maintaining perfect alignment.
Camera stays locked, product rotates slightly clockwise. Cinematic motion,
professional product animation, 4-5 seconds duration, 30fps.
```
**Settings**:
- Duration: 4-5 seconds
- FPS: 30 (yields 120-150 frames)
- Camera: Static or slow orbit
- Motion: Smooth, controlled separation
---
## Frame Extraction
### Using ffmpeg
```bash
# Extract as WebP (best for web)
ffmpeg -i animation.mp4 -vf fps=30 frame_%04d.webp
# Extract as PNG (higher quality, larger)
ffmpeg -i animation.mp4 -vf fps=30 frame_%04d.png
# Extract with quality control
ffmpeg -i animation.mp4 -vf fps=30 -quality 90 frame_%04d.webp
```
### Using ezgif.com
1. Upload MP4 video
2. Choose "Video to GIF" → "Split to frames"
3. Select WebP format
4. Download all frames as ZIP
5. Rename: `frame_0001.webp`, `frame_0002.webp`, etc.
---
## Background Color Matching
**CRITICAL**: Page background MUST match image background exactly
### Recommended Dark Backgrounds
| Color Code | Usage |
|------------|-------|
| `#050505` | Pure black with slight lift (recommended) |
| `#0a0a0a` | Slightly lighter, less harsh |
| `#000000` | True black (only if images are true black) |
| `#1a1a1a` | Dark gray (for lighter renders) |
**Pro tip**: Use eyedropper tool on first frame background, use exact hex in CSS
---
## Alternative Animation Styles
### Rotation (360° spin)
**Start**: Front view
**End**: Front view (after 360° rotation)
**Prompt**: "Rotate product 360 degrees on turntable, maintain lighting"
### Zoom In (Feature reveal)
**Start**: Full product view
**End**: Close-up of key feature
**Prompt**: "Smooth camera push-in focusing on [FEATURE], maintain focus"
### Morph (Color/style change)
**Start**: Product in color A
**End**: Product in color B
**Prompt**: "Seamlessly morph product color from [A] to [B], maintain form"
---
## Quality Settings
### For High-End Results
- **Resolution**: 1920x1080 minimum (4K for high-DPI)
- **Format**: WebP (compression) or PNG (quality)
- **Frame count**: 90-150 frames (3-5 seconds at 30fps)
- **Total size**: Target <50MB for all frames combined
### Optimization Tips
1. Use WebP format (70% smaller than PNG)
2. Compress with quality 85-90
3. Resize images to max 2000px width
4. Use consistent aspect ratio (16:9 or 1:1)
---
## Testing Checklist
- [ ] Background color matches exactly (no visible edges)
- [ ] All frames same dimensions
- [ ] Smooth motion (no jumps between frames)
- [ ] Consistent lighting across sequence
- [ ] File names sequential (`frame_0001` to `frame_0120`)
- [ ] Total file size reasonable (<50MB)
---
## Related
- concepts/scroll-linked-animations.md - Understanding the technique
- examples/scrollytelling-headphone.md - Full implementation
- guides/scrollytelling-setup.md - Setup instructions
---
## Tool References
- [Runway ML](https://runwayml.com) - AI video generation
- [Pika Labs](https://pika.art) - AI video interpolation
- [ezgif](https://ezgif.com/split-video) - Frame extraction
- [FFmpeg](https://ffmpeg.org) - Video processing

View File

@@ -0,0 +1,95 @@
<!-- Context: ui/navigation | Priority: critical | Version: 1.0 | Updated: 2026-02-15 -->
---
description: "Advanced web UI patterns - scroll animations, visual effects, and interactive design"
---
# Web Design Patterns
**Purpose**: Advanced web UI patterns - scroll animations, visual effects, and interactive design
**Last Updated**: 2026-01-31
---
## Quick Navigation
### Concepts
| File | Description | Priority |
|------|-------------|----------|
| [navigation.md](concepts/navigation.md) | Concepts navigation | high |
| [scroll-linked-animations.md](concepts/scroll-linked-animations.md) | Scroll-synced image sequences (scrollytelling) | high |
### Examples
| File | Description | Priority |
|------|-------------|----------|
| [navigation.md](examples/navigation.md) | Examples navigation | high |
| [scrollytelling-headphone.md](examples/scrollytelling-headphone.md) | Full Next.js scroll animation example | high |
### Guides
| File | Description | Priority |
|------|-------------|----------|
| [navigation.md](guides/navigation.md) | Guides navigation | high |
| [building-scrollytelling-pages.md](guides/building-scrollytelling-pages.md) | Complete implementation guide | high |
| [premium-dark-ui-visual-reference.md](guides/premium-dark-ui-visual-reference.md) | Visual reference for premium dark UI | medium |
### Lookup
| File | Description | Priority |
|------|-------------|----------|
| [navigation.md](lookup/navigation.md) | Lookup navigation | high |
| [scroll-animation-prompts.md](lookup/scroll-animation-prompts.md) | AI prompts for generating animation sequences | medium |
### Errors
| File | Description | Priority |
|------|-------------|----------|
| _(No error files yet)_ | | |
---
## Loading Strategy
**For scroll animation work**:
1. Load `concepts/scroll-linked-animations.md` (understand technique)
2. Load `lookup/scroll-animation-prompts.md` (generate image sequences)
3. Load `examples/scrollytelling-headphone.md` (see full code)
4. Reference `guides/building-scrollytelling-pages.md` (step-by-step)
**For premium dark UI design**:
1. Load `guides/premium-dark-ui-visual-reference.md` (visual patterns and implementation)
---
## Scope
This subcategory covers:
- ✅ Scroll-linked animations (scrollytelling)
- ✅ Canvas-based rendering
- ✅ Framer Motion patterns
- ✅ Image sequence generation
- ✅ Premium dark UI design system
- ✅ Glassmorphism patterns
- ⏳ CSS animations (future)
- ⏳ SVG animations (future)
- ⏳ WebGL effects (future)
---
## Related Categories
- `ui/web/` - Core web UI patterns (parent directory)
- `ui/web/animation-patterns.md` - CSS animations and transitions
- `development/` - General development patterns
---
## Used By
**Agents**: frontend-specialist, design-specialist, animation-expert
## Statistics
- Concepts: 1 + navigation
- Examples: 1 + navigation
- Guides: 6 + navigation
- Lookup: 1 + navigation
- Errors: 0
- **Total**: 13 files

View File

@@ -0,0 +1,118 @@
<!-- Context: ui/navigation | Priority: critical | Version: 1.0 | Updated: 2026-02-15 -->
# Web UI Context
**Purpose**: Web-based UI patterns, animations, styling standards, and React component design
**Last Updated**: 2026-01-07
---
## Quick Navigation
### Core Files
| File | Description | Priority |
|------|-------------|----------|
| [animation-basics.md](animation-basics.md) | Animation fundamentals, timing, easing | high |
| [animation-components.md](animation-components.md) | Button, card, modal, dropdown animations | high |
| [animation-chat.md](animation-chat.md) | Chat UI and message animations | medium |
| [animation-loading.md](animation-loading.md) | Skeleton, spinner, progress animations | medium |
| [animation-forms.md](animation-forms.md) | Form input and validation animations | medium |
| [animation-advanced.md](animation-advanced.md) | Recipes, best practices, accessibility | medium |
| [ui-styling-standards.md](ui-styling-standards.md) | CSS frameworks, Tailwind patterns, styling best practices | high |
| [react-patterns.md](react-patterns.md) | Modern React patterns, hooks, component design | high |
| [design-systems.md](design-systems.md) | Design system principles and component libraries | medium |
| [images-guide.md](images-guide.md) | Placeholder and responsive images | medium |
| [icons-guide.md](icons-guide.md) | Icon systems (Lucide, Heroicons, FA) | medium |
| [fonts-guide.md](fonts-guide.md) | Font loading and optimization | medium |
| [cdn-resources.md](cdn-resources.md) | CDN libraries and resources | medium |
### Subcategories
| Subcategory | Description | Path |
|-------------|-------------|------|
| **design/** | Advanced design patterns (scrollytelling, effects) | [design/navigation.md](design/navigation.md) |
---
## Loading Strategy
### For general web UI work:
1. Load `ui-styling-standards.md` (CSS frameworks, Tailwind)
2. Load `react-patterns.md` (component patterns)
3. Reference `animation-patterns.md` (if animations needed)
### For animation work:
1. Load `animation-basics.md` (fundamentals, timing, easing)
2. Load `animation-components.md` (UI component animations)
3. Reference `animation-chat.md` for chat UI patterns
4. Reference `animation-advanced.md` for recipes and accessibility
### For scroll animations:
1. Navigate to `design/` subcategory
2. Load scroll-linked animation guides
---
## Scope
This subcategory covers:
- ✅ CSS animations and transitions
- ✅ Tailwind CSS and utility-first styling
- ✅ React component patterns and hooks
- ✅ Design systems and component libraries
- ✅ Icon libraries and web fonts
- ✅ Scroll-linked animations (scrollytelling)
- ✅ Canvas-based rendering
- ✅ Framer Motion patterns
---
## File Summaries
### animation-basics.md, animation-components.md, animation-chat.md, animation-loading.md, animation-forms.md, animation-advanced.md
CSS animations, micro-interactions, and UI transitions split into focused modules.
**Key topics**: Animation micro-syntax, 60fps performance, reduced motion, chat UI animations, component patterns
### ui-styling-standards.md
CSS framework usage, Tailwind CSS patterns, responsive design, and styling best practices.
**Key topics**: Utility-first CSS, component styling, responsive breakpoints, dark mode
### react-patterns.md
Modern React patterns including functional components, hooks, state management, and performance optimization.
**Key topics**: Custom hooks, context API, code splitting, memoization
### design-systems.md
Design system principles, component libraries, and maintaining consistency across applications.
**Key topics**: Design tokens, component APIs, documentation, versioning
### images-guide.md, icons-guide.md, fonts-guide.md, cdn-resources.md
Managing design assets in web applications - split into focused guides.
**Key topics**: Placeholder images, icon libraries (Lucide, Heroicons), web fonts, CDN resources
---
## Related Categories
- `ui/terminal/` - Terminal UI patterns
- `development/` - General development patterns
- `product/` - Product design and UX strategy
---
## Used By
**Agents**: frontend-specialist, design-specialist, ui-developer, react-developer, animation-expert
---
## Statistics
- Core files: 8
- Subcategories: 1 (design/)
- **Total context files**: 8 + design subcategory

View File

@@ -0,0 +1,330 @@
<!-- Context: ui/react-patterns | Priority: low | Version: 1.0 | Updated: 2026-02-15 -->
# React Patterns & Best Practices
**Category**: development
**Purpose**: Modern React patterns, hooks usage, and component design principles
**Used by**: frontend-specialist
---
## Overview
This guide covers modern React patterns using functional components, hooks, and best practices for building scalable React applications.
## Component Patterns
### 1. Functional Components with Hooks
**Always use functional components**:
```jsx
// Good
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetchUser(userId).then(setUser);
}, [userId]);
return <div>{user?.name}</div>;
}
```
### 2. Custom Hooks for Reusable Logic
**Extract common logic into custom hooks**:
```jsx
// Custom hook
function useUser(userId) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
fetchUser(userId)
.then(setUser)
.catch(setError)
.finally(() => setLoading(false));
}, [userId]);
return { user, loading, error };
}
// Usage
function UserProfile({ userId }) {
const { user, loading, error } = useUser(userId);
if (loading) return <Spinner />;
if (error) return <Error message={error.message} />;
return <div>{user.name}</div>;
}
```
### 3. Composition Over Props Drilling
**Use composition to avoid prop drilling**:
```jsx
// Bad - Props drilling
function App() {
const [theme, setTheme] = useState('light');
return <Layout theme={theme} setTheme={setTheme} />;
}
// Good - Composition with Context
const ThemeContext = createContext();
function App() {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Layout />
</ThemeContext.Provider>
);
}
function Layout() {
const { theme } = useContext(ThemeContext);
return <div className={theme}>...</div>;
}
```
### 4. Compound Components
**For complex, related components**:
```jsx
function Tabs({ children }) {
const [activeTab, setActiveTab] = useState(0);
return (
<TabsContext.Provider value={{ activeTab, setActiveTab }}>
{children}
</TabsContext.Provider>
);
}
Tabs.List = function TabsList({ children }) {
return <div className="tabs-list">{children}</div>;
};
Tabs.Tab = function Tab({ index, children }) {
const { activeTab, setActiveTab } = useContext(TabsContext);
return (
<button
className={activeTab === index ? 'active' : ''}
onClick={() => setActiveTab(index)}
>
{children}
</button>
);
};
Tabs.Panel = function TabPanel({ index, children }) {
const { activeTab } = useContext(TabsContext);
return activeTab === index ? <div>{children}</div> : null;
};
// Usage
<Tabs>
<Tabs.List>
<Tabs.Tab index={0}>Tab 1</Tabs.Tab>
<Tabs.Tab index={1}>Tab 2</Tabs.Tab>
</Tabs.List>
<Tabs.Panel index={0}>Content 1</Tabs.Panel>
<Tabs.Panel index={1}>Content 2</Tabs.Panel>
</Tabs>
```
## Hooks Best Practices
### 1. useEffect Dependencies
**Always specify dependencies correctly**:
```jsx
// Bad - Missing dependencies
useEffect(() => {
fetchData(userId);
}, []);
// Good - Correct dependencies
useEffect(() => {
fetchData(userId);
}, [userId]);
// Good - Stable function reference
const fetchData = useCallback((id) => {
api.getUser(id).then(setUser);
}, []);
useEffect(() => {
fetchData(userId);
}, [userId, fetchData]);
```
### 2. useMemo for Expensive Calculations
**Memoize expensive computations**:
```jsx
function DataTable({ data, filters }) {
const filteredData = useMemo(() => {
return data.filter(item =>
filters.every(filter => filter(item))
);
}, [data, filters]);
return <Table data={filteredData} />;
}
```
### 3. useCallback for Stable References
**Prevent unnecessary re-renders**:
```jsx
function Parent() {
const [count, setCount] = useState(0);
// Bad - New function on every render
const handleClick = () => setCount(c => c + 1);
// Good - Stable function reference
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
return <Child onClick={handleClick} />;
}
const Child = memo(function Child({ onClick }) {
return <button onClick={onClick}>Click</button>;
});
```
## State Management Patterns
### 1. Local State First
**Start with local state, lift when needed**:
```jsx
// Local state
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}
// Lifted state when shared
function App() {
const [count, setCount] = useState(0);
return (
<>
<Counter count={count} setCount={setCount} />
<Display count={count} />
</>
);
}
```
### 2. useReducer for Complex State
**Use reducer for related state updates**:
```jsx
const initialState = { count: 0, step: 1 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { ...state, count: state.count + state.step };
case 'decrement':
return { ...state, count: state.count - state.step };
case 'setStep':
return { ...state, step: action.payload };
default:
return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<span>{state.count}</span>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
</>
);
}
```
## Performance Optimization
### 1. Code Splitting
**Lazy load routes and heavy components**:
```jsx
import { lazy, Suspense } from 'react';
const Dashboard = lazy(() => import('./Dashboard'));
const Settings = lazy(() => import('./Settings'));
function App() {
return (
<Suspense fallback={<Loading />}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</Suspense>
);
}
```
### 2. Virtualization for Long Lists
**Use virtualization for large datasets**:
```jsx
import { FixedSizeList } from 'react-window';
function VirtualList({ items }) {
const Row = ({ index, style }) => (
<div style={style}>{items[index].name}</div>
);
return (
<FixedSizeList
height={600}
itemCount={items.length}
itemSize={50}
width="100%"
>
{Row}
</FixedSizeList>
);
}
```
## Best Practices
1. **Keep components small and focused** - Single responsibility principle
2. **Use TypeScript** - Type safety prevents bugs and improves DX
3. **Colocate related code** - Keep components, styles, and tests together
4. **Use meaningful prop names** - Clear, descriptive names improve readability
5. **Avoid inline functions in JSX** - Extract to named functions or useCallback
6. **Use fragments** - Avoid unnecessary wrapper divs
7. **Handle loading and error states** - Always show feedback to users
8. **Test components** - Use React Testing Library for user-centric tests
## Anti-Patterns
-**Prop drilling** - Use context or composition instead
-**Massive components** - Break down into smaller, focused components
-**Mutating state directly** - Always use setState or dispatch
-**Using index as key** - Use stable, unique identifiers
-**Unnecessary useEffect** - Derive state when possible
-**Ignoring ESLint warnings** - React hooks rules prevent bugs
-**Not memoizing context values** - Causes unnecessary re-renders
## References
- React Documentation (react.dev)
- React Patterns by Kent C. Dodds
- Epic React by Kent C. Dodds

View File

@@ -0,0 +1,552 @@
<!-- Context: development/ui-styling-standards | Priority: high | Version: 1.0 | Updated: 2025-12-09 -->
# UI Styling Standards
## Overview
Standards and conventions for CSS frameworks, responsive design, and styling best practices in frontend development.
## Quick Reference
**Framework**: Tailwind CSS + Flowbite (default)
**Approach**: Mobile-first responsive
**Format**: Utility-first CSS
**Specificity**: Use `!important` for overrides when needed
---
## CSS Framework Conventions
### Tailwind CSS
**Loading Method** (Preferred):
```html
<!-- ✅ Use CDN script tag -->
<script src="https://cdn.tailwindcss.com"></script>
```
**Avoid**:
```html
<!-- ❌ Don't use stylesheet link -->
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
```
**Why**: Script tag allows for JIT compilation and configuration
### Flowbite
**Loading Method**:
```html
<!-- Flowbite CSS -->
<link href="https://cdn.jsdelivr.net/npm/flowbite@2.0.0/dist/flowbite.min.css" rel="stylesheet">
<!-- Flowbite JS -->
<script src="https://cdn.jsdelivr.net/npm/flowbite@2.0.0/dist/flowbite.min.js"></script>
```
**Usage**: Flowbite is the default component library unless user specifies otherwise
**Components Available**:
- Buttons, forms, modals
- Navigation, dropdowns, tabs
- Cards, alerts, badges
- Tables, pagination
- Tooltips, popovers
---
## Responsive Design Requirements
### Mobile-First Approach
**Rule**: ALL designs MUST be responsive
**Breakpoints** (Tailwind defaults):
```css
/* Mobile first - base styles apply to mobile */
.element { }
/* Small devices (640px and up) */
@media (min-width: 640px) { } /* sm: */
/* Medium devices (768px and up) */
@media (min-width: 768px) { } /* md: */
/* Large devices (1024px and up) */
@media (min-width: 1024px) { } /* lg: */
/* Extra large devices (1280px and up) */
@media (min-width: 1280px) { } /* xl: */
/* 2XL devices (1536px and up) */
@media (min-width: 1536px) { } /* 2xl: */
```
**Tailwind Syntax**:
```html
<!-- Mobile: stack, Desktop: side-by-side -->
<div class="flex flex-col md:flex-row">
<div class="w-full md:w-1/2">Left</div>
<div class="w-full md:w-1/2">Right</div>
</div>
<!-- Mobile: full width, Desktop: constrained -->
<div class="w-full lg:w-3/4 xl:w-1/2 mx-auto">
Content
</div>
```
### Testing Requirements
✅ Test at minimum breakpoints: 375px, 768px, 1024px, 1440px
✅ Verify touch targets (min 44x44px)
✅ Check text readability at all sizes
✅ Ensure images scale properly
✅ Test navigation on mobile
---
## Color Palette Guidelines
### Avoid Bootstrap Blue
**Rule**: NEVER use generic Bootstrap blue (#007bff) unless explicitly requested
**Why**: Overused, lacks personality, feels dated
**Alternatives**:
```css
/* Instead of Bootstrap blue */
--bootstrap-blue: #007bff; /* ❌ Avoid */
/* Use contextual colors */
--primary: oklch(0.6489 0.2370 26.9728); /* Vibrant orange */
--accent: oklch(0.5635 0.2408 260.8178); /* Rich purple */
--info: oklch(0.6200 0.1900 260); /* Modern blue */
--success: oklch(0.7323 0.2492 142.4953); /* Fresh green */
```
### Color Usage Rules
1. **Semantic naming**: Use `--primary`, `--accent`, not `--blue`, `--red`
2. **Brand alignment**: Choose colors that match project personality
3. **Contrast testing**: Ensure WCAG AA compliance (4.5:1 minimum)
4. **Consistency**: Use theme variables throughout
---
## Background/Foreground Contrast
### Contrast Rule
**When designing components or posters**:
- **Light component** → Dark background
- **Dark component** → Light background
**Why**: Ensures visibility and creates visual hierarchy
**Examples**:
```html
<!-- Light card on dark background -->
<div class="bg-gray-900 p-8">
<div class="bg-white text-gray-900 p-6 rounded-lg">
Light card content
</div>
</div>
<!-- Dark card on light background -->
<div class="bg-gray-50 p-8">
<div class="bg-gray-900 text-white p-6 rounded-lg">
Dark card content
</div>
</div>
```
### Component-Specific Rules
**Posters/Hero Sections**:
- Use high contrast for readability
- Consider overlay gradients for text on images
- Test with actual content
**Cards/Panels**:
- Subtle elevation with shadows
- Clear boundary between card and background
- Consistent padding
---
## CSS Specificity & Overrides
### Using !important
**Rule**: Use `!important` for properties that might be overwritten by Tailwind or Flowbite
**Common Cases**:
```css
/* Typography overrides */
h1 {
font-size: 2.5rem !important;
font-weight: 700 !important;
line-height: 1.2 !important;
}
body {
font-family: 'Inter', sans-serif !important;
color: var(--foreground) !important;
}
/* Component overrides */
.custom-button {
background-color: var(--primary) !important;
border-radius: var(--radius) !important;
}
```
**When NOT to use**:
```css
/* ❌ Don't use for everything */
.element {
margin: 1rem !important;
padding: 1rem !important;
display: flex !important;
}
/* ✅ Use Tailwind utilities instead */
<div class="m-4 p-4 flex">
```
### Specificity Best Practices
1. **Prefer utility classes** over custom CSS
2. **Use !important sparingly** - only for framework overrides
3. **Scope custom styles** to avoid conflicts
4. **Use CSS custom properties** for theming
---
## Layout Patterns
### Flexbox (Preferred for 1D layouts)
```html
<!-- Horizontal layout -->
<div class="flex items-center gap-4">
<div>Item 1</div>
<div>Item 2</div>
</div>
<!-- Vertical layout -->
<div class="flex flex-col gap-4">
<div>Item 1</div>
<div>Item 2</div>
</div>
<!-- Centered content -->
<div class="flex items-center justify-center min-h-screen">
<div>Centered content</div>
</div>
```
### Grid (Preferred for 2D layouts)
```html
<!-- Responsive grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<div>Card 1</div>
<div>Card 2</div>
<div>Card 3</div>
</div>
<!-- Dashboard layout -->
<div class="grid grid-cols-12 gap-4">
<aside class="col-span-12 lg:col-span-3">Sidebar</aside>
<main class="col-span-12 lg:col-span-9">Content</main>
</div>
```
### Container Patterns
```html
<!-- Centered container with max width -->
<div class="container mx-auto px-4 max-w-7xl">
Content
</div>
<!-- Full-width section with contained content -->
<section class="w-full bg-gray-50">
<div class="container mx-auto px-4 py-12 max-w-6xl">
Content
</div>
</section>
```
---
## Typography Standards
### Hierarchy
```html
<!-- Heading scale -->
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold">Main Heading</h1>
<h2 class="text-3xl md:text-4xl font-semibold">Section Heading</h2>
<h3 class="text-2xl md:text-3xl font-semibold">Subsection</h3>
<h4 class="text-xl md:text-2xl font-medium">Minor Heading</h4>
<!-- Body text -->
<p class="text-base md:text-lg leading-relaxed">Body text</p>
<p class="text-sm text-gray-600">Secondary text</p>
<p class="text-xs text-gray-500">Caption text</p>
```
### Font Loading
**Always use Google Fonts**:
```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
```
**Apply in CSS**:
```css
body {
font-family: 'Inter', sans-serif !important;
}
```
### Readability
- **Line length**: 60-80 characters optimal
- **Line height**: 1.5-1.75 for body text
- **Font size**: Minimum 16px for body text
- **Contrast**: 4.5:1 minimum for normal text
---
## Component Styling Patterns
### Buttons
```html
<!-- Primary button -->
<button class="bg-primary text-primary-foreground px-6 py-3 rounded-lg font-medium hover:opacity-90 transition-opacity">
Primary Action
</button>
<!-- Secondary button -->
<button class="bg-secondary text-secondary-foreground px-6 py-3 rounded-lg font-medium hover:bg-secondary/80 transition-colors">
Secondary Action
</button>
<!-- Outline button -->
<button class="border-2 border-primary text-primary px-6 py-3 rounded-lg font-medium hover:bg-primary hover:text-primary-foreground transition-all">
Outline Action
</button>
```
### Cards
```html
<!-- Basic card -->
<div class="bg-card text-card-foreground rounded-lg shadow-md p-6">
<h3 class="text-xl font-semibold mb-2">Card Title</h3>
<p class="text-muted-foreground">Card content</p>
</div>
<!-- Interactive card -->
<div class="bg-card text-card-foreground rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow cursor-pointer">
<h3 class="text-xl font-semibold mb-2">Interactive Card</h3>
<p class="text-muted-foreground">Hover for effect</p>
</div>
```
### Forms
```html
<!-- Input field -->
<div class="space-y-2">
<label class="block text-sm font-medium">Email</label>
<input
type="email"
class="w-full px-4 py-2 border border-input rounded-lg focus:ring-2 focus:ring-ring focus:border-transparent transition-all"
placeholder="you@example.com"
>
</div>
<!-- Textarea -->
<div class="space-y-2">
<label class="block text-sm font-medium">Message</label>
<textarea
class="w-full px-4 py-2 border border-input rounded-lg focus:ring-2 focus:ring-ring focus:border-transparent transition-all resize-none"
rows="4"
placeholder="Your message..."
></textarea>
</div>
```
---
## Accessibility Standards
### ARIA Labels
```html
<!-- Button with icon -->
<button aria-label="Close dialog">
<svg>...</svg>
</button>
<!-- Navigation -->
<nav aria-label="Main navigation">
<ul>...</ul>
</nav>
```
### Semantic HTML
```html
<!-- ✅ Use semantic elements -->
<header>...</header>
<nav>...</nav>
<main>...</main>
<article>...</article>
<aside>...</aside>
<footer>...</footer>
<!-- ❌ Avoid div soup -->
<div class="header">...</div>
<div class="nav">...</div>
<div class="main">...</div>
```
### Focus States
```css
/* Always provide visible focus states */
button:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
}
/* Tailwind utility */
<button class="focus:ring-2 focus:ring-ring focus:ring-offset-2">
Button
</button>
```
---
## Performance Optimization
### CSS Loading
```html
<!-- Preconnect to font sources -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- Preload critical fonts -->
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
```
### Image Optimization
```html
<!-- Responsive images -->
<img
src="image-800.jpg"
srcset="image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
alt="Description"
loading="lazy"
>
```
### Critical CSS
```html
<!-- Inline critical CSS -->
<style>
/* Above-the-fold styles */
body { margin: 0; font-family: system-ui; }
.hero { min-height: 100vh; }
</style>
<!-- Load full CSS async -->
<link rel="stylesheet" href="styles.css" media="print" onload="this.media='all'">
```
---
## Best Practices
### Do's ✅
- Use Tailwind utility classes for rapid development
- Load Tailwind via script tag for JIT compilation
- Use Flowbite as default component library
- Ensure all designs are mobile-first responsive
- Test at multiple breakpoints
- Use semantic HTML elements
- Provide ARIA labels for interactive elements
- Use CSS custom properties for theming
- Apply `!important` for framework overrides
- Ensure proper color contrast (WCAG AA)
### Don'ts ❌
- Don't use Bootstrap blue without explicit request
- Don't load Tailwind as a stylesheet
- Don't skip responsive design
- Don't use div soup (use semantic HTML)
- Don't forget focus states
- Don't hardcode colors (use theme variables)
- Don't skip accessibility testing
- Don't use tiny touch targets (<44px)
- Don't mix color formats
- Don't over-use `!important`
---
## Framework Alternatives
If user requests a different framework:
**Bootstrap**:
```html
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
```
**Bulma**:
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
```
**Foundation**:
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/foundation-sites@6.7.5/dist/css/foundation.min.css">
<script src="https://cdn.jsdelivr.net/npm/foundation-sites@6.7.5/dist/js/foundation.min.js"></script>
```
---
## References
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
- [Flowbite Components](https://flowbite.com/docs/getting-started/introduction/)
- [WCAG Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)
- [MDN Web Accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility)