Portfolio Moderno implements dark mode using Tailwind CSS’sDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/nicolasgrajaleshoyos/portafolio/llms.txt
Use this file to discover all available pages before exploring further.
darkMode: 'class' strategy. Under this approach, dark-variant utility classes (e.g. dark:bg-dark, dark:text-light) only activate when the string "dark" is present as a class on the root <html> element. Adding or removing that class is the sole mechanism that switches the entire visual theme — no CSS variables, no separate stylesheets. The useTheme custom hook in App.tsx is the single owner of this responsibility: it reads the user’s preference on first load, keeps React state and the DOM in sync, and persists the choice to localStorage so it survives page reloads.
Color Tokens
These custom color tokens are defined intailwind.config.js under theme.extend.colors and are available throughout the project as Tailwind utility classes (e.g. bg-primary, text-medium, dark:bg-dark-secondary).
| Token | Value | Usage |
|---|---|---|
primary | #06b6d4 | Cyan 500 — links, highlights, skill badges, CTA button |
primary-hover | #0891b2 | Cyan 600 — hover state on primary elements |
dark | #0f172a | Slate 900 — dark mode page background and Footer background |
dark-secondary | #1e293b | Slate 800 — card and section background in dark mode |
medium | #64748b | Slate 500 — muted body text in light mode |
light | #f1f5f9 | Slate 100 — heading and body text color on dark backgrounds |
Typography
Two Google Fonts families are loaded via the<head> of index.html and mapped to Tailwind’s fontFamily extension in tailwind.config.js:
| Tailwind class | Font family | Role |
|---|---|---|
font-sans | Inter | Body copy, navigation labels, paragraph text |
font-heading | Poppins | Section headings (h1–h3), logo wordmark, card titles |
extend block so they augment — rather than replace — the default font stack, keeping all built-in utilities intact.
Custom Animations
All custom keyframes and theiranimation shorthand utilities are defined in tailwind.config.js under theme.extend. They are used with standard Tailwind animate-* classes in component JSX.
| Name | Duration | Description |
|---|---|---|
fade-in-up | 0.8s | Opacity 0 → 1, translateY(20px) → 0 — general entrance animation |
gradient-shift | 15s | Background position 0% → 100% → 0% — animated Hero background gradient |
blink | 1s | Opacity steps between 1 and 0 — blinking cursor in the typing effect |
tilt | 10s | Rotation 0° → 1° → 0° → −1° → 0° — subtle tilt loop on the glow ring |
float | 6s | translateY(0) → translateY(−10px) → translateY(0) — gentle vertical drift on profile images |
useTheme Hook
The useTheme hook in App.tsx is the single source of truth for the active theme. It uses two useEffect calls with deliberately separate concerns: initialization runs once on mount, and the sync effect re-runs every time theme changes.
- Stored value — if
localStoragecontains a"theme"key set by a previous visit, that value wins. - OS preference — if no stored value exists,
window.matchMedia('(prefers-color-scheme: dark)').matchesis checked. - Default — if neither condition is met,
'light'is used.
The
animate-float and animate-tilt classes on the Hero and About profile images are paired with motion-reduce:animate-none. This Tailwind variant disables those animations automatically for users who have enabled Reduce Motion in their operating system’s accessibility settings, ensuring Portfolio Moderno respects the prefers-reduced-motion media query without any additional JavaScript.