|
1 | 1 | import styled from '@emotion/styled';
|
| 2 | +import qs from 'query-string'; |
2 | 3 |
|
3 | 4 | import {LinkButton} from 'sentry/components/core/button/linkButton';
|
4 | 5 | import {Flex} from 'sentry/components/core/layout';
|
5 | 6 | import {IconArrow} from 'sentry/icons';
|
6 |
| -import {isMDXStory} from 'sentry/stories/view/useStoriesLoader'; |
| 7 | +import {useStoryBookFilesByCategory} from 'sentry/stories/view/storySidebar'; |
| 8 | +import type {StoryTreeNode} from 'sentry/stories/view/storyTree'; |
| 9 | +import type {StoryDescriptor} from 'sentry/stories/view/useStoriesLoader'; |
7 | 10 | import {useStory} from 'sentry/stories/view/useStory';
|
8 | 11 | import {space} from 'sentry/styles/space';
|
| 12 | +import {useLocation} from 'sentry/utils/useLocation'; |
9 | 13 |
|
10 | 14 | export function StoryFooter() {
|
| 15 | + const location = useLocation(); |
| 16 | + |
11 | 17 | const {story} = useStory();
|
12 |
| - if (!isMDXStory(story)) return null; |
13 |
| - const {prev, next} = story.exports.frontmatter ?? {}; |
| 18 | + const categories = useStoryBookFilesByCategory(); |
| 19 | + const pagination = findPreviousAndNextStory(story, categories); |
| 20 | + |
| 21 | + const prevLocationDescriptor = qs.stringify({ |
| 22 | + ...location.query, |
| 23 | + name: pagination?.prev?.story.filesystemPath, |
| 24 | + }); |
| 25 | + const nextLocationDescriptor = qs.stringify({ |
| 26 | + ...location.query, |
| 27 | + name: pagination?.next?.story.filesystemPath, |
| 28 | + }); |
14 | 29 |
|
15 | 30 | return (
|
16 | 31 | <Flex align="center" justify="space-between" gap={space(2)}>
|
17 |
| - {typeof prev === 'object' && 'link' in prev && ( |
18 |
| - <Card to={prev.link} icon={<IconArrow direction="left" />}> |
| 32 | + {pagination?.prev && ( |
| 33 | + <Card |
| 34 | + to={`/stories/?${prevLocationDescriptor}`} |
| 35 | + icon={<IconArrow direction="left" />} |
| 36 | + > |
19 | 37 | <CardLabel>Previous</CardLabel>
|
20 |
| - <CardTitle>{prev.label}</CardTitle> |
| 38 | + <CardTitle>{pagination.prev.story.label}</CardTitle> |
21 | 39 | </Card>
|
22 | 40 | )}
|
23 |
| - {typeof next === 'object' && 'link' in next && ( |
24 |
| - <Card data-flip to={next.link} icon={<IconArrow direction="right" />}> |
| 41 | + {pagination?.next && ( |
| 42 | + <Card |
| 43 | + data-flip |
| 44 | + to={`/stories/?${nextLocationDescriptor}`} |
| 45 | + icon={<IconArrow direction="right" />} |
| 46 | + > |
25 | 47 | <CardLabel>Next</CardLabel>
|
26 |
| - <CardTitle>{next.label}</CardTitle> |
| 48 | + <CardTitle>{pagination.next.story.label}</CardTitle> |
27 | 49 | </Card>
|
28 | 50 | )}
|
29 | 51 | </Flex>
|
30 | 52 | );
|
31 | 53 | }
|
32 | 54 |
|
| 55 | +function findPreviousAndNextStory( |
| 56 | + story: StoryDescriptor, |
| 57 | + categories: ReturnType<typeof useStoryBookFilesByCategory> |
| 58 | +): { |
| 59 | + next: {category: string; story: StoryTreeNode} | undefined; |
| 60 | + prev: {category: string; story: StoryTreeNode} | undefined; |
| 61 | +} | null { |
| 62 | + const stories = Object.entries(categories).flatMap(([key, category]) => |
| 63 | + category.map(s => ({category: key, story: s})) |
| 64 | + ); |
| 65 | + |
| 66 | + const currentIndex = stories.findIndex(s => s.story.filesystemPath === story.filename); |
| 67 | + |
| 68 | + if (currentIndex === -1) { |
| 69 | + return null; |
| 70 | + } |
| 71 | + |
| 72 | + return { |
| 73 | + prev: stories[currentIndex - 1] ?? undefined, |
| 74 | + next: stories[currentIndex + 1] ?? undefined, |
| 75 | + }; |
| 76 | +} |
| 77 | + |
33 | 78 | const Card = styled(LinkButton)`
|
34 | 79 | display: flex;
|
35 | 80 | flex-direction: column;
|
|
0 commit comments