18 KiB
18 KiB
HarborSmith Design System
Voyage Theme Standard
Version 1.0
Last Updated: December 2024
🎨 Core Design Philosophy
The HarborSmith Voyage theme embodies the spirit of maritime adventure with warm, inviting colors that evoke feelings of sunset voyages and golden horizons. Our design system combines nautical heritage with modern luxury, creating an experience that is both timeless and contemporary.
Design Principles
- Warmth & Welcome - Every element should feel inviting and aspirational
- Maritime Heritage - Subtle nautical references without being cliché
- Premium Experience - Convey luxury through spacing, typography, and imagery
- Emotional Connection - Use warm gradients and cinematic visuals to inspire adventure
- Accessibility - Maintain WCAG AA compliance across all color combinations
🎨 Color Palette
Primary Colors
Classic Nautical (Default Theme)
--primary-blue: #001f3f; /* Deep Navy - Headers, Primary Text */
--warm-orange: #dc143c; /* Crimson Red - CTAs, Accents */
--warm-amber: #b91c3c; /* Deep Crimson - Hover States */
--warm-yellow: #ef4444; /* Coral Red - Highlights */
--soft-cream: #f0f4f8; /* Light Blue-Gray - Backgrounds */
--text-dark: #0a1628; /* Near Black - Body Text */
--text-light: #4a5568; /* Gray - Secondary Text */
--white: #ffffff; /* Pure White - Cards, Contrast */
Gradients
--gradient-warm: linear-gradient(135deg, #dc143c 0%, #ef4444 100%);
--gradient-sunset: linear-gradient(135deg, #b91c3c 0%, #dc143c 50%, #ef4444 100%);
--gradient-ocean: linear-gradient(135deg, #001f3f 0%, #003366 100%);
Semantic Colors
--success: #10B981; /* Emerald Green */
--warning: #F59E0B; /* Amber */
--error: #EF4444; /* Red */
--info: #3B82F6; /* Blue */
Usage Guidelines
- Primary Blue (#001f3f): Main headers, navigation (scrolled state), footer backgrounds
- Warm Orange (#dc143c): Primary CTA buttons, active states, important accents
- Warm Amber (#b91c3c): Hover states for primary actions
- Soft Cream (#f0f4f8): Section backgrounds, alternate row colors
- Gradients: Hero sections, premium features, CTA buttons
📝 Typography
Font Families
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
--font-display: 'Playfair Display', serif;
Type Scale
/* Display - Hero Headlines */
.display-1 {
font-size: clamp(3rem, 8vw, 5rem);
font-family: var(--font-display);
font-weight: 900;
line-height: 1.1;
}
/* Headings */
h1 {
font-size: clamp(2.5rem, 5vw, 3.5rem);
font-family: var(--font-display);
font-weight: 700;
line-height: 1.2;
}
h2 {
font-size: clamp(2rem, 4vw, 2.5rem);
font-family: var(--font-display);
font-weight: 700;
line-height: 1.3;
}
h3 {
font-size: clamp(1.5rem, 3vw, 1.875rem);
font-family: var(--font-sans);
font-weight: 600;
line-height: 1.4;
}
h4 {
font-size: 1.25rem;
font-family: var(--font-sans);
font-weight: 600;
line-height: 1.5;
}
/* Body Text */
.body-large {
font-size: 1.125rem;
line-height: 1.7;
}
.body-regular {
font-size: 1rem;
line-height: 1.6;
}
.body-small {
font-size: 0.875rem;
line-height: 1.5;
}
Typography Usage
- Playfair Display: Hero headlines, section titles, brand name
- Inter: Body text, navigation, buttons, forms
- Font Weights: 300 (light), 400 (regular), 500 (medium), 600 (semibold), 700 (bold), 800 (extrabold), 900 (black)
📐 Spacing System
Base Unit: 8px
--space-xs: 0.5rem; /* 8px */
--space-sm: 1rem; /* 16px */
--space-md: 2rem; /* 32px */
--space-lg: 3rem; /* 48px */
--space-xl: 4rem; /* 64px */
--space-2xl: 6rem; /* 96px */
--space-3xl: 8rem; /* 128px */
Container Widths
--container-sm: 640px;
--container-md: 768px;
--container-lg: 1024px;
--container-xl: 1200px;
--container-2xl: 1400px;
Section Padding
- Mobile:
padding: var(--space-lg) var(--space-md); - Tablet:
padding: var(--space-xl) var(--space-md); - Desktop:
padding: var(--space-2xl) var(--space-md);
🎯 Components
Buttons
Primary Button (Warm Gradient)
.btn-primary {
background: var(--gradient-warm);
color: white;
padding: 0.875rem 2rem;
border-radius: 50px;
font-weight: 600;
font-size: 1rem;
border: none;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px rgba(220, 20, 60, 0.3);
}
Secondary Button (Ghost)
.btn-secondary {
background: transparent;
color: var(--warm-orange);
padding: 0.875rem 2rem;
border: 2px solid var(--warm-orange);
border-radius: 50px;
font-weight: 600;
transition: all 0.3s ease;
}
.btn-secondary:hover {
background: var(--warm-orange);
color: white;
transform: translateY(-2px);
}
Cards
Standard Card
.card {
background: white;
border-radius: 16px;
padding: var(--space-md);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
}
Premium Card (with gradient border)
.card-premium {
background: white;
border-radius: 20px;
padding: 3px;
background: var(--gradient-warm);
}
.card-premium-inner {
background: white;
border-radius: 17px;
padding: var(--space-md);
}
Navigation
Fixed Navigation Bar
.navigation {
position: fixed;
top: 0;
width: 100%;
z-index: 1000;
transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Transparent state (hero) */
.navigation {
background: rgba(255, 255, 255, 0);
backdrop-filter: blur(0);
}
/* Scrolled state */
.navigation.scrolled {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
}
Forms
Input Fields
.form-input {
width: 100%;
padding: 0.875rem 1.25rem;
border: 2px solid #E5E7EB;
border-radius: 12px;
font-size: 1rem;
transition: all 0.3s ease;
}
.form-input:focus {
outline: none;
border-color: var(--warm-orange);
box-shadow: 0 0 0 3px rgba(220, 20, 60, 0.1);
}
Dropdown Menus
// React Component with Framer Motion
// Standard dropdown pattern for consistent interactions across the platform
import { motion, AnimatePresence } from 'framer-motion';
import { ChevronDown } from 'lucide-react';
import { useState } from 'react';
const DropdownMenu = ({
label = "Select Option",
options = [],
value,
onChange,
placeholder = "Choose...",
icon = null
}) => {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="dropdown-container">
<button
className="dropdown-trigger"
onClick={() => setIsOpen(!isOpen)}
aria-expanded={isOpen}
aria-haspopup="listbox"
>
{icon && <span className="dropdown-icon">{icon}</span>}
<span className="dropdown-value">
{value || placeholder}
</span>
<ChevronDown
className={`dropdown-chevron ${isOpen ? 'rotate-180' : ''}`}
size={20}
/>
</button>
<AnimatePresence>
{isOpen && (
<motion.div
className="dropdown-menu"
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.2 }}
>
{options.map((option) => (
<motion.button
key={option.value}
className="dropdown-option"
onClick={() => {
onChange(option);
setIsOpen(false);
}}
whileHover={{ x: 4 }}
transition={{ type: "spring", stiffness: 300 }}
>
{option.icon && (
<span className="option-icon">{option.icon}</span>
)}
<span className="option-label">{option.label}</span>
{option.badge && (
<span className="option-badge">{option.badge}</span>
)}
</motion.button>
))}
</motion.div>
)}
</AnimatePresence>
</div>
);
};
Dropdown Styles (CSS)
.dropdown-container {
position: relative;
width: 100%;
}
.dropdown-trigger {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
padding: 0.875rem 1.25rem;
background: white;
border: 2px solid rgba(220, 20, 60, 0.1);
border-radius: 12px;
font-size: 1rem;
font-weight: 500;
color: #0a1628;
cursor: pointer;
transition: all 0.3s ease;
}
.dropdown-trigger:hover {
border-color: rgba(220, 20, 60, 0.2);
box-shadow: 0 4px 12px rgba(0, 31, 63, 0.08);
}
.dropdown-trigger:focus {
outline: none;
border-color: #dc143c;
box-shadow: 0 0 0 3px rgba(220, 20, 60, 0.1);
}
.dropdown-icon {
display: flex;
align-items: center;
color: #dc143c;
}
.dropdown-value {
flex: 1;
text-align: left;
}
.dropdown-chevron {
color: #64748b;
transition: transform 0.3s ease;
}
.dropdown-chevron.rotate-180 {
transform: rotate(180deg);
}
.dropdown-menu {
position: absolute;
top: calc(100% + 8px);
left: 0;
right: 0;
max-height: 320px;
overflow-y: auto;
background: white;
border: 1px solid rgba(220, 20, 60, 0.08);
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0, 31, 63, 0.12);
z-index: 1000;
}
.dropdown-option {
width: 100%;
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.875rem 1.25rem;
background: transparent;
border: none;
font-size: 0.95rem;
color: #4a5568;
cursor: pointer;
transition: all 0.2s ease;
text-align: left;
}
.dropdown-option:hover {
background: linear-gradient(90deg, rgba(220, 20, 60, 0.05), rgba(239, 68, 68, 0.05));
color: #0a1628;
}
.dropdown-option:focus {
outline: none;
background: rgba(220, 20, 60, 0.08);
}
.option-icon {
display: flex;
align-items: center;
color: #dc143c;
width: 20px;
}
.option-label {
flex: 1;
}
.option-badge {
padding: 0.25rem 0.5rem;
background: linear-gradient(135deg, #dc143c, #ef4444);
color: white;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
}
/* Dark Mode Variant */
.dark .dropdown-trigger {
background: rgba(255, 255, 255, 0.05);
border-color: rgba(255, 255, 255, 0.1);
color: white;
}
.dark .dropdown-menu {
background: #1a1a2e;
border-color: rgba(255, 255, 255, 0.1);
}
.dark .dropdown-option {
color: rgba(255, 255, 255, 0.8);
}
.dark .dropdown-option:hover {
background: rgba(220, 20, 60, 0.2);
color: white;
}
Usage Examples
// Basic Dropdown
<DropdownMenu
label="Select Yacht"
options={[
{ value: 'azure', label: 'Azure Dream' },
{ value: 'seastar', label: 'Sea Star' },
{ value: 'windwhisper', label: 'Wind Whisper' }
]}
value={selectedYacht}
onChange={(option) => setSelectedYacht(option.value)}
/>
// Dropdown with Icons and Badges
<DropdownMenu
label="Choose Route"
icon={<MapPin />}
options={[
{
value: 'golden-gate',
label: 'Golden Gate Tour',
icon: <Bridge />,
badge: 'Popular'
},
{
value: 'alcatraz',
label: 'Alcatraz Circle',
icon: <Anchor />
},
{
value: 'sunset',
label: 'Sunset Cruise',
icon: <Sun />,
badge: 'Romantic'
}
]}
value={selectedRoute}
onChange={(option) => setSelectedRoute(option.value)}
/>
Accessibility Guidelines
- Always include proper ARIA attributes (
aria-expanded,aria-haspopup) - Ensure keyboard navigation works (Tab, Enter, Escape keys)
- Maintain focus management when opening/closing
- Provide clear visual focus indicators
- Support screen readers with semantic HTML
🎬 Animations
Standard Transitions
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
--transition-slow: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
--transition-fast: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
Animation Classes
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-fade-up {
animation: fadeInUp 0.8s ease forwards;
}
.animate-fade-up-delay {
animation: fadeInUp 0.8s ease 0.2s forwards;
opacity: 0;
}
.animate-fade-up-delay-2 {
animation: fadeInUp 0.8s ease 0.4s forwards;
opacity: 0;
}
Hover Effects
- Lift:
transform: translateY(-4px); - Scale:
transform: scale(1.05); - Glow:
box-shadow: 0 10px 30px rgba(220, 20, 60, 0.3);
🖼️ Imagery Guidelines
Hero Images
- Aspect Ratio: 16:9 for desktop, 4:3 for mobile
- Overlay: Dark gradient overlay (40-60% opacity) for text legibility
- Quality: Minimum 1920x1080 for desktop, optimized for web
Content Images
- Border Radius: 16px for standard images, 20px for featured
- Shadow:
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12); - Hover Effect: Scale 1.05 with transition
Image Overlays
.image-overlay {
background: linear-gradient(
to bottom,
rgba(0, 31, 63, 0.3) 0%,
rgba(0, 31, 63, 0.7) 100%
);
}
📱 Responsive Breakpoints
/* Mobile First Approach */
--breakpoint-sm: 640px; /* Small tablets */
--breakpoint-md: 768px; /* Tablets */
--breakpoint-lg: 1024px; /* Small laptops */
--breakpoint-xl: 1280px; /* Desktop */
--breakpoint-2xl: 1536px; /* Large screens */
Media Query Usage
/* Mobile (default) */
.element { }
/* Tablet and up */
@media (min-width: 768px) {
.element { }
}
/* Desktop and up */
@media (min-width: 1024px) {
.element { }
}
🌟 Special Effects
Gradient Text
.gradient-text {
background: var(--gradient-warm);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
Glass Morphism
.glass {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 16px;
}
Warm Glow Effect
.warm-glow {
box-shadow:
0 0 20px rgba(220, 20, 60, 0.1),
0 0 40px rgba(220, 20, 60, 0.05);
}
🎯 Icon System
Lucide Icons Configuration
[data-lucide] {
width: 24px;
height: 24px;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
fill: none;
}
Icon Sizes
- Small: 16px (inline text)
- Default: 24px (buttons, navigation)
- Medium: 32px (feature icons)
- Large: 48px (hero icons)
✅ Accessibility Standards
Color Contrast
- Normal Text: Minimum 4.5:1 contrast ratio
- Large Text: Minimum 3:1 contrast ratio
- Interactive Elements: Minimum 3:1 contrast ratio
Focus States
:focus-visible {
outline: 3px solid var(--warm-orange);
outline-offset: 2px;
border-radius: 4px;
}
Touch Targets
- Minimum size: 44x44px
- Spacing between targets: minimum 8px
🚀 Implementation Checklist
For Each Page
- Use correct color palette variables
- Apply consistent typography scale
- Maintain spacing system
- Include smooth transitions
- Implement hover states
- Ensure mobile responsiveness
- Add proper focus states
- Use semantic HTML
- Include meta descriptions
- Optimize images
Component Consistency
- Buttons match design system
- Forms use standard inputs
- Cards follow shadow/radius standards
- Navigation transitions properly
- Footer matches other pages
- Icons use Lucide consistently
📋 Quick Reference
CSS Variables to Include
<link rel="stylesheet" href="css/voyage-layout.css">
<link rel="stylesheet" href="css/themes.css">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;700;900&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
Standard Page Structure
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Meta tags -->
<!-- Font imports -->
<!-- CSS files -->
</head>
<body>
<!-- Navigation -->
<nav class="voyage-nav">...</nav>
<!-- Hero Section -->
<section class="hero-voyage">...</section>
<!-- Content Sections -->
<section class="section-name">
<div class="container">
<!-- Content -->
</div>
</section>
<!-- Footer -->
<footer class="voyage-footer">...</footer>
<!-- Scripts -->
<script>lucide.createIcons();</script>
</body>
</html>
🔄 Version History
Version 1.0 (December 2024)
- Initial design system documentation
- Voyage theme standardization
- Color palette definition
- Typography scale
- Component library
- Animation guidelines
📝 Notes
This design system is optimized for:
- Modern browsers (Chrome, Firefox, Safari, Edge)
- Mobile-first responsive design
- WCAG AA accessibility standards
- Performance (lazy loading, optimized assets)
- SEO best practices
For questions or updates, contact the HarborSmith development team.