diff --git a/src/components/RoadmapInMotion.astro b/src/components/RoadmapInMotion.astro new file mode 100644 index 0000000..216c9a4 --- /dev/null +++ b/src/components/RoadmapInMotion.astro @@ -0,0 +1,69 @@ +--- +import type { RoadmapItemWithAttribution } from '../lib/db'; + +interface Props { + items: RoadmapItemWithAttribution[]; +} + +const { items } = Astro.props; + +/** First sentence of a description — naive but matches the user's needs. + * Returns '' for null/empty input. Falls back to a 200-char slice if no + * sentence-ending punctuation is found in a reasonable window. */ +function firstSentenceOf(text: string | null): string { + if (!text) return ''; + const trimmed = text.trim(); + const match = trimmed.match(/^[^.!?]*[.!?](?=\s|$)/); + return match ? match[0] : trimmed.slice(0, 200); +} + +// Most recent shipping item, in display_order (same selection rule as +// the .rr-current marker on the route). +let currentItem: RoadmapItemWithAttribution | null = null; +items.forEach((it) => { if (it.status === 'shipping') currentItem = it; }); + +const line = currentItem ? firstSentenceOf(currentItem.description) : ''; +const visible = !!currentItem && line.length > 0; +--- +{visible && ( +
{line}
+A live picture of the work. What's in motion, what's queued, - what we're still thinking about. Hover any milestone for the - full story. + what we're still thinking about. Tap or hover any milestone + for the full story.