Skip to main content

Style Guide

This is the comprehensive design system and component library for this website. It showcases all design tokens, components, and patterns used throughout the site in both light and dark modes.

Theme toggle is in the header →
Live preview mode

Design Tokens

Color Palette

HSLA Color System

This project uses HSLA (Hue, Saturation, Lightness, Alpha) color format throughout for enhanced maintainability and flexibility.

Key Benefits
  • Better opacity control with alpha channel
  • Intuitive color manipulation (hue, saturation, lightness)
  • Consistent format across all components
  • Enhanced accessibility support
  • Future-proof color system architecture
Usage Example
// Base color
hsla(217, 91%, 60%, 1)

// With transparency
hsla(217, 91%, 60%, 0.5)

// Lighter variant
hsla(217, 91%, 80%, 1)

Note: All color examples below show HSLA values alongside their corresponding TailwindCSS utility classes for easy implementation.

Primary Colors

Light Mode
Background
hsla(0, 0%, 100%, 1)
bg-white
Primary Text
hsla(0, 0%, 0%, 1)
text-black
Muted Text
hsla(0, 0%, 32%, 1)
text-neutral-600
Dark Mode
Background
hsla(0, 0%, 16%, 1)
dark:bg-dark-bg
Primary Text
hsla(0, 0%, 100%, 1)
dark:text-white
Muted Text
hsla(220, 13%, 68%, 1)
dark:text-neutral-400

Neutral Scale

100/900
200/800
300/700
400/600
500

Typography System

Font Family

Inter
Primary font family for all text content. Weights: 300, 400, 500, 600, 700, 800

Headings

Hero Heading
text-6xl md:text-8xl font-bold • textStyles.heading.hero

Heading 1

text-4xl md:text-5xl font-bold • textStyles.heading.h1

Heading 2

text-2xl md:text-3xl font-bold • textStyles.heading.h2

Heading 3

text-xl md:text-2xl font-semibold • textStyles.heading.h3

Heading 4

text-lg md:text-xl font-semibold • textStyles.heading.h4

Body Text

Large body text for important descriptions
text-xl md:text-2xl leading-relaxed • textStyles.body.large
Default body text for general content
text-base leading-relaxed • textStyles.body.default
Small body text for captions and metadata
text-sm leading-relaxed • textStyles.body.small

Text Colors

Primary Text
textStyles.colors.primary
Secondary Text
textStyles.colors.secondary
Muted Text
textStyles.colors.muted
Subtle Text
textStyles.colors.subtle

Spacing & Layout

Container Max Widths

Small (max-w-2xl) • layoutSizes.maxWidth.sm
Medium (max-w-4xl) • layoutSizes.maxWidth.md
Large (max-w-5xl) • layoutSizes.maxWidth.lg

Content Spacing Scale

content-xs (0.5rem / 8px)
content-sm (0.75rem / 12px)
content (1rem / 16px)
content-lg (1.5rem / 24px)
content-xl (2rem / 32px)

Color Token System

Color Token Structure

The color token system provides semantic color definitions that automatically adapt to light and dark themes. These tokens ensure consistent color usage across all components while maintaining proper contrast ratios.

Primary Colors (High Contrast)

Primary Background
colorTokens.primary.background
Primary Text
colorTokens.primary.text
// Usage example
const primaryButton = `
  ${colorTokens.primary.background} 
  ${colorTokens.primary.text}
`;

// Results in:
// bg-black dark:bg-white 
// text-white dark:text-black

Secondary Colors (Muted)

Secondary Background
colorTokens.secondary.background
Secondary Text
colorTokens.secondary.text
// Usage example
const subtleCard = `
  ${colorTokens.secondary.background} 
  ${colorTokens.secondary.text}
`;

// Results in:
// bg-neutral-100 dark:bg-neutral-800 
// text-neutral-700 dark:text-neutral-300

Surface Colors (Cards & Containers)

Surface Background
colorTokens.surface.background
Surface Border
colorTokens.surface.border
// Usage example
const cardStyles = `
  ${colorTokens.surface.background} 
  ${colorTokens.surface.border}
`;

// Results in:
// bg-white dark:bg-black 
// border-neutral-200 dark:border-neutral-800

Text Color Hierarchy

Primary Text - colorTokens.text.primary
text-black dark:text-white
Secondary Text - colorTokens.text.secondary
text-neutral-800 dark:text-neutral-200
Muted Text - colorTokens.text.muted
text-neutral-600 dark:text-neutral-400
Subtle Text - colorTokens.text.subtle
text-neutral-500 dark:text-neutral-500

Color Presets

Color presets provide pre-configured color combinations for specific component contexts, ensuring consistent styling patterns across similar elements.

Available Presets

Default Preset
Heading Text heading
Body Text body
Muted Text muted
colorPresets.default
Hero Preset
Hero Heading heading
Hero Body body
Hero Muted muted
colorPresets.hero

Component Default System

