diff --git a/static/app/components/core/button/index.mdx b/static/app/components/core/button/index.mdx index e587d128f4e697..1c7651ef2fe06f 100644 --- a/static/app/components/core/button/index.mdx +++ b/static/app/components/core/button/index.mdx @@ -11,12 +11,6 @@ resources: WCAG 2.4.7: https://www.w3.org/TR/WCAG22/#focus-visible WCAG 2.5.8: https://www.w3.org/TR/WCAG22/#target-size-minimum WAI-ARIA Button Practices: https://www.w3.org/WAI/ARIA/apg/patterns/button/ -next: - link: '/stories/?name=app%2Fcomponents%2Fcore%2Fbutton%2FbuttonBar.stories.tsx' - label: ButtonBar -prev: - link: '?name=app%2Fcomponents%2Fcore%2Fbadge%2Ftag.stories.tsx' - label: Tag --- import {Button} from 'sentry/components/core/button'; diff --git a/static/app/stories/view/storyFooter.tsx b/static/app/stories/view/storyFooter.tsx index a4af4c6b9f32c1..796c7836af2ba6 100644 --- a/static/app/stories/view/storyFooter.tsx +++ b/static/app/stories/view/storyFooter.tsx @@ -1,35 +1,80 @@ import styled from '@emotion/styled'; +import qs from 'query-string'; import {LinkButton} from 'sentry/components/core/button/linkButton'; import {Flex} from 'sentry/components/core/layout'; import {IconArrow} from 'sentry/icons'; -import {isMDXStory} from 'sentry/stories/view/useStoriesLoader'; +import {useStoryBookFilesByCategory} from 'sentry/stories/view/storySidebar'; +import type {StoryTreeNode} from 'sentry/stories/view/storyTree'; +import type {StoryDescriptor} from 'sentry/stories/view/useStoriesLoader'; import {useStory} from 'sentry/stories/view/useStory'; import {space} from 'sentry/styles/space'; +import {useLocation} from 'sentry/utils/useLocation'; export function StoryFooter() { + const location = useLocation(); + const {story} = useStory(); - if (!isMDXStory(story)) return null; - const {prev, next} = story.exports.frontmatter ?? {}; + const categories = useStoryBookFilesByCategory(); + const pagination = findPreviousAndNextStory(story, categories); + + const prevLocationDescriptor = qs.stringify({ + ...location.query, + name: pagination?.prev?.story.filesystemPath, + }); + const nextLocationDescriptor = qs.stringify({ + ...location.query, + name: pagination?.next?.story.filesystemPath, + }); return ( - {typeof prev === 'object' && 'link' in prev && ( - }> + {pagination?.prev && ( + } + > Previous - {prev.label} + {pagination.prev.story.label} )} - {typeof next === 'object' && 'link' in next && ( - }> + {pagination?.next && ( + } + > Next - {next.label} + {pagination.next.story.label} )} ); } +function findPreviousAndNextStory( + story: StoryDescriptor, + categories: ReturnType +): { + next: {category: string; story: StoryTreeNode} | undefined; + prev: {category: string; story: StoryTreeNode} | undefined; +} | null { + const stories = Object.entries(categories).flatMap(([key, category]) => + category.map(s => ({category: key, story: s})) + ); + + const currentIndex = stories.findIndex(s => s.story.filesystemPath === story.filename); + + if (currentIndex === -1) { + return null; + } + + return { + prev: stories[currentIndex - 1] ?? undefined, + next: stories[currentIndex + 1] ?? undefined, + }; +} + const Card = styled(LinkButton)` display: flex; flex-direction: column; diff --git a/static/app/stories/view/storySidebar.tsx b/static/app/stories/view/storySidebar.tsx index b1349a02a64399..a2d3f4d236ed94 100644 --- a/static/app/stories/view/storySidebar.tsx +++ b/static/app/stories/view/storySidebar.tsx @@ -3,6 +3,7 @@ import styled from '@emotion/styled'; import {space} from 'sentry/styles/space'; +import type {StoryTreeNode} from './storyTree'; import {StoryTree, useStoryTree} from './storyTree'; import {useStoryBookFiles} from './useStoriesLoader'; @@ -29,9 +30,13 @@ export function StorySidebar() { ); } -export function useStoryBookFilesByCategory() { +export function useStoryBookFilesByCategory(): Record< + 'foundations' | 'core' | 'shared', + StoryTreeNode[] +> { const files = useStoryBookFiles(); const filesByOwner = useMemo(() => { + // The order of keys here is important and used by the pagination in storyFooter const map: Record<'foundations' | 'core' | 'shared', string[]> = { foundations: [], core: [], diff --git a/static/app/stories/view/useStoriesLoader.tsx b/static/app/stories/view/useStoriesLoader.tsx index 1af8698fe43c78..79ad179f9d84e4 100644 --- a/static/app/stories/view/useStoriesLoader.tsx +++ b/static/app/stories/view/useStoriesLoader.tsx @@ -12,16 +12,12 @@ export interface StoryResources { js?: string; } -type FrontmatterPagination = boolean | {label: string; link: string}; - interface MDXStoryDescriptor { exports: { default: React.ComponentType | any; frontmatter?: { description: string; title: string; - next?: FrontmatterPagination; - prev?: FrontmatterPagination; resources?: StoryResources; source?: string; types?: string;