diff --git a/submissions/examples/project-roadmap-timeline/README.md b/submissions/examples/project-roadmap-timeline/README.md new file mode 100644 index 00000000..06d3b42b --- /dev/null +++ b/submissions/examples/project-roadmap-timeline/README.md @@ -0,0 +1,47 @@ +# Project Roadmap Timeline Component + +## 1. What does this do? +Provides a highly responsive, interactive, and visually polished project roadmap timeline component that tracks progress milestones (Completed, In Progress, Upcoming) with glassmorphic cards and spring-bounce animations. + +--- + +## 2. How is it used? +Construct a timeline using the following semantic classes. No JavaScript required. + +```html + +
+ + +
+ + +
+ + + +
+ + +
+ In Progress +

Core Development

+

Milestone details go here.

+ +
+ +
+ +
+``` + +--- + +## 3. Why is it useful? +Roadmaps and progress stepper components are standard for landing pages, product pages, and developer dashboards, but they are difficult to code responsively. + +This component features: +- **Responsive Layout Shifting:** Automatically lays out steps horizontally on desktop viewports (>768px) and switches to vertical layouts on tablets and mobile screens using fluid grid metrics and no JavaScript. +- **High-fidelity Micro-interactions:** Applies a bouncy spring curve (`cubic-bezier(0.34, 1.56, 0.64, 1)`) on card-lifts and dot scaling to match EaseMotion's snappy feel. +- **State-aware Connecting Connectors:** The timeline connecting bar transitions dynamically between states (green for completed, blue-to-gray gradient for in-progress, dark gray for upcoming). +- **Accessibility Audit Compliant:** Employs explicit ARIA role list/listitem annotations, semantic layout tags, keyboard-friendly outline hints, and complete `@media (prefers-reduced-motion: reduce)` resets. diff --git a/submissions/examples/project-roadmap-timeline/demo.html b/submissions/examples/project-roadmap-timeline/demo.html new file mode 100644 index 00000000..7c4610df --- /dev/null +++ b/submissions/examples/project-roadmap-timeline/demo.html @@ -0,0 +1,111 @@ + + + + + + + Project Roadmap Timeline | EaseMotion CSS + + + + + + + + + + + +
+
+ + +
+ DEVELOPMENT PLAN • 2026 +

Project Roadmap

+
+ + +
+ + +
+
+ + + +
+
+ Completed +

Research & Discovery

+

Conducted comprehensive market analysis, user interviews, and competitive audits to outline core requirements.

+ +
+
+ + +
+
+ + + +
+
+ Completed +

Design System

+

Designed design tokens, built component library, and defined interaction guidelines for consistent experiences.

+ +
+
+ + +
+
+ + + +
+
+ In Progress +

Core Development

+

Coding core APIs, state management pipelines, backend integrations, and responsive components.

+ +
+
+ + +
+
+ +
+
+ Upcoming +

Beta Launch

+

Release closed beta testing to early adopters for feedback collection and load stability tuning.

+ +
+
+ + +
+
+ +
+
+ Upcoming +

Public Launch

+

Production deployment, global scale-up, user onboarding tutorial modules, and marketing push.

+ +
+
+ +
+
+
+ + + diff --git a/submissions/examples/project-roadmap-timeline/style.css b/submissions/examples/project-roadmap-timeline/style.css new file mode 100644 index 00000000..0340ef73 --- /dev/null +++ b/submissions/examples/project-roadmap-timeline/style.css @@ -0,0 +1,577 @@ +/* ============================================================ + Project Roadmap Timeline – style.css + Author: open-source contributor + Theme: Obsidian Glass & Neon Progression (EaseMotion CSS style) + ============================================================ */ + +/* ---- Design System Variables & Tokens ---- */ +:root { + /* Fonts */ + --rt-font-sans: 'Outfit', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + --rt-font-mono: 'Courier New', Courier, monospace; + + /* Colors */ + --rt-color-bg: #080a0f; + --rt-color-surface: rgba(17, 22, 34, 0.65); + --rt-color-surface-hover: rgba(22, 29, 45, 0.85); + --rt-color-border: rgba(255, 255, 255, 0.06); + --rt-color-border-hover: rgba(255, 255, 255, 0.15); + + /* Status Colors */ + --rt-color-completed: #10b981; + --rt-color-completed-glow: rgba(16, 185, 129, 0.25); + + --rt-color-active: #3b82f6; + --rt-color-active-glow: rgba(59, 130, 246, 0.35); + + --rt-color-upcoming: #64748b; + --rt-color-upcoming-border: rgba(255, 255, 255, 0.08); + + /* Typography Colors */ + --rt-color-text-primary: #f8fafc; + --rt-color-text-muted: #94a3b8; + --rt-color-text-dark: #64748b; + + /* Transitions & Easings (EaseMotion Bounce Style) */ + --rt-transition-speed: 350ms; + --rt-ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1); + --rt-ease-smooth: cubic-bezier(0.25, 0.8, 0.25, 1); + + /* Shadows & Glows */ + --rt-shadow-glass: 0 8px 32px 0 rgba(0, 0, 0, 0.4); + --rt-shadow-card-hover: 0 12px 40px -10px rgba(0, 0, 0, 0.6); +} + +/* ---- Reset & Page Structure ---- */ +*, +*::before, +*::after { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + background: var(--rt-color-bg); + background-image: + radial-gradient(circle at 10% 20%, rgba(59, 130, 246, 0.05) 0%, transparent 40%), + radial-gradient(circle at 90% 80%, rgba(16, 185, 129, 0.04) 0%, transparent 40%); + font-family: var(--rt-font-sans); + color: var(--rt-color-text-primary); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + overflow-x: hidden; +} + +/* ---- Preview Wrapper ---- */ +.rt-preview { + width: 100%; + max-width: 1200px; + padding: 80px 40px; + display: flex; + justify-content: center; + align-items: center; +} + +/* ---- Main Container ---- */ +.rt-section { + width: 100%; + display: flex; + flex-direction: column; + gap: 60px; +} + +/* ---- Header Section ---- */ +.rt-header { + text-align: center; + display: flex; + flex-direction: column; + gap: 8px; +} + +.rt-heading { + font-size: 32px; + font-weight: 700; + letter-spacing: -0.02em; + background: linear-gradient(135deg, #ffffff 0%, #cbd5e1 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + +.rt-subheading { + font-size: 14px; + font-weight: 600; + color: var(--rt-color-text-dark); + letter-spacing: 0.15em; + text-transform: uppercase; + font-family: var(--rt-font-mono); +} + +/* ---- Timeline Layout (Default Desktop: Horizontal) ---- */ +.rt-timeline { + display: flex; + flex-direction: row; + justify-content: space-between; + gap: 32px; + position: relative; + width: 100%; + padding: 20px 0; +} + +/* ---- Timeline Item ---- */ +.rt-item { + display: flex; + flex-direction: column; + align-items: center; + flex: 1; + min-width: 180px; + position: relative; + + /* Entrance Animation: Slide-up & Fade-in */ + opacity: 0; + transform: translateY(20px); + animation: rtFadeIn 0.7s var(--rt-ease-smooth) forwards; +} + +/* Staggered Delay for Entrance */ +.rt-item:nth-child(1) { animation-delay: 0.1s; } +.rt-item:nth-child(2) { animation-delay: 0.2s; } +.rt-item:nth-child(3) { animation-delay: 0.3s; } +.rt-item:nth-child(4) { animation-delay: 0.4s; } +.rt-item:nth-child(5) { animation-delay: 0.5s; } + +/* ---- Connecting Lines (Desktop: Horizontal) ---- */ +.rt-item:not(:last-child)::after { + content: ""; + position: absolute; + top: 20px; /* Centered with 40px dot */ + left: calc(50% + 20px); /* Radiates from right side of the dot */ + width: calc(100% - 40px + 32px); /* Calculated width across items & gaps */ + height: 3px; + z-index: 1; + transition: all var(--rt-transition-speed) var(--rt-ease-smooth); +} + +/* Connector Line Colors Based on Progression State */ +.rt-item--completed:not(:last-child)::after { + background: var(--rt-color-completed); + box-shadow: 0 0 8px var(--rt-color-completed-glow); +} + +.rt-item--active:not(:last-child)::after { + background: linear-gradient(to right, var(--rt-color-active) 0%, rgba(255, 255, 255, 0.08) 100%); +} + +.rt-item--upcoming:not(:last-child)::after { + background: rgba(255, 255, 255, 0.06); +} + +/* ---- Milestone Marker Column ---- */ +.rt-marker { + position: relative; + display: flex; + justify-content: center; + align-items: center; + height: 40px; + margin-bottom: 28px; + z-index: 2; +} + +/* ---- Timeline Dots ---- */ +.rt-dot { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + border-radius: 50%; + background: #0f131a; + border: 2px solid var(--rt-color-border); + color: var(--rt-color-text-dark); + transition: all var(--rt-transition-speed) var(--rt-ease-bounce); + cursor: pointer; + position: relative; +} + +/* Completed Dot Styling */ +.rt-item--completed .rt-dot { + border-color: var(--rt-color-completed); + background: rgba(16, 185, 129, 0.1); + color: var(--rt-color-completed); +} + +.rt-item--completed .rt-dot:hover { + box-shadow: 0 0 20px var(--rt-color-completed-glow); + transform: scale(1.1); +} + +/* Active / In Progress Dot Styling */ +.rt-item--active .rt-dot { + border-color: var(--rt-color-active); + background: rgba(59, 130, 246, 0.15); + color: var(--rt-color-active); +} + +.rt-item--active .rt-dot:hover { + box-shadow: 0 0 20px var(--rt-color-active-glow); + transform: scale(1.1); +} + +/* Inner dot representation */ +.rt-dot-inner { + width: 10px; + height: 10px; + border-radius: 50%; + background: var(--rt-color-active); +} + +/* Glowing Pulsing rings for Active Item */ +.rt-dot--pulse { + position: relative; +} + +.rt-dot--pulse::before, +.rt-dot--pulse::after { + content: ""; + position: absolute; + top: -2px; + left: -2px; + right: -2px; + bottom: -2px; + border: 2px solid var(--rt-color-active); + border-radius: 50%; + z-index: -1; + opacity: 0; + animation: rtRingPulse 2.5s cubic-bezier(0.24, 0, 0.38, 1) infinite; +} + +.rt-dot--pulse::after { + animation-delay: 1.25s; +} + +/* Upcoming Dot Styling */ +.rt-item--upcoming .rt-dot { + border-color: var(--rt-color-upcoming-border); + background: rgba(255, 255, 255, 0.02); +} + +.rt-item--upcoming .rt-dot::before { + content: ""; + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--rt-color-upcoming); + opacity: 0.4; + transition: opacity var(--rt-transition-speed) var(--rt-ease-smooth); +} + +.rt-item--upcoming .rt-dot:hover::before { + opacity: 0.8; +} + +/* ---- Glassmorphic Cards ---- */ +.rt-card { + width: 100%; + background: var(--rt-color-surface); + border: 1px solid var(--rt-color-border); + border-radius: 18px; + padding: 24px; + display: flex; + flex-direction: column; + gap: 12px; + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); + box-shadow: var(--rt-shadow-glass); + text-align: left; + transition: + transform var(--rt-transition-speed) var(--rt-ease-bounce), + border-color var(--rt-transition-speed) var(--rt-ease-smooth), + box-shadow var(--rt-transition-speed) var(--rt-ease-smooth), + background-color var(--rt-transition-speed) var(--rt-ease-smooth); +} + +/* Card Hover States */ +.rt-card:hover { + transform: translateY(-8px); + border-color: var(--rt-color-border-hover); + box-shadow: var(--rt-shadow-card-hover); + background-color: var(--rt-color-surface-hover); +} + +/* Specific glows for status hover */ +.rt-item--completed .rt-card:hover { + border-color: rgba(16, 185, 129, 0.3); + box-shadow: + 0 12px 40px -10px rgba(0, 0, 0, 0.6), + 0 0 25px rgba(16, 185, 129, 0.05); +} + +.rt-item--active .rt-card:hover { + border-color: rgba(59, 130, 246, 0.4); + box-shadow: + 0 12px 40px -10px rgba(0, 0, 0, 0.6), + 0 0 25px rgba(59, 130, 246, 0.08); +} + +/* ---- Badge Elements ---- */ +.rt-badge { + display: inline-flex; + align-self: flex-start; + padding: 4px 10px; + border-radius: 30px; + font-size: 10px; + font-weight: 700; + letter-spacing: 0.05em; + text-transform: uppercase; + transition: all var(--rt-transition-speed) var(--rt-ease-smooth); +} + +.rt-badge--completed { + background: rgba(16, 185, 129, 0.08); + border: 1px solid rgba(16, 185, 129, 0.15); + color: var(--rt-color-completed); +} + +.rt-card:hover .rt-badge--completed { + background: rgba(16, 185, 129, 0.15); + box-shadow: 0 0 10px rgba(16, 185, 129, 0.15); +} + +.rt-badge--active { + background: rgba(59, 130, 246, 0.08); + border: 1px solid rgba(59, 130, 246, 0.15); + color: var(--rt-color-active); +} + +.rt-card:hover .rt-badge--active { + background: rgba(59, 130, 246, 0.15); + box-shadow: 0 0 10px rgba(59, 130, 246, 0.15); +} + +.rt-badge--upcoming { + background: rgba(255, 255, 255, 0.03); + border: 1px solid rgba(255, 255, 255, 0.05); + color: var(--rt-color-text-dark); +} + +.rt-card:hover .rt-badge--upcoming { + background: rgba(255, 255, 255, 0.06); + color: var(--rt-color-text-muted); +} + +/* ---- Card Contents ---- */ +.rt-title { + font-size: 16px; + font-weight: 600; + letter-spacing: -0.01em; + color: var(--rt-color-text-primary); + transition: color var(--rt-transition-speed) var(--rt-ease-smooth); +} + +.rt-item--upcoming .rt-title { + color: var(--rt-color-text-muted); +} + +.rt-card:hover .rt-title { + color: #ffffff; +} + +.rt-desc { + font-size: 13px; + line-height: 1.6; + color: var(--rt-color-text-muted); + transition: color var(--rt-transition-speed) var(--rt-ease-smooth); +} + +.rt-item--upcoming .rt-desc { + color: var(--rt-color-text-dark); +} + +.rt-card:hover .rt-desc { + color: #e2e8f0; +} + +.rt-date { + font-size: 11px; + font-family: var(--rt-font-mono); + font-weight: 500; + color: var(--rt-color-text-dark); + letter-spacing: 0.05em; + text-transform: uppercase; + margin-top: 4px; + transition: color var(--rt-transition-speed) var(--rt-ease-smooth); +} + +.rt-card:hover .rt-date { + color: var(--rt-color-text-muted); +} + +/* ============================================================ + RESPONSIVE DESIGN (Breakpoint: Tablets / Mobile - Vertical Flow) + ============================================================ */ +@media (max-width: 900px) { + .rt-preview { + padding: 60px 24px; + } +} + +@media (max-width: 768px) { + /* Shift timeline container from horizontal flex to vertical block */ + .rt-timeline { + flex-direction: column; + gap: 0; + padding-left: 20px; + } + + /* Adjust timeline item structure for vertical stacking */ + .rt-item { + flex-direction: row; + align-items: flex-start; + gap: 24px; + padding-bottom: 40px; + width: 100%; + transform: translateX(-15px); /* slide sideways for vertical fade-in style */ + animation: rtFadeInVertical 0.7s var(--rt-ease-smooth) forwards; + } + + .rt-item:last-child { + padding-bottom: 0; + } + + /* ---- Connecting Lines (Mobile: Vertical) ---- */ + .rt-item:not(:last-child)::after { + top: 40px; /* Starts directly below the 40px dot */ + left: 20px; /* Centered inside the 40px dot */ + width: 3px; + height: calc(100% - 40px); /* Fills vertical space to the next item */ + } + + .rt-item--active:not(:last-child)::after { + background: linear-gradient(to bottom, var(--rt-color-active) 0%, rgba(255, 255, 255, 0.08) 100%); + } + + /* Marker configuration for vertical alignment */ + .rt-marker { + margin-bottom: 0; + height: auto; + width: 40px; + flex-shrink: 0; + } + + .rt-card { + padding: 20px; + } + + /* Shift card hover animation to side shift instead of lift to prevent vertical overlaps */ + .rt-card:hover { + transform: translateX(6px); + } +} + +@media (max-width: 480px) { + .rt-preview { + padding: 40px 16px; + } + + .rt-item { + gap: 16px; + padding-bottom: 32px; + } + + .rt-dot { + width: 32px; + height: 32px; + } + + .rt-marker { + width: 32px; + } + + .rt-item:not(:last-child)::after { + top: 32px; + left: 16px; + height: calc(100% - 32px); + } + + .rt-card { + padding: 16px; + border-radius: 14px; + } + + .rt-heading { + font-size: 26px; + } + + .rt-subheading { + font-size: 12px; + } +} + +/* ============================================================ + ANIMATION KEYFRAMES + ============================================================ */ + +/* Entrance Fade-in / Rise (Desktop) */ +@keyframes rtFadeIn { + 0% { + opacity: 0; + transform: translateY(24px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + +/* Entrance Fade-in / Slide-right (Mobile) */ +@keyframes rtFadeInVertical { + 0% { + opacity: 0; + transform: translateX(-15px); + } + 100% { + opacity: 1; + transform: translateX(0); + } +} + +/* Active Ring Pulse Animation */ +@keyframes rtRingPulse { + 0% { + transform: scale(1); + opacity: 0.6; + } + 50% { + opacity: 0; + } + 100% { + transform: scale(1.6); + opacity: 0; + } +} + +/* ============================================================ + ACCESSIBILITY: PREFERS REDUCED MOTION OVERRIDES + ============================================================ */ +@media (prefers-reduced-motion: reduce) { + .rt-item, + .rt-card, + .rt-dot, + .rt-dot--pulse::before, + .rt-dot--pulse::after, + .rt-badge { + animation: none !important; + transition: none !important; + transform: none !important; + box-shadow: none !important; + } + + .rt-dot--pulse::before { + opacity: 0.5; + transform: scale(1.2) !important; + } +}