The default system provides automatic color assignment for components when no specific color is provided, ensuring consistent styling while allowing for easy customization when needed.

getComponentDefaults() Function

Default Assignments
heading Primary Text
body Secondary Text
navigation Secondary Text
// Usage with defaults
getComponentDefaults('heading')
// Returns: text-black dark:text-white

getComponentDefaults('body')
// Returns: text-neutral-800 dark:text-neutral-200

Enhanced Utility Functions

getHeadingClasses() with Defaults
Default Heading (auto color)
getHeadingClasses('h2')
Custom Color Heading
getHeadingClasses('h2', 'muted')
getBodyClasses() with Defaults

Default body text (auto color)

getBodyClasses('default')

Custom color body text

getBodyClasses('default', 'muted')

HSLA System Integration

styleUtils HSLA Colors

The hslaColors system in styleUtils.ts provides a comprehensive HSLA color foundation for the project.

Direct HSLA Access
import { hslaColors, getHslaColor } from '../utils/styleUtils';

// Access color values directly
const darkBg = hslaColors.dark.bg;
// Returns: "hsla(0, 0%, 16%, 1)"

// Or use the utility function
const neutralGray = getHslaColor('neutral.500');
// Returns: "hsla(0, 0%, 52%, 1)"
Color Manipulation
import { withOpacity, adjustLightness } from '../utils/styleUtils';

// Create transparent variants
const semiTransparent = withOpacity(
  'hsla(217, 91%, 60%, 1)', 
  0.5
);

// Adjust lightness
const lighter = adjustLightness(
  'hsla(217, 91%, 60%, 1)', 
  80
);

💡 Pro Tip: Use the HSLA system for custom colors and shadows while leveraging TailwindCSS utility classes for standard UI elements.

🎨 CSS Variables: Global dark theme colors in global.css use HSLA format and are accessible via CSS custom properties.

Global CSS HSLA Variables

The following HSLA colors are defined in src/styles/global.css and mirror the styleUtils system:

/* CSS Custom Properties (global.css) */
--color-dark-bg: hsla(0, 0%, 16%, 1);           /* hslaColors.dark.bg */
--color-dark-surface: hsla(215, 16%, 27%, 1);   /* hslaColors.dark.surface */
--color-dark-text: hsla(0, 0%, 100%, 1);        /* hslaColors.dark.text */
--color-dark-text-secondary: hsla(220, 13%, 83%, 1); /* hslaColors.dark.textSecondary */
--color-dark-text-muted: hsla(220, 9%, 66%, 1);     /* hslaColors.dark.textMuted */
--color-dark-border: hsla(215, 16%, 27%, 1);    /* hslaColors.dark.border */

Usage Examples

HSLA Best Practices & Guidelines

✅ Do
  • Use HSLA for custom colors and shadows
  • Leverage the hslaColors system for consistency
  • Use utility functions like withOpacity()
  • Prefer TailwindCSS classes for standard UI elements
  • Document color choices with meaningful variable names
  • Test colors in both light and dark modes
❌ Don't
  • Mix hex, RGB, and HSLA formats in the same component
  • Hardcode color values without using the system
  • Use pure black (#000000) or white (#FFFFFF) - use HSLA variants
  • Forget to handle transparency (alpha channel) properly
  • Ignore accessibility contrast requirements
  • Create colors without testing hover/focus states
Example: Custom Shadow with HSLA
// ✅ Good: Using HSLA system
import { hslaColors, withOpacity } from '../utils/styleUtils';

const customShadow = {
  boxShadow: `0 4px 6px ${withOpacity(hslaColors.shadows.boxLight, 0.1)}`
};

// ❌ Avoid: Hardcoded values
const badShadow = {
  boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)'  // Not consistent with system
};

Direct Token Usage

import { colorTokens } from '../utils/styleUtils';

// Direct token usage
const primaryButton = `
  ${colorTokens.primary.background} 
  ${colorTokens.primary.text}
  ${colorTokens.primary.hover}
`;

// Text hierarchy
const textClasses = `
  ${colorTokens.text.primary}  // Main headings
  ${colorTokens.text.secondary}  // Body text
  ${colorTokens.text.muted}  // Captions, metadata
  ${colorTokens.text.subtle}  // Placeholder text
`;

// Surface elements
const cardClasses = `
  ${colorTokens.surface.background}
  ${colorTokens.surface.border}
  ${colorTokens.surface.hover}
`;

Color Preset Usage

import { colorPresets, getColorPreset } from '../utils/styleUtils';

// Using preset directly
const heroSection = `
  <h1 class="${colorPresets.hero.heading}">
    Hero Title
  </h1>
  <p class="${colorPresets.hero.body}">
    Hero description text
  </p>
`;

// Using getColorPreset function
const cardPreset = getColorPreset('card');
const cardHeading = cardPreset.heading;
const cardBody = cardPreset.body;

Enhanced Functions with Defaults

import { 
  getHeadingClasses, 
  getBodyClasses, 
  getComponentDefaults 
} from '../utils/styleUtils';

