Skip to content

feat(stories): add map stories feature#162

Open
mitoperni wants to merge 16 commits into
developfrom
feat/rangeland-stories-ui
Open

feat(stories): add map stories feature#162
mitoperni wants to merge 16 commits into
developfrom
feat/rangeland-stories-ui

Conversation

@mitoperni

Copy link
Copy Markdown
Contributor

Summary

  • Adds Stories panel at /map/stories with category filter chips, color-variant cards per category, and per-category bordered markers on the map
  • Adds Story detail at /map/story/<slug> that flies the map to the story location keeping current zoom, hides other markers, and pulses the active marker with a category-colored glow — preserves the user's layer and dataset selection across navigation
  • Drives sidebar content from per-route page.tsx files (Datasets, Stories, StoryDetail); the shared shell (Header, Sidebar, Map) lives in app/[locale]/map/layout.tsx so the Mapbox instance stays mounted across navigation
  • Hides the bottom scroll-area fade when scrolled to the end of the list — signals end of content instead of an always-on gradient
  • Surfaces photo credits from Strapi media caption on both card and detail images
  • Drops the unused ?bbox=... URL parameter — never read back into the map and added noise to shared URLs
  • Allows next/image to fetch local-IP upstream in dev only via dangerouslyAllowLocalIP — prod keeps SSRF protection on

Test plan

  • /en/map loads with Datasets panel and no story markers
  • /en/map/stories shows category filter (4 chips) + story list grouped by category, markers visible on map with per-category borders
  • Click a category chip → list narrows; "All stories" chip returns full list
  • Click a story card → URL becomes /en/map/story/<slug>, sidebar swaps to story detail, map flies to the story location keeping current zoom, only that story's marker remains with a category-colored glow
  • Click "← Stories" → sidebar returns to the story list, all markers return
  • Photo credit overlay renders bottom-left on the card image and on the detail image when Strapi media has a caption

@vercel

vercel Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
rangelands-data-platform Ready Ready Preview, Comment May 29, 2026 11:52am

Request Review

@mitoperni mitoperni marked this pull request as ready for review May 29, 2026 11:07
@mitoperni mitoperni requested a review from mbarrenechea May 29, 2026 11:07
notFound();
}
} catch {
notFound();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If for some reason we don't find a story we should have a notFound page that renders on the sidebar instead a full 404 page?

<div className="overflow-hidden">
<div className={cn("flex flex-col gap-2.5 px-8 pb-5 pt-8", variant)}>
{categoryTitle && (
<p className="text-[10px] font-medium uppercase leading-5">{categoryTitle}</p>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A title should use a html tag accordingly


return (
<>
{visibleStories.map((item) => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I always prefer to have a component that render the marker list and another to render the marker. By doing this you can decouple a lot of functionality and keep separate concerns.

Comment thread client/src/lib/cms.ts
@@ -0,0 +1,3 @@
import { env } from "@/env.mjs";

export const CMS_MEDIA_BASE = env.NEXT_PUBLIC_API_URL.replace(/\/api\/?$/, "");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to change the env vars in all environments and remove the /api so we can use it for media uploads or api because is tedius, right?

const imageAttrs = storyAttrs?.image?.data?.attributes;

return (
<Link href={`/map/story/${storySlug}${searchParams}`} className="group block">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is a good idea from the accessibility perspective.

  • Screen readers announce the whole thing as one link. The image alt text, the heading, the body copy, the date, the "read more" — all of it gets concatenated into one enormous link name. Instead of hearing "Article title, link," the user hears a paragraph-long blob. It also breaks heading navigation, which is one of the primary ways screen reader users scan a page.
  • You can't nest interactive elements. An inside an (or a button inside it) is invalid HTML. So the moment your card needs a second link, a tag, or a bookmark button, the pattern falls apart.
  • Text becomes unselectable. Dragging across card text initiates link-drag behavior rather than selection, which annoys everyone and particularly affects people who rely on selecting/copying text

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to split nested components into different files. Everything related to stories list or stories detail in its respective folder. I feel like there is a lot functionality in one component

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants