Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/the-craft/llms.txt

Use this file to discover all available pages before exploring further.

Candle is an interactive UI element that doubles as a visual metaphor. On the Work page, each position in the employment history is represented by a candle whose physical height corresponds to the significance or seniority of that role — taller candles for senior positions, shorter ones for earlier or shorter-tenure roles. Clicking a candle lights it and opens the corresponding job detail panel. The result is a timeline that feels less like a résumé table and more like an altar: a row of candles waiting to be called upon.

Props

PropTypeDefaultDescription
labelstringThe year or date label displayed beneath the candle body in font-cinzel tracking-widest text.
heightnumber120The pixel height of the candle’s wax body (rect). Does not include the flame or wick — the full visual height is height + 40px.
isActivebooleanWhen true, the flame glows at full brightness with animate-flicker and the candle body brightens. When false, the flame is dim and the candle is at reduced opacity.
onClickfunctionCallback fired when the candle div is clicked. Typically used to call setActiveId in the Work page.

Visual Structure

The candle is built from HTML div elements (not a raw SVG), with Framer Motion on the flame for state-driven animation:

Flame

A motion.div with w-4 h-8 rounded-[50%_50%_20%_20%] sitting at the top of the candle. When isActive, it gets bg-spell, shadow-[0_0_20px_rgba(45,212,191,0.8)], animate-flicker, and a blur(1px) filter. An inner div (absolute inset-1 bg-white rounded-full blur-[2px] opacity-80) creates the bright inner core of the flame. When inactive, the flame is bg-spell/20 with no shadow.

Wick

A w-0.5 h-3 bg-midnight-darker div sits between the flame and the candle body at z-10, creating the illusion of a physical wick separating the two elements.

Candle Body

A w-10 div with rounded-t-sm and height set by the height prop. Active candles use bg-parchment; inactive candles use bg-parchment/40. Three absolutely positioned inner divs add wax drip texture: a full-width top shadow and two narrow vertical melted-wax channels.

Label

A <span> below the body using font-cinzel text-sm tracking-widest. Active labels are text-spell text-glow; inactive labels are text-parchment/40, brightening to text-parchment/80 on group-hover.
The entire candle is wrapped in a div with cursor-pointer group classes, so hover effects on the label respond to hovering anywhere over the candle assembly.

Usage in Work.js

Three Candle instances are rendered side by side in the Work page timeline. Each is bound to a work history entry via a shared activeId state variable:
import { useState } from 'react';
import { AnimatePresence } from 'framer-motion';
import { C as Candle } from '../components/Candle';

export function Work() {
  const [activeId, setActiveId] = useState(null);

  return (
    <div className="flex gap-12 items-end justify-center">
      <Candle
        label="2023"
        height={140}
        isActive={activeId === 'coven-1'}
        onClick={() => setActiveId('coven-1')}
      />
      <Candle
        label="2021"
        height={100}
        isActive={activeId === 'coven-2'}
        onClick={() => setActiveId('coven-2')}
      />
      <Candle
        label="2019"
        height={70}
        isActive={activeId === 'coven-3'}
        onClick={() => setActiveId('coven-3')}
      />
    </div>
  );
}
When a candle is clicked, setActiveId updates state, toggling the isActive prop on that candle and triggering the flame animation. Below the candle row, a Framer Motion <AnimatePresence> block watches activeId and swaps in the matching job detail panel with an enter/exit transition.

The Flicker Animation

The active flame uses the .animate-flicker CSS class, which is a custom keyframe animation defined in the Tailwind configuration. It makes the flame subtly scale and shift on a randomised loop, simulating the organic movement of a real candle flame.
The animate-flicker class must be defined in your tailwind.config.js under theme.extend.animation and theme.extend.keyframes. If you are setting up the project from scratch, make sure this animation is registered or the active flame will render statically without flickering.

Customizing Heights

The sample work data uses heights of 140, 100, and 70 pixels to represent three roles in descending seniority. These values are entirely aesthetic — choose heights that feel balanced for your own work history.
A good rule of thumb: give the most recent or most senior role the tallest candle, and taper down from there. Avoid heights below 50px — the wax drip decorations inside the candle body need at least 50px of height to render without overlapping the wick. Avoid going above 200px without also adjusting the parent container’s layout, as very tall candles may push the flame off the visible viewport on shorter screens.

Build docs developers (and LLMs) love