Browse Source

feat: Story titles can come straight from the imported component (#56815)

Ryan Albrecht 1 year ago
parent
commit
f830509dd7

+ 1 - 1
static/app/components/badge.stories.tsx

@@ -2,7 +2,7 @@ import Badge from 'sentry/components/badge';
 import SideBySide from 'sentry/components/stories/sideBySide';
 import SideBySide from 'sentry/components/stories/sideBySide';
 import storyBook from 'sentry/stories/storyBook';
 import storyBook from 'sentry/stories/storyBook';
 
 
-export default storyBook('Badge', story => {
+export default storyBook(Badge, story => {
   story('Default', () => (
   story('Default', () => (
     <SideBySide>
     <SideBySide>
       <Badge text="Text Prop" />
       <Badge text="Text Prop" />

+ 1 - 1
static/app/components/container/negativeSpaceContainer.stories.tsx

@@ -6,7 +6,7 @@ import onboardingFrameworkSelectionJavascript from 'sentry-images/spot/onboardin
 import NegativeSpaceContainer from 'sentry/components/container/negativeSpaceContainer';
 import NegativeSpaceContainer from 'sentry/components/container/negativeSpaceContainer';
 import storyBook from 'sentry/stories/storyBook';
 import storyBook from 'sentry/stories/storyBook';
 
 
-export default storyBook('NegativeSpaceContainer', story => {
+export default storyBook(NegativeSpaceContainer, story => {
   story('Empty', () => (
   story('Empty', () => (
     <Fragment>
     <Fragment>
       <p>
       <p>

+ 1 - 1
static/app/components/featureBadge.stories.tsx

@@ -5,7 +5,7 @@ import Matrix from 'sentry/components/stories/matrix';
 import SideBySide from 'sentry/components/stories/sideBySide';
 import SideBySide from 'sentry/components/stories/sideBySide';
 import storyBook from 'sentry/stories/storyBook';
 import storyBook from 'sentry/stories/storyBook';
 
 
-export default storyBook('FeatureBadge', story => {
+export default storyBook(FeatureBadge, story => {
   story('Types', () => (
   story('Types', () => (
     <SideBySide>
     <SideBySide>
       <FeatureBadge type="alpha" />
       <FeatureBadge type="alpha" />

+ 1 - 1
static/app/components/loadingTriangle.stories.tsx

@@ -2,7 +2,7 @@ import LoadingTriangle from 'sentry/components/loadingTriangle';
 import SizingWindow from 'sentry/components/stories/sizingWindow';
 import SizingWindow from 'sentry/components/stories/sizingWindow';
 import storyBook from 'sentry/stories/storyBook';
 import storyBook from 'sentry/stories/storyBook';
 
 
-export default storyBook('LogoSentry', story => {
+export default storyBook(LoadingTriangle, story => {
   story('Default', () => (
   story('Default', () => (
     <SizingWindow style={{height: '150px'}}>
     <SizingWindow style={{height: '150px'}}>
       <LoadingTriangle />
       <LoadingTriangle />

+ 1 - 1
static/app/components/logoSentry.stories.tsx

@@ -2,7 +2,7 @@ import LogoSentry from 'sentry/components/logoSentry';
 import SizingWindow from 'sentry/components/stories/sizingWindow';
 import SizingWindow from 'sentry/components/stories/sizingWindow';
 import storyBook from 'sentry/stories/storyBook';
 import storyBook from 'sentry/stories/storyBook';
 
 
-export default storyBook('LogoSentry', story => {
+export default storyBook(LogoSentry, story => {
   story('Default', () => (
   story('Default', () => (
     <SizingWindow>
     <SizingWindow>
       <LogoSentry />
       <LogoSentry />

+ 1 - 1
static/app/components/replays/pageBanner.stories.tsx

@@ -10,7 +10,7 @@ import SizingWindow from 'sentry/components/stories/sizingWindow';
 import {IconBroadcast} from 'sentry/icons';
 import {IconBroadcast} from 'sentry/icons';
 import storyBook from 'sentry/stories/storyBook';
 import storyBook from 'sentry/stories/storyBook';
 
 
-export default storyBook('PageBanner', story => {
+export default storyBook(PageBanner, story => {
   const storiesButton = (
   const storiesButton = (
     <LinkButton
     <LinkButton
       external
       external

+ 1 - 1
static/app/components/tabs/index.stories.tsx

@@ -7,7 +7,7 @@ import SizingWindow from 'sentry/components/stories/sizingWindow';
 import {TabList, TabPanels, Tabs} from 'sentry/components/tabs';
 import {TabList, TabPanels, Tabs} from 'sentry/components/tabs';
 import storyBook from 'sentry/stories/storyBook';
 import storyBook from 'sentry/stories/storyBook';
 
 
-export default storyBook('Tabs', story => {
+export default storyBook(Tabs, story => {
   const TABS = [
   const TABS = [
     {key: 'one', label: 'One', content: 'This is the first Panel.'},
     {key: 'one', label: 'One', content: 'This is the first Panel.'},
     {key: 'two', label: 'Two', content: 'This is the second panel'},
     {key: 'two', label: 'Two', content: 'This is the second panel'},

+ 32 - 7
static/app/stories/storyBook.tsx

@@ -1,6 +1,7 @@
-import {Children, Fragment, ReactNode} from 'react';
+import {Children, JSXElementConstructor, ReactNode} from 'react';
 import styled from '@emotion/styled';
 import styled from '@emotion/styled';
 
 
+import {Flex} from 'sentry/components/profiling/flex';
 import SideBySide from 'sentry/components/stories/sideBySide';
 import SideBySide from 'sentry/components/stories/sideBySide';
 import {space} from 'sentry/styles/space';
 import {space} from 'sentry/styles/space';
 
 
@@ -13,7 +14,10 @@ type Context = {
   render: RenderFn;
   render: RenderFn;
 };
 };
 
 
-export default function storyBook(rootName: string, setup: SetupFn) {
+export default function storyBook(
+  bookContext: string | JSXElementConstructor<any>,
+  setup: SetupFn
+) {
   const contexts: Context[] = [];
   const contexts: Context[] = [];
 
 
   const storyFn: StoryFn = (name: string, render: RenderFn) => {
   const storyFn: StoryFn = (name: string, render: RenderFn) => {
@@ -24,8 +28,8 @@ export default function storyBook(rootName: string, setup: SetupFn) {
 
 
   return function RenderStory() {
   return function RenderStory() {
     return (
     return (
-      <Fragment>
-        {rootName ? <h3>{rootName}</h3> : null}
+      <Flex column gap={space(4)}>
+        <BookHeading bookContext={bookContext} />
         {contexts.map(({name, render}, i) => {
         {contexts.map(({name, render}, i) => {
           const children = render();
           const children = render();
           const isOneChild = Children.count(children) === 1;
           const isOneChild = Children.count(children) === 1;
@@ -38,14 +42,35 @@ export default function storyBook(rootName: string, setup: SetupFn) {
             </Story>
             </Story>
           );
           );
         })}
         })}
-      </Fragment>
+      </Flex>
     );
     );
   };
   };
 }
 }
 
 
-const Story = styled('section')`
-  margin-bottom: ${space(4)};
+function BookHeading({bookContext}) {
+  if (typeof bookContext === 'string') {
+    return <BookTitle>{bookContext}</BookTitle>;
+  }
+
+  const componentName =
+    bookContext.displayName ?? bookContext.name ?? bookContext.constructor.name;
+
+  if (!componentName) {
+    return null;
+  }
 
 
+  return (
+    <BookTitle>
+      <code>{`<${componentName}/>`}</code>
+    </BookTitle>
+  );
+}
+
+const BookTitle = styled('h3')`
+  margin: 0;
+`;
+
+const Story = styled('section')`
   & > p {
   & > p {
     margin: ${space(3)} 0;
     margin: ${space(3)} 0;
   }
   }

+ 7 - 0
static/app/views/stories/useStoriesLoader.tsx

@@ -39,16 +39,23 @@ export default function useStoriesLoader({filename}: Props) {
       return;
       return;
     }
     }
     try {
     try {
+      setMod({
+        error: undefined,
+        filename,
+        resolved: undefined,
+      });
       const resolved = await storiesContext().importStory(filename);
       const resolved = await storiesContext().importStory(filename);
       setMod({
       setMod({
         error: undefined,
         error: undefined,
         filename,
         filename,
+
         resolved,
         resolved,
       });
       });
     } catch (error) {
     } catch (error) {
       setMod({
       setMod({
         error,
         error,
         filename,
         filename,
+
         resolved: undefined,
         resolved: undefined,
       });
       });
     }
     }