storyBook.tsx 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. import {Children, Fragment, ReactNode} from 'react';
  2. import styled from '@emotion/styled';
  3. import SideBySide from 'sentry/components/stories/sideBySide';
  4. import {space} from 'sentry/styles/space';
  5. type RenderFn = () => ReactNode | ReactNode[];
  6. type StoryFn = (storyName: string, storyRender: RenderFn) => void;
  7. type SetupFn = (story: StoryFn) => void;
  8. type Context = {
  9. name: string;
  10. render: RenderFn;
  11. };
  12. export default function storyBook(rootName: string, setup: SetupFn) {
  13. const contexts: Context[] = [];
  14. const storyFn: StoryFn = (name: string, render: RenderFn) => {
  15. contexts.push({name, render});
  16. };
  17. setup(storyFn);
  18. return function RenderStory() {
  19. return (
  20. <Fragment>
  21. {rootName ? <h3>{rootName}</h3> : null}
  22. {contexts.map(({name, render}, i) => {
  23. const children = render();
  24. const isOneChild = Children.count(children) === 1;
  25. const key = `${i}_${name}`;
  26. return (
  27. <Story key={key}>
  28. <StoryTitle id={key}>{name}</StoryTitle>
  29. {isOneChild ? children : <SideBySide>{children}</SideBySide>}
  30. </Story>
  31. );
  32. })}
  33. </Fragment>
  34. );
  35. };
  36. }
  37. const Story = styled('section')`
  38. margin-bottom: ${space(4)};
  39. `;
  40. const StoryTitle = styled('h4')`
  41. border-bottom: 1px solid ${p => p.theme.border};
  42. `;