Skip to main content

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.

The Projects component (internally function U) showcases three portfolio projects as interactive cards. Clicking any card triggers a Framer Motion shared-layout expansion — the card morphs fluidly into a full-screen modal without a cut or fade, creating the illusion of the card growing to fill the viewport.

What It Displays

The page renders:
  1. Section header — the title “PATTERNS I’VE MADE” enters from above on mount.
  2. Card grid — three project cards arranged in a responsive grid. Each card shows the project title, a “technique type” label (the dyeing method metaphor), a color accent fill, and a tag list.
  3. Modal overlay — clicking a card opens an expanded modal with the full description and two action buttons: View Live (ExternalLink icon) and Source (Github icon). Clicking outside the modal or pressing the close button dismisses it.

Content Data

Projects are stored in the f array:
const f = [
  {
    id: 1,
    title: "Liquid UI Library",
    type: "Spiral Fold",
    color: "#0d9488",
    description:
      "A React component library focused on organic, fluid animations and SVG filter effects. Built to break the rigid grid of modern web design.",
    tags: ["React", "Framer Motion", "SVG"],
  },
  {
    id: 2,
    title: "Chroma E-commerce",
    type: "Crumple Technique",
    color: "#db2777",
    description:
      "A headless Shopify storefront with a dynamic color-shifting theme based on the product being viewed. Smooth transitions and a custom cart experience.",
    tags: ["Next.js", "Shopify", "Tailwind"],
  },
  {
    id: 3,
    title: "Flow State App",
    type: "Bullseye Pattern",
    color: "#1e3a8a",
    description:
      "A productivity tool that uses ambient sound and slowly morphing visuals to help users maintain focus. Features a custom audio engine.",
    tags: ["TypeScript", "Web Audio API", "Canvas"],
  },
];
Each color value is used as the card’s full background fill and as the modal’s left-panel background tint.

Animation Details

ElementTechniqueDetails
Section titleinitial → animate on mounty: -20 → 0, opacity: 0 → 1
CardsFramer Motion layoutIdEach card is a motion.div with layoutId: "card-{id}"
Card hoverwhileHover scaleCards scale to 1.02
Card tapwhileTap scaleCards scale to 0.98 on press
Card → modal expandlayoutId shared layoutThe card and modal share the same layoutId string (e.g., "card-1"); Framer Motion interpolates all geometry
Modal backdropAnimatePresence + opacityBackground overlay fades in via opacity: 0 → 1 with bg-dye-fabric/80 backdrop-blur-sm
Modal exitAnimatePresence exitReverse of the expand — modal shrinks back to card position
About layoutId modal animation: Framer Motion’s layoutId prop allows two separate elements in the React tree to be treated as the same element across mount/unmount events. When the card unmounts and the modal mounts, both share the same layoutId string (e.g., "card-1"), so Framer Motion automatically FLIP-animates the geometry transition between them. This means no manually coded position, transform, or getBoundingClientRect calls are needed — the library handles all positional interpolation automatically.

Customization

Add a new project Append an object to the f array. All fields are required:
{
  id: 4,
  title: "Your New Project",
  type: "Ice Fold",            // The dyeing-technique label
  color: "#7c3aed",            // Accent color (hex)
  description: "A short description of what the project does and the interesting tech choices behind it.",
  tags: ["Vue", "D3", "GSAP"],
}
Change the live or source URLs The View Live and Source buttons currently render with href="#" placeholders in the modal. Wire them up by adding url and repo fields to each f entry and threading them into the button href props inside the modal JSX. Change card accent colors Each project’s color field controls its card background fill and modal left-panel tint. Replace the hex value with any valid CSS color:
color: "#7c3aed"  // purple
Adjust stagger timing The per-card stagger is controlled by Framer Motion’s transition delay. To speed up the entrance, reduce the multiplier:
transition={{ delay: index * 0.08 }}

Build docs developers (and LLMs) love