diff --git a/website/docs/slides/index.mdx b/website/docs/slides/index.mdx index 2a17d10d26..c521738e2a 100644 --- a/website/docs/slides/index.mdx +++ b/website/docs/slides/index.mdx @@ -14,6 +14,13 @@ Browse our collection of presentation slide decks about Atmos and infrastructure { + const parts = text.split(/(`[^`]+`)/g); + return parts.map((part, i) => { + if (part.startsWith('`') && part.endsWith('`')) { + return {part.slice(1, -1)}; + } + return part; + }); +}; + +export const StatusBadge = ({ status }) => { + const badgeClass = status === 'shipped' ? 'slide-badge--shipped' : + status === 'in-progress' ? 'slide-badge--in-progress' : 'slide-badge--planned'; + const label = status === 'shipped' ? 'Shipped' : + status === 'in-progress' ? 'In Progress' : 'Planned'; + return {label}; +}; + +export const StatusIcon = ({ status }) => { + const iconClass = status === 'shipped' ? 'slide-status-icon--shipped' : + status === 'in-progress' ? 'slide-status-icon--in-progress' : 'slide-status-icon--planned'; + const icon = status === 'shipped' ? '✓' : + status === 'in-progress' ? '→' : '○'; + return {icon}; +}; + +export const MilestoneLinks = ({ milestone }) => { + if (!milestone.changelog && !milestone.docs && !milestone.pr) return null; + return ( + + {milestone.changelog && ( + + Announcement + + )} + {milestone.docs && ( + + Docs + + )} + {milestone.pr && ( + + PR #{milestone.pr} + + )} + + ); +}; + +export const ProgressBar = ({ progress }) => ( +
+
+
+
+ {progress}% +
+); + +export const MilestoneList = ({ milestones }) => ( + +); + +export const PaginatedMilestones = ({ milestones, itemsPerPage = 4 }) => { + const [currentPage, setCurrentPage] = useState(0); + const containerRef = useRef(null); + + // Sort: featured first, then shipped, then in-progress, then planned + const sorted = [ + ...milestones.filter(m => m.category === 'featured'), + ...milestones.filter(m => m.category !== 'featured' && m.status === 'shipped'), + ...milestones.filter(m => m.status === 'in-progress' && m.category !== 'featured'), + ...milestones.filter(m => m.status === 'planned' && m.category !== 'featured'), + ].filter((m, i, arr) => arr.findIndex(x => x.label === m.label) === i); // dedupe + + // Chunk into pages + const pages = []; + for (let i = 0; i < sorted.length; i += itemsPerPage) { + pages.push(sorted.slice(i, i + itemsPerPage)); + } + const totalPages = pages.length; + + // Keyboard navigation: Shift+Left/Right when this component is visible + useEffect(() => { + if (totalPages <= 1) return; + const handleKeyDown = (e) => { + if (!e.shiftKey) return; + if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return; + // Only respond if this component is visible (current slide) + const el = containerRef.current; + if (!el || el.offsetParent === null) return; + const rect = el.getBoundingClientRect(); + if (rect.width === 0 || rect.height === 0) return; + // Check if element is in viewport + if (rect.top >= window.innerHeight || rect.bottom <= 0) return; + if (e.key === 'ArrowLeft') { + setCurrentPage(p => Math.max(0, p - 1)); + } else { + setCurrentPage(p => Math.min(totalPages - 1, p + 1)); + } + }; + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [totalPages]); + + if (totalPages === 0) return null; + + return ( +
+ + {totalPages > 1 && ( +
+ {pages.map((_, i) => ( +
+ )} +
+ ); +}; + + + +{/* Slide 1: Title */} + + Atmos Roadmap 2025-2026 + Reducing Tool Fatigue + + Welcome to the Atmos roadmap presentation. This deck covers our vision, + current initiatives, and where we're headed in 2025 and 2026. + + + +{/* Slide 2: Vision */} + + Vision + +

{roadmapConfig.vision}

+
+ + Our vision is to provide one tool that orchestrates your entire infrastructure + lifecycle. As convenient as a PaaS, but as flexible as Terraform, sitting on + top of the tools you already know and love. + +
+ +{/* Slide 3: Theme */} + + {roadmapConfig.theme.title} + +

{roadmapConfig.theme.description}

+
+ + The theme for this roadmap period is reducing tool fatigue. We're taking the sprawl + of infrastructure tooling and bringing it into a cohesive, discoverable, + zero-config experience that works identically whether you're running locally + or in CI. + +
+ +{/* Slide 4: Highlights */} + + Key Achievements +
    + {roadmapConfig.highlights.map((highlight) => ( +
  • + + + {highlight.label}: {highlight.before} → {highlight.after} — {highlight.description} + +
  • + ))} +
+ + Before diving into initiatives, let's highlight some key achievements. + Test coverage went from less than 20% to 74% - a 54% improvement. + We moved from per-PR releases to a predictable weekly release cadence. + And we've consolidated dozens of third-party tools into minimal dependencies. + +
+ +{/* Featured Initiatives Slides */} +{roadmapConfig.featured.map((feature) => { + const initiative = roadmapConfig.initiatives.find(i => i.id === feature.id); + const milestones = initiative?.milestones || []; + + return ( + + + {feature.title} + + + {feature.tagline} + +

{feature.description}

+
+ {milestones.length > 0 && } + + {feature.title}: {feature.description} + {'\n\n'} + Benefits: {feature.benefits} + +
+ ); +})} + +{/* Remaining Initiative Slides (not in featured) */} +{roadmapConfig.initiatives + .filter(initiative => !roadmapConfig.featured.some(f => f.id === initiative.id)) + .map((initiative) => { + return ( + + + {initiative.title} + + + {initiative.tagline} + + +

{initiative.description}

+
+ + + {initiative.title}: {initiative.description} + +
+ ); + })} + +{/* Closing Slide */} + + Get Started with Atmos + atmos.tools + +
+

Documentation: atmos.tools

+

Roadmap: atmos.tools/roadmap

+

GitHub: github.com/cloudposse/atmos

+

Community: cloudposse.com/slack

+
+
+ + Thank you for your interest in Atmos! Visit atmos.tools for documentation, + check out the roadmap to see what's coming, explore our GitHub repository, + and join our Slack community to connect with other users and contributors. + +
+ +
diff --git a/website/src/components/SlideDeck/SlideContent.css b/website/src/components/SlideDeck/SlideContent.css index c3481f1251..d20df46c9b 100644 --- a/website/src/components/SlideDeck/SlideContent.css +++ b/website/src/components/SlideDeck/SlideContent.css @@ -1,3 +1,204 @@ +/* Inline Code in Slides */ +.slide-inline-code { + font-family: var(--ifm-font-family-monospace); + font-size: 0.85em; + padding: 0.15rem 0.4rem; + background: rgba(255, 255, 255, 0.1); + border-radius: 4px; + color: var(--ifm-color-emphasis-700); +} + +html[data-theme='light'] .slide-inline-code { + background: rgba(0, 0, 0, 0.06); + color: var(--ifm-color-emphasis-800); +} + +/* Status Badges */ +.slide-badge { + display: inline-flex; + align-items: center; + font-size: 0.75rem; + font-weight: 600; + padding: 0.2rem 0.6rem; + border-radius: 9999px; + margin-left: 0.5rem; + white-space: nowrap; + vertical-align: middle; + position: relative; + top: -0.15em; +} + +.slide-badge--shipped { + background: rgba(104, 211, 145, 0.2); + color: #68d391; +} + +.slide-badge--in-progress { + background: rgba(83, 140, 233, 0.2); + color: #538ce9; +} + +.slide-badge--planned { + background: rgba(160, 174, 192, 0.2); + color: #a0aec0; +} + +html[data-theme='light'] .slide-badge--shipped { + background: rgba(56, 161, 105, 0.15); + color: #2f855a; +} + +html[data-theme='light'] .slide-badge--in-progress { + background: rgba(30, 91, 184, 0.15); + color: #1e5bb8; +} + +html[data-theme='light'] .slide-badge--planned { + background: rgba(113, 128, 150, 0.15); + color: #4a5568; +} + +/* Link Badges */ +.slide-link-badge { + display: inline-flex; + align-items: center; + font-size: 0.65rem; + font-weight: 500; + padding: 0.1rem 0.4rem; + margin-left: 0.4rem; + border-radius: 4px; + text-decoration: none; + white-space: nowrap; + transition: all 0.2s ease; + background: rgba(83, 140, 233, 0.15); + color: #538ce9; +} + +.slide-link-badge:hover { + background: rgba(83, 140, 233, 0.25); + text-decoration: none; + color: #538ce9; +} + +.slide-link-badge--docs { + background: rgba(104, 211, 145, 0.15); + color: #68d391; +} + +.slide-link-badge--docs:hover { + background: rgba(104, 211, 145, 0.25); + color: #68d391; +} + +html[data-theme='light'] .slide-link-badge { + background: rgba(30, 91, 184, 0.1); + color: #1e5bb8; +} + +html[data-theme='light'] .slide-link-badge:hover { + background: rgba(30, 91, 184, 0.2); + color: #1e5bb8; +} + +html[data-theme='light'] .slide-link-badge--docs { + background: rgba(56, 161, 105, 0.1); + color: #38a169; +} + +html[data-theme='light'] .slide-link-badge--docs:hover { + background: rgba(56, 161, 105, 0.2); + color: #38a169; +} + +/* Milestone List (no bullets, styled checkmarks) */ +.slide-milestone-list { + list-style: none; + padding: 0; + margin: 1rem 0; + text-align: left; +} + +.slide-milestone-list li { + display: flex; + align-items: flex-start; + gap: 0.5rem; + margin-bottom: 0.6rem; + font-size: 1.1rem; + line-height: 1.5; +} + +.slide-milestone-list li:last-child { + margin-bottom: 0; +} + +/* Status Icons */ +.slide-status-icon { + flex-shrink: 0; + font-size: 1rem; + width: 1.25rem; + text-align: center; +} + +.slide-status-icon--shipped { + color: #68d391; +} + +.slide-status-icon--in-progress { + color: #538ce9; +} + +.slide-status-icon--planned { + color: #a0aec0; +} + +html[data-theme='light'] .slide-status-icon--shipped { + color: #38a169; +} + +html[data-theme='light'] .slide-status-icon--in-progress { + color: #1e5bb8; +} + +html[data-theme='light'] .slide-status-icon--planned { + color: #718096; +} + +/* Progress Bar for Slides */ +.slide-progress-bar { + display: flex; + align-items: center; + gap: 0.75rem; + margin: 0.5rem 0 1rem 0; +} + +.slide-progress-bar__track { + flex: 1; + height: 8px; + background: rgba(255, 255, 255, 0.2); + border-radius: 4px; + overflow: hidden; + border: 1px solid rgba(255, 255, 255, 0.15); +} + +.slide-progress-bar__fill { + height: 100%; + background: linear-gradient(90deg, #68d391, #38a169); + border-radius: 4px; + transition: width 0.3s ease; +} + +.slide-progress-bar__label { + font-size: 0.9rem; + font-weight: 600; + color: var(--ifm-color-emphasis-600); + min-width: 3rem; +} + +html[data-theme='light'] .slide-progress-bar__track { + background: rgba(0, 0, 0, 0.1); + border: 1px solid rgba(0, 0, 0, 0.1); +} + /* SlideTitle */ .slide-title { font-size: 2.5rem; @@ -235,6 +436,75 @@ html[data-theme='dark'] .slide-subtitle { } } +/* Pagination Dots */ +.slide-pagination-dots { + display: flex; + justify-content: center; + gap: 0.5rem; + margin-top: 1rem; +} + +.slide-dot { + width: 8px; + height: 8px; + border-radius: 50%; + border: none; + background: rgba(255, 255, 255, 0.3); + cursor: pointer; + transition: all 0.2s ease; + padding: 0; +} + +.slide-dot:hover { + background: rgba(255, 255, 255, 0.5); +} + +.slide-dot--active { + background: #538ce9; + transform: scale(1.2); +} + +html[data-theme='light'] .slide-dot { + background: rgba(0, 0, 0, 0.15); +} + +html[data-theme='light'] .slide-dot:hover { + background: rgba(0, 0, 0, 0.25); +} + +html[data-theme='light'] .slide-dot--active { + background: #1e5bb8; +} + +/* Paginated Milestones Container */ +.slide-paginated-milestones { + position: relative; + min-height: 220px; + padding-bottom: 2rem; + width: 100%; +} + +.slide-paginated-milestones .slide-pagination-dots { + position: absolute; + bottom: 0; + left: 0; + right: 0; + display: flex; + justify-content: center; +} + +/* Keyboard Hint */ +.slide-pagination-hint { + font-size: 0.65rem; + color: rgba(255, 255, 255, 0.5); + margin-left: 0.75rem; + font-family: var(--ifm-font-family-monospace); +} + +html[data-theme='light'] .slide-pagination-hint { + color: rgba(0, 0, 0, 0.4); +} + /* Mobile Portrait Fullscreen - use smaller font sizes for narrow viewports */ @media screen and (max-width: 768px) and (orientation: portrait) { .slide-deck--fullscreen .slide-title { diff --git a/website/src/components/SlideDeck/SlideDeck.tsx b/website/src/components/SlideDeck/SlideDeck.tsx index 19555781de..c45609c931 100644 --- a/website/src/components/SlideDeck/SlideDeck.tsx +++ b/website/src/components/SlideDeck/SlideDeck.tsx @@ -256,10 +256,11 @@ function SlideDeckInner({ } } - if (e.key === 'ArrowRight' || e.key === ' ') { + // Skip arrow navigation when Shift is held (reserved for inner pagination) + if ((e.key === 'ArrowRight' || e.key === ' ') && !e.shiftKey) { e.preventDefault(); nextSlide(); - } else if (e.key === 'ArrowLeft') { + } else if (e.key === 'ArrowLeft' && !e.shiftKey) { e.preventDefault(); prevSlide(); } else if (e.key === 'f' || e.key === 'F') { diff --git a/website/src/components/SlideDeck/SlideIndex.css b/website/src/components/SlideDeck/SlideIndex.css index 1ccfd6a730..28f70a2df6 100644 --- a/website/src/components/SlideDeck/SlideIndex.css +++ b/website/src/components/SlideDeck/SlideIndex.css @@ -68,6 +68,7 @@ html[data-theme='dark'] .slide-index__thumbnail { display: flex; flex-direction: column; gap: 0.5rem; + flex: 1; } .slide-index__card-title { @@ -92,16 +93,30 @@ html[data-theme='dark'] .slide-index__card-description { .slide-index__card-meta { display: flex; align-items: center; - justify-content: space-between; - margin-top: 0.5rem; + margin-top: auto; + padding-top: 0.75rem; + gap: 0.75rem; flex-wrap: wrap; - gap: 0.5rem; } .slide-index__slide-count { font-size: 0.75rem; color: var(--ifm-color-emphasis-600); font-weight: 500; + display: inline-flex; + align-items: center; + gap: 0.25rem; +} + +.slide-index__slide-count::before { + content: ''; + display: inline-block; + width: 14px; + height: 14px; + background: currentColor; + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Crect x='2' y='3' width='20' height='14' rx='2'/%3E%3Cpath d='M8 21h8M12 17v4'/%3E%3C/svg%3E"); + mask-size: contain; + mask-repeat: no-repeat; } /* Tags */ @@ -114,15 +129,15 @@ html[data-theme='dark'] .slide-index__card-description { .slide-index__tag { font-size: 0.6875rem; padding: 0.125rem 0.5rem; - background: var(--ifm-color-primary-lightest); - color: var(--ifm-color-primary-darkest); + background: var(--ifm-color-emphasis-100); + color: var(--ifm-color-emphasis-700); border-radius: 9999px; font-weight: 500; } html[data-theme='dark'] .slide-index__tag { - background: var(--ifm-color-primary-darkest); - color: var(--ifm-color-primary-lightest); + background: var(--ifm-color-emphasis-200); + color: var(--ifm-color-emphasis-500); } /* Responsive */ diff --git a/website/src/data/roadmap.js b/website/src/data/roadmap.js index 4631f67990..e8d90969c7 100644 --- a/website/src/data/roadmap.js +++ b/website/src/data/roadmap.js @@ -22,7 +22,7 @@ export const roadmapConfig = { 'One tool to orchestrate your entire infrastructure lifecycle — as convenient as PaaS, but as flexible as Terraform, sitting on top of the tools you know and love.', theme: { - title: 'From Fragmented to Unified', + title: 'Reducing Tool Fatigue', description: 'Atmos is consolidating the sprawl of infrastructure tooling into a cohesive, discoverable, zero-config experience that works identically locally and in CI.', },