Skip to main content

Documentation Index

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

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

CandleTimeline is the centrepiece of the Work (/work) page. It presents three career history entries arranged vertically in an alternating left-right layout. A central vertical column acts as a wax pillar — as the user scrolls through the timeline, a turquoise gradient “wax melt” fills the column from top to bottom in real time, driven by Framer Motion’s useScroll hook. A flickering candle flame crowns the column at the top. The component takes no props.

Work History Data

Three entries are hardcoded inside the component:
YearTitleCompany
2023 – PresentSenior Alchemist (Frontend)Mystic Tech Corp
2020 – 2023UI SorcererEthereal Agency
2018 – 2020Apprentice DeveloperThe Guild
Entries are spaced space-y-32 (8 rem) apart and alternate left (justify-start) for even indices and right (justify-end) for odd indices. Each occupies w-5/12 of the total width.

Scroll Progress System

CandleTimeline uses Framer Motion’s useScroll with element-scoped tracking:
const ref = useRef(null);
const { scrollYProgress } = useScroll({
  target: ref,
  offset: ["start center", "end center"],
});
scrollYProgress (0 → 1) is transformed into a CSS height percentage string via useTransform:
const candleHeight = useTransform(scrollYProgress, [0, 1], ["0%", "100%"]);
This candleHeight is applied directly to the motion.div column fill via a style prop, so the turquoise wax rises smoothly as the user scrolls — no step-function snapping.

Central Column

The spine of the timeline is a w-4 bg-ink border-x border-turquoise/20 rounded-full overflow-hidden vertical bar centred with left-1/2 -translate-x-1/2. Inside it, the wax-fill motion.div:
style: { height: candleHeight }
className: "absolute top-0 left-0 right-0
            bg-gradient-to-b from-turquoise/80 to-teal/40
            rounded-b-full
            shadow-[0_5px_15px_rgba(64,224,208,0.5)]"

Candle Flame (Top Decoration)

At -top-12 above the column, a flame assembly mirrors the standalone Candle component but is rendered inline:
  • Outer flame: w-4 h-10 bg-amber rounded-[50%_50%_20%_20%] blur-[3px] animate-flicker shadow-[0_0_30px_#FFBF00]
  • Inner flame: w-2 h-6 bg-white rounded-[50%_50%_20%_20%] blur-[1px] animate-flicker
  • Wick: w-1 h-3 bg-ink/80 mt-1

Entry Animation

Each timeline entry uses whileInView so it only animates when it enters the viewport, not on initial page load:
initial:    { opacity: 0, x: isLeft ? -50 : 50 }
whileInView: { opacity: 1, x: 0 }
viewport:   { once: true, margin: "-100px" }
transition: { duration: 0.8, type: "spring" }
Left-side entries slide in from the left; right-side entries from the right.

Entry Layout

Each entry card contains:
year        ←──●──  (connector line + node)
Job Title
Company Name
Description paragraph
  • Yeartext-turquoise font-serif text-sm tracking-widest
  • Titletext-2xl font-serif text-parchment
  • Companytext-sm font-sans text-parchment/60 uppercase tracking-wider
  • Descriptiontext-parchment/80 font-sans text-sm leading-relaxed
The connector line is a w-12 h-0.5 bg-turquoise/30 bar positioned absolutely to the left or right of the card (depending on side), with a w-2 h-2 rounded-full bg-turquoise shadow-[0_0_10px_rgba(64,224,208,0.8)] node at the end touching the central column.
import { CandleTimeline } from './components/CandleTimeline';

// Used directly on the /work page — no props required
<CandleTimeline />
The scroll progress tracks the component element itself (target: ref), not the window, using offset: ["start center", "end center"]. This means the candle begins melting when the top of the timeline reaches the viewport centre, and finishes when the bottom reaches the centre.
Because whileInView entries use once: true, scrolling back up will not re-run their slide-in animations. This prevents the jarring effect of elements constantly appearing and disappearing.

Build docs developers (and LLMs) love