// With automatic defaults (recommended)
const heading = getHeadingClasses('h1');
// Returns: text-4xl md:text-5xl font-bold leading-tight text-black dark:text-white

const body = getBodyClasses('default');
// Returns: text-base leading-relaxed text-neutral-800 dark:text-neutral-200

// With custom color override
const mutedHeading = getHeadingClasses('h2', 'muted');
const primaryBody = getBodyClasses('large', 'primary');

// Custom color string
const customHeading = getHeadingClasses('h3', 'text-blue-600');

// Getting defaults manually
const defaultHeadingColor = getComponentDefaults('heading');
const defaultBodyColor = getComponentDefaults('body');

Component Library

Button Patterns

Button Variants

Usage Examples
import { getButtonClasses } from '../utils/styleUtils';

<button class={getButtonClasses('primary')}>
  Primary Action
</button>

<button class={getButtonClasses('secondary')}>
  Secondary Action  
</button>

<button class={getButtonClasses('filter')}>
  Filter Option
</button>

Color Overrides

You can customize button colors by providing color overrides to getButtonClasses():

Color Override Usage
import { getButtonClasses } from '../utils/styleUtils';

// Custom fill color
const blueButton = getButtonClasses('primary', '', {
  fillColor: 'hsla(217, 91%, 60%, 1)'
});

// Custom border and text color  
const greenOutline = getButtonClasses('secondary', '', {
  borderColor: 'hsla(142, 71%, 45%, 1)',
  textColor: 'hsla(142, 71%, 45%, 1)'
});

// Use in template
<button 
  class={blueButton.classes}
  style={blueButton.styles}
>
  Custom Blue Button
</button>

Card Patterns

Blog Post Card

2025-01-11

Sample Blog Post Title

Design

View All Card

Tag Patterns

Topic Tags

Design Coffee Opinion Urban Planning Ideaettes

Filter Buttons

Tag Size Variations

Extra Small Small Medium Large

Tag Style Variations

Default Outlined Minimal Interactive

Layout Components

Hero Component

Sample Hero Title

This demonstrates the hero component with primary and secondary call-to-action buttons.

Two Column Layout

Left Column

This is the left column content. It can contain any content and will automatically adapt to mobile by stacking vertically.

Right Column

This is the right column content. The layout is responsive and maintains consistent spacing across all screen sizes.

Content Block

Sample Content Block

Content blocks provide consistent spacing and typography for sections of content. They support various spacing options and maintain design consistency.

Project Components

Project Hero

Design Project Sep 1, 2025

Sample Project

A demonstration project showing how components work together

Tools & Technologies

Astro TailwindCSS TypeScript

Materials

Web Technologies Design System

Project Links

Project Highlight

This component highlights important aspects of a project with consistent styling and spacing.

Project Insight

Design Decision

Project Outcome

Final Result

Interactive Features

Live Theme Toggle

The theme toggle in the header affects this entire page in real-time, demonstrating how all components adapt to both light and dark modes.

Try switching themes using the toggle in the header to see live changes

Hover States

All interactive elements include hover states that provide visual feedback.

Hover this card
Hover this tag

Focus States

All interactive elements include keyboard-accessible focus states with proper focus rings.

Tip: Use Tab key to navigate through focusable elements and see the focus rings in action.

Usage Guidelines

Component Import Pattern

// Import utilities
import { 
  getButtonClasses, 
  getCardClasses, 
  getTagClasses,
  getHeadingClasses,
  getBodyClasses,
  colorTokens,
  colorPresets,
  getComponentDefaults,
  textStyles,
  layoutSizes 
} from '../utils/styleUtils';

// Import components
import Section from '../components/Section.astro';
import ContentBlock from '../components/ContentBlock.astro';

Accessibility Requirements

  • All interactive elements must be keyboard accessible
  • Focus states are required for all clickable elements
  • Color contrast ratios meet WCAG 2.1 AA standards in both themes
  • Semantic HTML structure is maintained throughout
  • Screen reader friendly markup and ARIA labels where needed

Responsive Design Principles

  • Mobile-first responsive design approach
  • Touch-friendly interactions on mobile devices
  • Consistent spacing and typography across all screen sizes
  • Flexible layouts that adapt to content length
  • Optimized loading performance for all device types

Theme Consistency

  • All components must work seamlessly in both light and dark modes
  • Use semantic color tokens instead of hardcoded colors
  • Maintain proper contrast ratios in both themes
  • Test component visibility and usability in both modes
  • Ensure hover and focus states work in both themes

Color System Best Practices

  • Prefer color tokens over direct TailwindCSS classes for theme compatibility
  • Use colorPresets for consistent component styling patterns
  • Leverage getComponentDefaults() for automatic color assignment
  • Override defaults only when specific design requirements demand it
  • Always test color combinations in both light and dark modes
  • Maintain text contrast ratios above WCAG AA standards (4.5:1)