Documentation Index
Fetch the complete documentation index at: https://mintlify.com/apursley2012/dyed-in-the-wool/llms.txt
Use this file to discover all available pages before exploring further.
Overview
All interactive and transitional animations in Dyed in the Wool are implemented with Framer Motion. The only CSS keyframe animation in the codebase isanimate-blob, which handles the decorative pulsing circles in the hero background — everything else (page entry, scroll reveals, button hovers, modal expansions, cursor trails) is driven by Framer Motion variants.
This document catalogs each animation pattern with its exact values so you can tune, extend, or disable them individually.
Animation Patterns
1. Fade + Slide Up — Page Section Entry
Used when a section or content block first appears in the viewport on page load.y: 20 → 0) combined with a fade communicates that content is “settling into place”. Increase y for a more dramatic entrance; reduce duration for snappier feel.
2. Spring Scale — Hero Headline
Applied to the main hero heading so it “breathes in” on load rather than simply fading.spring type with bounce: 0.4 gives the headline a subtle overshoot. Lower bounce toward 0 for a more refined, editorial feel; raise it toward 0.6 for a more playful pop.
3. Scroll-Triggered Reveal — Story Paragraphs
Each paragraph in the About / story section animates in as it enters the viewport, with a slight rotation that unwinds as it arrives.rotate: -5 → 0 adds a hand-crafted, organic quality that reinforces the craft aesthetic. The margin: '-100px' means the animation triggers 100 px before the element fully enters the viewport, so it’s already in motion when the reader’s eye reaches it.
4. Button Hover & Tap
Simple scale transforms give buttons a physical, pressable quality.1 simulates the button physically depressing under a finger or click. Keep the hover scale modest (1.05–1.08) to avoid making buttons feel oversized.
5. Button Fill — Radial Expand
Amotion.div sits inside each CTA button and expands from a circle to fill the entire button on hover, creating an ink-bleed effect.
dye-magenta background color, so hovering reveals the accent color bleeding outward from the center. Increase scale beyond 1.5 if the button is wide and the fill doesn’t reach the edges.
6. Page Transition — Blur Fade
Used withAnimatePresence mode="wait" around the router outlet. When navigating between pages, the outgoing page blurs and fades, and the incoming page unblurs and fades in.
mode="wait" on AnimatePresence ensures the exit animation completes before the enter animation starts — critical for the blur effect to feel intentional rather than chaotic.
7. Project Card Modal — layoutId Shared Element
The project grid cards expand into a full modal using Framer Motion’s shared layout animation.
initial / animate values are needed — the layoutId match is sufficient. Ensure the modal is rendered in the same AnimatePresence tree so Framer can coordinate the transition.
8. Ink Drop Cursor Trail
Each drop in theDyeDropCursor trail spawns a motion.div that expands outward and fades.
P array (see Color Palette → Updating the DyeDropCursor Trail).
9. Nav Indicator — Shared Layout Underline
The active-route underline in the navigation uses a shared layout element so it slides smoothly between links when the route changes.layoutId="nav-indicator" should exist in the DOM at any time — the currently active nav item renders it. Framer Motion tracks its position and animates it to the new location whenever the active link changes. The stiffness: 300 / damping: 30 spring feels snappy without overshooting.
10. Cursor — Spring Follow
TheDyeDropCursor dot that tracks the pointer uses a spring transition so it trails the mouse with natural physics rather than teleporting.
stiffness: 500 keeps the cursor close to the pointer at all times, while damping: 28 and mass: 0.5 prevent excessive oscillation. Lowering stiffness creates a lazier, more exaggerated trail; raising damping makes it feel heavier and less springy.
Accessibility — Respecting Reduced Motion
Users who have enabled the “reduce motion” preference in their OS should not see large-scale movement or rapid transitions. Use Framer Motion’suseReducedMotion hook to conditionally disable or minimise animations:
shouldReduceMotion is true, skip the y offset entirely so the element simply fades in without moving. Apply the same pattern to scale, rotate, and filter values — opacity-only transitions are generally safe to keep.
Stagger Delays
Several lists and grids in the portfolio create a cascade effect by multiplying the animation delay by the item’s index:delay: 0), the second after 100 ms, the third after 200 ms, and so on. This gives the impression that items are appearing in sequence rather than all at once.
For long lists, cap the maximum delay to keep the total stagger under ~600 ms — for example
delay: Math.min(index * 0.1, 0.6). An unbounded stagger on a 10-item list would make the last item wait a full second, which feels slow and can frustrate users who scroll quickly.