From 3ed612083637a74ede780625914b0ba081f28d0a Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Thu, 13 Feb 2025 16:32:29 +0100 Subject: [PATCH 01/28] feat(storybook): implement argTypeEnhancers for nice UX for Slot API rendering --- .storybook/preview.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.storybook/preview.js b/.storybook/preview.js index 537bdd7f719136..ce0cd326b1d739 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -35,3 +35,29 @@ export const parameters = { }, }, }; + +const slotRegex = /as\?:\s*"([^"]+)"/; + +/** + * + * @param {import('@storybook/types').StoryContextForEnhancers} context + */ +const withSlotEnhancer = context => { + const updatedArgTypes = { ...context.argTypes }; + + Object.entries(updatedArgTypes).forEach(([key, argType]) => { + // @ts-expect-error - storybook doesn't ship these types + const value = argType?.type?.value; + + if (value && typeof value === 'string') { + const match = value.match(slotRegex); + if (match) { + updatedArgTypes[key].table.type.summary = `Slot<'${match[1]}'>`; + } + } + }); + + return updatedArgTypes; +}; + +export const argTypesEnhancers = [withSlotEnhancer]; From 302f4958465a53620c09ad714b0f2e4c4689e0b3 Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Thu, 13 Feb 2025 16:34:07 +0100 Subject: [PATCH 02/28] feat(react-card-stories): use argTypeEnhancer for rendering --- .../react-components/react-card/stories/.storybook/preview.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/react-components/react-card/stories/.storybook/preview.js b/packages/react-components/react-card/stories/.storybook/preview.js index 94455f782364e4..fa91f82fbd1a3e 100644 --- a/packages/react-components/react-card/stories/.storybook/preview.js +++ b/packages/react-components/react-card/stories/.storybook/preview.js @@ -5,3 +5,5 @@ export const decorators = [...rootPreview.decorators]; /** @type {typeof rootPreview.parameters} */ export const parameters = { ...rootPreview.parameters }; + +export const argTypesEnhancers = [...rootPreview.argTypesEnhancers]; From 1d49538d63ddc3d929b28223eb8044c5822409b8 Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Thu, 13 Feb 2025 19:05:55 +0100 Subject: [PATCH 03/28] fixup! feat(storybook): implement argTypeEnhancers for nice UX for Slot API rendering --- .storybook/preview.js | 26 ----------------- apps/public-docsite-v9/.storybook/preview.js | 30 ++++++++++++++++++++ 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/.storybook/preview.js b/.storybook/preview.js index ce0cd326b1d739..537bdd7f719136 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -35,29 +35,3 @@ export const parameters = { }, }, }; - -const slotRegex = /as\?:\s*"([^"]+)"/; - -/** - * - * @param {import('@storybook/types').StoryContextForEnhancers} context - */ -const withSlotEnhancer = context => { - const updatedArgTypes = { ...context.argTypes }; - - Object.entries(updatedArgTypes).forEach(([key, argType]) => { - // @ts-expect-error - storybook doesn't ship these types - const value = argType?.type?.value; - - if (value && typeof value === 'string') { - const match = value.match(slotRegex); - if (match) { - updatedArgTypes[key].table.type.summary = `Slot<'${match[1]}'>`; - } - } - }); - - return updatedArgTypes; -}; - -export const argTypesEnhancers = [withSlotEnhancer]; diff --git a/apps/public-docsite-v9/.storybook/preview.js b/apps/public-docsite-v9/.storybook/preview.js index 461d1c131c4103..f18f691afed091 100644 --- a/apps/public-docsite-v9/.storybook/preview.js +++ b/apps/public-docsite-v9/.storybook/preview.js @@ -59,3 +59,33 @@ export const parameters = { }, }, }; + +const slotRegex = /as\?:\s*"([^"]+)"/; + +/** + * + * @type {import('@storybook/types').ArgTypesEnhancer} + */ +const withSlotEnhancer = context => { + const updatedArgTypes = { ...context.argTypes }; + + Object.entries(updatedArgTypes).forEach(([key, argType]) => { + // @ts-expect-error - storybook doesn't ship proper types + const value = argType?.type?.value; + + // we are interested only on raw strings ( which is case of non Storybook supported types) + if (value && typeof value === 'string') { + const match = value.match(slotRegex); + if (match) { + updatedArgTypes[key].table.type.summary = `Slot<'${match[1]}'>`; + } + } + }); + + return updatedArgTypes; +}; + +/** + * @type {import('@storybook/types').ArgTypesEnhancer[]} + */ +export const argTypesEnhancers = [withSlotEnhancer]; From 151ad36f87e60e93f077503e413783991e131e1f Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Thu, 13 Feb 2025 19:21:54 +0100 Subject: [PATCH 04/28] Revert "feat(react-card-stories): use argTypeEnhancer for rendering" This reverts commit 302f4958465a53620c09ad714b0f2e4c4689e0b3. --- .../react-components/react-card/stories/.storybook/preview.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/react-components/react-card/stories/.storybook/preview.js b/packages/react-components/react-card/stories/.storybook/preview.js index fa91f82fbd1a3e..94455f782364e4 100644 --- a/packages/react-components/react-card/stories/.storybook/preview.js +++ b/packages/react-components/react-card/stories/.storybook/preview.js @@ -5,5 +5,3 @@ export const decorators = [...rootPreview.decorators]; /** @type {typeof rootPreview.parameters} */ export const parameters = { ...rootPreview.parameters }; - -export const argTypesEnhancers = [...rootPreview.argTypesEnhancers]; From 2bc520b74f2d733a5b567fe0a625a4d6a602aaac Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Thu, 13 Feb 2025 19:22:45 +0100 Subject: [PATCH 05/28] fixup! fixup! feat(storybook): implement argTypeEnhancers for nice UX for Slot API rendering --- apps/public-docsite-v9/.storybook/preview.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/public-docsite-v9/.storybook/preview.js b/apps/public-docsite-v9/.storybook/preview.js index f18f691afed091..892a4cecf45bde 100644 --- a/apps/public-docsite-v9/.storybook/preview.js +++ b/apps/public-docsite-v9/.storybook/preview.js @@ -77,7 +77,7 @@ const withSlotEnhancer = context => { if (value && typeof value === 'string') { const match = value.match(slotRegex); if (match) { - updatedArgTypes[key].table.type.summary = `Slot<'${match[1]}'>`; + updatedArgTypes[key].table.type.summary = `Slot<\"${match[1]}\">`; } } }); From 1f2d51fccf0d09ef1cec6c8be58f0cb92357df7b Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Thu, 13 Feb 2025 20:06:20 +0100 Subject: [PATCH 06/28] feat: apply enhancer internallly within custom DocPage --- .../DocsComponents/FluentDocsPage.stories.tsx | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 7313f5f22f428d..bf50f83253e7cd 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -10,7 +10,7 @@ import { Stories, type DocsContextProps, } from '@storybook/addon-docs'; -import type { PreparedStory, Renderer } from '@storybook/types'; +import type { PreparedStory, Renderer, StrictArgTypes, StoryContextForEnhancers } from '@storybook/types'; import type { SBEnumType } from '@storybook/csf'; import { makeStyles, shorthands, tokens, Link, Text } from '@fluentui/react-components'; import { InfoFilled } from '@fluentui/react-icons'; @@ -133,11 +133,41 @@ const getNativeElementsList = (elements: SBEnumType['value']): JSX.Element => { ); }; -const RenderArgsTable = ({ hideArgsTable, primaryStory }: { primaryStory: PrimaryStory; hideArgsTable: boolean }) => { +const slotRegex = /as\?:\s*"([^"]+)"/; +function withSlotEnhancer(story: PreparedStory) { + const docGenProps = story.component?.__docgenInfo?.props; + + if (!docGenProps) { + return story; + } + + Object.entries(docGenProps).forEach(([key, argType]) => { + const value: string = argType?.type?.name; + const match = value.match(slotRegex); + + if (Array.isArray(match)) { + story.component.__docgenInfo.props[key].type.name = `Slot<\"${match[1]}\">`; + } + }); + + return story; +} + +const RenderArgsTable = ({ + hideArgsTable, + primaryStory, + argsTypes, +}: { + primaryStory: PrimaryStory; + hideArgsTable: boolean; + argsTypes: StrictArgTypes; +}) => { const styles = useStyles(); + return hideArgsTable ? null : ( <> + {primaryStory.argTypes.as && primaryStory.argTypes.as?.type?.name === 'enum' && (
@@ -179,6 +209,7 @@ const RenderPrimaryStory = ({ export const FluentDocsPage = () => { const context = React.useContext(DocsContext); const stories = context.componentStories(); + const primaryStory = stories[0]; const primaryStoryContext = context.getStoryContext(primaryStory); @@ -204,6 +235,8 @@ export const FluentDocsPage = () => { // })), // ); + const TweakedComponent = withSlotEnhancer(primaryStory); + return (
@@ -219,7 +252,11 @@ export const FluentDocsPage = () => { {videos && <VideoPreviews videos={videos} />} </div> <RenderPrimaryStory primaryStory={primaryStory} skipPrimaryStory={skipPrimaryStory} /> - <RenderArgsTable primaryStory={primaryStory} hideArgsTable={hideArgsTable} /> + <RenderArgsTable + primaryStory={primaryStory} + hideArgsTable={hideArgsTable} + argsTypes={primaryStoryContext.argTypes} + /> <Stories /> </div> <div className={styles.toc}> From 1b764e429f2e09b9698c1839192ecf8561224c7f Mon Sep 17 00:00:00 2001 From: Martin Hochel <martinhochel@microsoft.com> Date: Fri, 14 Feb 2025 10:37:18 +0100 Subject: [PATCH 07/28] refactor: dont mutate story object rather use scoped enhancer within args table --- apps/public-docsite-v9/.storybook/preview.js | 16 +++++-- .../DocsComponents/FluentDocsPage.stories.tsx | 44 +++++++++---------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/apps/public-docsite-v9/.storybook/preview.js b/apps/public-docsite-v9/.storybook/preview.js index 892a4cecf45bde..bb5c680f10def5 100644 --- a/apps/public-docsite-v9/.storybook/preview.js +++ b/apps/public-docsite-v9/.storybook/preview.js @@ -70,14 +70,24 @@ const withSlotEnhancer = context => { const updatedArgTypes = { ...context.argTypes }; Object.entries(updatedArgTypes).forEach(([key, argType]) => { - // @ts-expect-error - storybook doesn't ship proper types - const value = argType?.type?.value; + const type = argType.type; + if (!type || type.name !== 'other') { + return; + } + + const value = type.value; + + if (!value) { + return; + } // we are interested only on raw strings ( which is case of non Storybook supported types) - if (value && typeof value === 'string') { + if (typeof value === 'string') { const match = value.match(slotRegex); if (match) { updatedArgTypes[key].table.type.summary = `Slot<\"${match[1]}\">`; + // @ts-expect-error - storybook doesn't ship proper types (value is missing) + updatedArgTypes[key].type.value = `Slot<\"${match[1]}\">`; } } }); diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index bf50f83253e7cd..332f86119a86bd 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -10,7 +10,7 @@ import { Stories, type DocsContextProps, } from '@storybook/addon-docs'; -import type { PreparedStory, Renderer, StrictArgTypes, StoryContextForEnhancers } from '@storybook/types'; +import type { PreparedStory, Renderer, StrictArgTypes } from '@storybook/types'; import type { SBEnumType } from '@storybook/csf'; import { makeStyles, shorthands, tokens, Link, Text } from '@fluentui/react-components'; import { InfoFilled } from '@fluentui/react-icons'; @@ -135,40 +135,47 @@ const getNativeElementsList = (elements: SBEnumType['value']): JSX.Element => { const slotRegex = /as\?:\s*"([^"]+)"/; function withSlotEnhancer(story: PreparedStory) { - const docGenProps = story.component?.__docgenInfo?.props; + type InternalComponentApi = { + __docgenInfo: { props?: Record<string, { type: { name: string } }> }; + [k: string]: unknown; + }; + const component = story.component as InternalComponentApi; + const docGenProps = component?.__docgenInfo?.props; if (!docGenProps) { - return story; + return component; } Object.entries(docGenProps).forEach(([key, argType]) => { const value: string = argType?.type?.name; const match = value.match(slotRegex); - if (Array.isArray(match)) { - story.component.__docgenInfo.props[key].type.name = `Slot<\"${match[1]}\">`; + if (match) { + component.__docgenInfo.props![key].type.name = `Slot<\"${match[1]}\">`; } }); - return story; + return component; } const RenderArgsTable = ({ hideArgsTable, - primaryStory, - argsTypes, + story, + argTypes, }: { - primaryStory: PrimaryStory; + story: PrimaryStory; hideArgsTable: boolean; - argsTypes: StrictArgTypes; + argTypes: StrictArgTypes; }) => { const styles = useStyles(); + const { component } = withSlotEnhancer(story); + return hideArgsTable ? null : ( <> - <ArgsTable of={primaryStory.component} /> + <ArgsTable of={component} /> - {primaryStory.argTypes.as && primaryStory.argTypes.as?.type?.name === 'enum' && ( + {story.argTypes.as && story.argTypes.as?.type?.name === 'enum' && ( <div className={styles.nativeProps}> <InfoFilled className={styles.nativePropsIcon} /> <div className={styles.nativePropsMessage}> @@ -176,9 +183,8 @@ const RenderArgsTable = ({ Native props are supported <span role="presentation">🙌</span> </b> <span> - All HTML attributes native to the {getNativeElementsList(primaryStory.argTypes.as.type.value)}, including - all <code>aria-*</code> and <code>data-*</code> attributes, can be applied as native props on this - component. + All HTML attributes native to the {getNativeElementsList(story.argTypes.as.type.value)}, including all{' '} + <code>aria-*</code> and <code>data-*</code> attributes, can be applied as native props on this component. </span> </div> </div> @@ -235,8 +241,6 @@ export const FluentDocsPage = () => { // })), // ); - const TweakedComponent = withSlotEnhancer(primaryStory); - return ( <div className="sb-unstyled"> <Title /> @@ -252,11 +256,7 @@ export const FluentDocsPage = () => { {videos && <VideoPreviews videos={videos} />} </div> <RenderPrimaryStory primaryStory={primaryStory} skipPrimaryStory={skipPrimaryStory} /> - <RenderArgsTable - primaryStory={primaryStory} - hideArgsTable={hideArgsTable} - argsTypes={primaryStoryContext.argTypes} - /> + <RenderArgsTable story={primaryStory} hideArgsTable={hideArgsTable} argTypes={primaryStoryContext.argTypes} /> <Stories /> </div> <div className={styles.toc}> From c755e842a9af097c0f353ef50196b6a4d70529f9 Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Fri, 21 Feb 2025 11:01:06 +0100 Subject: [PATCH 08/28] improve readability - move message before prop table --- .../DocsComponents/FluentDocsPage.stories.tsx | 39 +++++++++++++++++-- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 332f86119a86bd..275400f7605b0b 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -71,6 +71,34 @@ const useStyles = makeStyles({ flexDirection: 'column', gap: tokens.spacingVerticalXS, }, + slotAPIs: { + display: 'flex', + gap: tokens.spacingHorizontalM, + + border: `1px solid ${tokens.colorNeutralStroke1}`, + borderRadius: tokens.borderRadiusMedium, + padding: tokens.spacingHorizontalM, + margin: `0 ${tokens.spacingHorizontalM}`, + }, + slotAPIsInfo: { + display: 'flex', + gap: tokens.spacingHorizontalM, + + border: `1px solid ${tokens.colorNeutralStroke1}`, + borderRadius: tokens.borderRadiusMedium, + padding: tokens.spacingHorizontalM, + margin: `0 ${tokens.spacingHorizontalM}`, + }, + slotAPIsMessage: { + display: 'flex', + flexDirection: 'column', + gap: tokens.spacingVerticalXS, + }, + slotAPIsIcon: { + alignSelf: 'center', + color: tokens.colorBrandForeground1, + fontSize: '24px', + }, }); const useVideoClasses = makeStyles({ @@ -149,9 +177,10 @@ function withSlotEnhancer(story: PreparedStory) { Object.entries(docGenProps).forEach(([key, argType]) => { const value: string = argType?.type?.name; const match = value.match(slotRegex); - if (match) { component.__docgenInfo.props![key].type.name = `Slot<\"${match[1]}\">`; + // @ts-expect-error - storybook doesn't ship proper types (value is missing) + updatedArgTypes[key].type.value = `Slot<\"${match[1]}\">`; } }); @@ -170,11 +199,11 @@ const RenderArgsTable = ({ const styles = useStyles(); const { component } = withSlotEnhancer(story); - + // const hasSlot = Object.keys(story.argTypes).some(key => + // story.argTypes[key].table?.type?.summary?.startsWith('Slot<'), + // ); return hideArgsTable ? null : ( <> - <ArgsTable of={component} /> - {story.argTypes.as && story.argTypes.as?.type?.name === 'enum' && ( <div className={styles.nativeProps}> <InfoFilled className={styles.nativePropsIcon} /> @@ -189,6 +218,8 @@ const RenderArgsTable = ({ </div> </div> )} + + <ArgsTable of={component} /> </> ); }; From 5b1cb705d1dae1c5b8aabc8180efdcd6a40da238 Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Fri, 21 Feb 2025 11:21:50 +0100 Subject: [PATCH 09/28] adjusted overrides to handle complex Slot types --- .../DocsComponents/FluentDocsPage.stories.tsx | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 275400f7605b0b..757f4f4f3f9acd 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -162,6 +162,7 @@ const getNativeElementsList = (elements: SBEnumType['value']): JSX.Element => { }; const slotRegex = /as\?:\s*"([^"]+)"/; + function withSlotEnhancer(story: PreparedStory) { type InternalComponentApi = { __docgenInfo: { props?: Record<string, { type: { name: string } }> }; @@ -176,11 +177,17 @@ function withSlotEnhancer(story: PreparedStory) { Object.entries(docGenProps).forEach(([key, argType]) => { const value: string = argType?.type?.name; - const match = value.match(slotRegex); - if (match) { - component.__docgenInfo.props![key].type.name = `Slot<\"${match[1]}\">`; - // @ts-expect-error - storybook doesn't ship proper types (value is missing) - updatedArgTypes[key].type.value = `Slot<\"${match[1]}\">`; + if (value.includes('WithSlotShorthandValue')) { + const match = value.match(slotRegex); + if (match) { + component.__docgenInfo.props![key].type.name = `Slot<\"${match[1]}\">`; + // @ts-expect-error - storybook doesn't ship proper types (value is missing) + updatedArgTypes[key].type.value = `Slot<\"${match[1]}\">`; + } else { + component.__docgenInfo.props![key].type.name = `Slot`; + // @ts-expect-error - storybook doesn't ship proper types (value is missing) + updatedArgTypes[key].type.value = `Slot`; + } } }); From 9accdbbe3f199e03ea0c88de005961e9e0832a44 Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Fri, 21 Feb 2025 11:43:14 +0100 Subject: [PATCH 10/28] adjust for complex Slot types --- apps/public-docsite-v9/.storybook/preview.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/public-docsite-v9/.storybook/preview.js b/apps/public-docsite-v9/.storybook/preview.js index bb5c680f10def5..37c64c681bf2c1 100644 --- a/apps/public-docsite-v9/.storybook/preview.js +++ b/apps/public-docsite-v9/.storybook/preview.js @@ -81,13 +81,12 @@ const withSlotEnhancer = context => { return; } - // we are interested only on raw strings ( which is case of non Storybook supported types) - if (typeof value === 'string') { + if (value.includes('WithSlotShorthandValue')) { const match = value.match(slotRegex); if (match) { updatedArgTypes[key].table.type.summary = `Slot<\"${match[1]}\">`; - // @ts-expect-error - storybook doesn't ship proper types (value is missing) - updatedArgTypes[key].type.value = `Slot<\"${match[1]}\">`; + } else { + updatedArgTypes[key].table.type.summary = `Slot`; } } }); From ca619c1143b0e85406abed323024970a6ebedd3e Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Thu, 27 Feb 2025 09:03:50 +0100 Subject: [PATCH 11/28] fix info box --- .../src/DocsComponents/FluentDocsPage.stories.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 757f4f4f3f9acd..9ce652df9a6870 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -206,9 +206,6 @@ const RenderArgsTable = ({ const styles = useStyles(); const { component } = withSlotEnhancer(story); - // const hasSlot = Object.keys(story.argTypes).some(key => - // story.argTypes[key].table?.type?.summary?.startsWith('Slot<'), - // ); return hideArgsTable ? null : ( <> {story.argTypes.as && story.argTypes.as?.type?.name === 'enum' && ( @@ -225,7 +222,6 @@ const RenderArgsTable = ({ </div> </div> )} - <ArgsTable of={component} /> </> ); From 8394dab5b040494bdaa2795bfbf3772bd22c2374 Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Thu, 27 Feb 2025 09:29:26 +0100 Subject: [PATCH 12/28] additional info about customizing with slots --- .../DocsComponents/FluentDocsPage.stories.tsx | 53 ++++++++++++++----- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 9ce652df9a6870..d0a7f9aaadc142 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -54,27 +54,34 @@ const useStyles = makeStyles({ }, nativeProps: { display: 'flex', + flexDirection: 'column', gap: tokens.spacingHorizontalM, - border: `1px solid ${tokens.colorNeutralStroke1}`, borderRadius: tokens.borderRadiusMedium, padding: tokens.spacingHorizontalM, margin: `0 ${tokens.spacingHorizontalM}`, }, nativePropsIcon: { - alignSelf: 'center', + alignSelf: 'flex-start', color: tokens.colorBrandForeground1, fontSize: '24px', + marginRight: tokens.spacingHorizontalM, }, nativePropsMessage: { + display: 'flex', + flexDirection: 'row', + alignItems: 'flex-start', + gap: tokens.spacingVerticalXS, + }, + infoIcon: { display: 'flex', flexDirection: 'column', gap: tokens.spacingVerticalXS, + flex: 1, }, slotAPIs: { display: 'flex', gap: tokens.spacingHorizontalM, - border: `1px solid ${tokens.colorNeutralStroke1}`, borderRadius: tokens.borderRadiusMedium, padding: tokens.spacingHorizontalM, @@ -83,7 +90,6 @@ const useStyles = makeStyles({ slotAPIsInfo: { display: 'flex', gap: tokens.spacingHorizontalM, - border: `1px solid ${tokens.colorNeutralStroke1}`, borderRadius: tokens.borderRadiusMedium, padding: tokens.spacingHorizontalM, @@ -193,7 +199,6 @@ function withSlotEnhancer(story: PreparedStory) { return component; } - const RenderArgsTable = ({ hideArgsTable, story, @@ -206,19 +211,40 @@ const RenderArgsTable = ({ const styles = useStyles(); const { component } = withSlotEnhancer(story); + return hideArgsTable ? null : ( <> {story.argTypes.as && story.argTypes.as?.type?.name === 'enum' && ( <div className={styles.nativeProps}> - <InfoFilled className={styles.nativePropsIcon} /> <div className={styles.nativePropsMessage}> - <b> - Native props are supported <span role="presentation">🙌</span> - </b> - <span> - All HTML attributes native to the {getNativeElementsList(story.argTypes.as.type.value)}, including all{' '} - <code>aria-*</code> and <code>data-*</code> attributes, can be applied as native props on this component. - </span> + <InfoFilled className={styles.nativePropsIcon} /> + <div className={styles.infoIcon}> + <b> + Native props are supported <span role="presentation">🙌</span> + </b> + <span> + All HTML attributes native to the {getNativeElementsList(story.argTypes.as.type.value)}, including all{' '} + <code>aria-*</code> and <code>data-*</code> attributes, can be applied as native props on this + component. + </span> + </div> + </div> + <div className={styles.nativePropsMessage}> + <InfoFilled className={styles.nativePropsIcon} /> + <div className={styles.infoIcon}> + <b> + Customizing components with slots <span role="presentation">🙌</span> + </b> + <span> + Slots in Fluent UI React components are designed to be modified or replaced, providing a flexible + approach to customizing components. Each slot is exposed as a top-level prop and can be filled with + primitive values, JSX/TSX, props objects, or render functions. This allows for more dynamic and reusable + component structures, similar to slots in other frameworks.{' '} + <a href="https://fluent2.microsoft.design/get-started/migrate/#customizing-component-parts"> + Customizing components with slots + </a> + </span> + </div> </div> </div> )} @@ -226,7 +252,6 @@ const RenderArgsTable = ({ </> ); }; - const RenderPrimaryStory = ({ primaryStory, skipPrimaryStory, From 1c6f3b536c3670f36ae6650374db45eab3e06dfb Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Thu, 27 Feb 2025 09:53:33 +0100 Subject: [PATCH 13/28] create copy for story --- .../src/DocsComponents/FluentDocsPage.stories.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index d0a7f9aaadc142..2f6a49ee791350 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -210,7 +210,8 @@ const RenderArgsTable = ({ }) => { const styles = useStyles(); - const { component } = withSlotEnhancer(story); + const storyCopy = { ...story }; + const { component } = withSlotEnhancer(storyCopy); return hideArgsTable ? null : ( <> From 50a6bdb7704ab1ec7e20264754fa3d29b641e8f0 Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Thu, 27 Feb 2025 10:58:35 +0100 Subject: [PATCH 14/28] refactor additional info styles --- .../DocsComponents/FluentDocsPage.stories.tsx | 42 ++++--------------- 1 file changed, 8 insertions(+), 34 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 2f6a49ee791350..786dcb8404f082 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -52,7 +52,7 @@ const useStyles = makeStyles({ display: 'grid', gridTemplateColumns: '1fr min-content', }, - nativeProps: { + additionalInfo: { display: 'flex', flexDirection: 'column', gap: tokens.spacingHorizontalM, @@ -61,13 +61,13 @@ const useStyles = makeStyles({ padding: tokens.spacingHorizontalM, margin: `0 ${tokens.spacingHorizontalM}`, }, - nativePropsIcon: { + additionalInfoIcon: { alignSelf: 'flex-start', color: tokens.colorBrandForeground1, fontSize: '24px', marginRight: tokens.spacingHorizontalM, }, - nativePropsMessage: { + additionalInfoMessage: { display: 'flex', flexDirection: 'row', alignItems: 'flex-start', @@ -79,32 +79,6 @@ const useStyles = makeStyles({ gap: tokens.spacingVerticalXS, flex: 1, }, - slotAPIs: { - display: 'flex', - gap: tokens.spacingHorizontalM, - border: `1px solid ${tokens.colorNeutralStroke1}`, - borderRadius: tokens.borderRadiusMedium, - padding: tokens.spacingHorizontalM, - margin: `0 ${tokens.spacingHorizontalM}`, - }, - slotAPIsInfo: { - display: 'flex', - gap: tokens.spacingHorizontalM, - border: `1px solid ${tokens.colorNeutralStroke1}`, - borderRadius: tokens.borderRadiusMedium, - padding: tokens.spacingHorizontalM, - margin: `0 ${tokens.spacingHorizontalM}`, - }, - slotAPIsMessage: { - display: 'flex', - flexDirection: 'column', - gap: tokens.spacingVerticalXS, - }, - slotAPIsIcon: { - alignSelf: 'center', - color: tokens.colorBrandForeground1, - fontSize: '24px', - }, }); const useVideoClasses = makeStyles({ @@ -216,9 +190,9 @@ const RenderArgsTable = ({ return hideArgsTable ? null : ( <> {story.argTypes.as && story.argTypes.as?.type?.name === 'enum' && ( - <div className={styles.nativeProps}> - <div className={styles.nativePropsMessage}> - <InfoFilled className={styles.nativePropsIcon} /> + <div className={styles.additionalInfo}> + <div className={styles.additionalInfoMessage}> + <InfoFilled className={styles.additionalInfoIcon} /> <div className={styles.infoIcon}> <b> Native props are supported <span role="presentation">🙌</span> @@ -230,8 +204,8 @@ const RenderArgsTable = ({ </span> </div> </div> - <div className={styles.nativePropsMessage}> - <InfoFilled className={styles.nativePropsIcon} /> + <div className={styles.additionalInfoMessage}> + <InfoFilled className={styles.additionalInfoIcon} /> <div className={styles.infoIcon}> <b> Customizing components with slots <span role="presentation">🙌</span> From 95ee5d8af7fc5b0e23d569c9c576b259dd7219ca Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Thu, 27 Feb 2025 11:24:39 +0100 Subject: [PATCH 15/28] fix link --- .../src/DocsComponents/FluentDocsPage.stories.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 786dcb8404f082..f0abc68c37f214 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -187,6 +187,7 @@ const RenderArgsTable = ({ const storyCopy = { ...story }; const { component } = withSlotEnhancer(storyCopy); + // const hasSlot = story.argTypes.as && story.argTypes.type.value === 'Slot'; return hideArgsTable ? null : ( <> {story.argTypes.as && story.argTypes.as?.type?.name === 'enum' && ( @@ -215,9 +216,9 @@ const RenderArgsTable = ({ approach to customizing components. Each slot is exposed as a top-level prop and can be filled with primitive values, JSX/TSX, props objects, or render functions. This allows for more dynamic and reusable component structures, similar to slots in other frameworks.{' '} - <a href="https://fluent2.microsoft.design/get-started/migrate/#customizing-component-parts"> - Customizing components with slots - </a> + <Link href="https://react.fluentui.dev/?path=/docs/concepts-developer-customizing-components-with-slots--docs"> + Customizing components with slots{' '} + </Link> </span> </div> </div> From 0d7b67952fa3498549f616578bc664eac46343b5 Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Thu, 27 Feb 2025 11:39:33 +0100 Subject: [PATCH 16/28] fix link for slots --- .../src/DocsComponents/FluentDocsPage.stories.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index f0abc68c37f214..21801837c21053 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -144,6 +144,8 @@ const getNativeElementsList = (elements: SBEnumType['value']): JSX.Element => { const slotRegex = /as\?:\s*"([^"]+)"/; function withSlotEnhancer(story: PreparedStory) { + const updatedArgTypes = { ...story.argTypes }; + type InternalComponentApi = { __docgenInfo: { props?: Record<string, { type: { name: string } }> }; [k: string]: unknown; @@ -216,7 +218,7 @@ const RenderArgsTable = ({ approach to customizing components. Each slot is exposed as a top-level prop and can be filled with primitive values, JSX/TSX, props objects, or render functions. This allows for more dynamic and reusable component structures, similar to slots in other frameworks.{' '} - <Link href="https://react.fluentui.dev/?path=/docs/concepts-developer-customizing-components-with-slots--docs"> + <Link href="/?path=/docs/concepts-developer-customizing-components-with-slots--docs"> Customizing components with slots{' '} </Link> </span> From dd097bbcee3266070562c7fbc9f6f3214b0d4273 Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Mon, 3 Mar 2025 13:37:55 +0100 Subject: [PATCH 17/28] encapsulate repeated logic into separate component and render conditionally --- .../DocsComponents/FluentDocsPage.stories.tsx | 97 +++++++++++-------- 1 file changed, 59 insertions(+), 38 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 21801837c21053..0cd4f3675fc233 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -142,7 +142,7 @@ const getNativeElementsList = (elements: SBEnumType['value']): JSX.Element => { }; const slotRegex = /as\?:\s*"([^"]+)"/; - +let hasSlotMatch = false; function withSlotEnhancer(story: PreparedStory) { const updatedArgTypes = { ...story.argTypes }; @@ -160,6 +160,7 @@ function withSlotEnhancer(story: PreparedStory) { Object.entries(docGenProps).forEach(([key, argType]) => { const value: string = argType?.type?.name; if (value.includes('WithSlotShorthandValue')) { + hasSlotMatch = true; const match = value.match(slotRegex); if (match) { component.__docgenInfo.props![key].type.name = `Slot<\"${match[1]}\">`; @@ -175,6 +176,18 @@ function withSlotEnhancer(story: PreparedStory) { return component; } + +const AdditionalApiDocs: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const styles = useStyles(); + return ( + <div className={styles.additionalInfo}> + <div className={styles.additionalInfoMessage}> + <InfoFilled className={styles.additionalInfoIcon} /> + <div className={styles.infoIcon}>{children}</div> + </div> + </div> + ); +}; const RenderArgsTable = ({ hideArgsTable, story, @@ -184,52 +197,60 @@ const RenderArgsTable = ({ hideArgsTable: boolean; argTypes: StrictArgTypes; }) => { - const styles = useStyles(); - const storyCopy = { ...story }; - const { component } = withSlotEnhancer(storyCopy); + type InternalComponentApi = { + __docgenInfo: { props?: Record<string, { type: { name: string } }> }; + [k: string]: unknown; + }; + // type DocgenProp = { + // type: { name: string }; + // }; + const component = withSlotEnhancer(storyCopy).component as InternalComponentApi; + // const docGenProps = component?.__docgenInfo?.props; + // const hasArgSlotProp = docGenProps + // ? Object.values(docGenProps).some((prop: DocgenProp) => { + // const typeName = prop.type.name; + // console.log(typeName); // Debugging statement + // return typeName.startsWith('Slot') || typeName.startsWith('WithSlotShorthandValue'); + // }) + // : false; + const hasArgAsProp = story.argTypes.as && story.argTypes.as?.type?.name === 'enum'; - // const hasSlot = story.argTypes.as && story.argTypes.type.value === 'Slot'; return hideArgsTable ? null : ( <> - {story.argTypes.as && story.argTypes.as?.type?.name === 'enum' && ( - <div className={styles.additionalInfo}> - <div className={styles.additionalInfoMessage}> - <InfoFilled className={styles.additionalInfoIcon} /> - <div className={styles.infoIcon}> - <b> - Native props are supported <span role="presentation">🙌</span> - </b> - <span> - All HTML attributes native to the {getNativeElementsList(story.argTypes.as.type.value)}, including all{' '} - <code>aria-*</code> and <code>data-*</code> attributes, can be applied as native props on this - component. - </span> - </div> - </div> - <div className={styles.additionalInfoMessage}> - <InfoFilled className={styles.additionalInfoIcon} /> - <div className={styles.infoIcon}> - <b> - Customizing components with slots <span role="presentation">🙌</span> - </b> - <span> - Slots in Fluent UI React components are designed to be modified or replaced, providing a flexible - approach to customizing components. Each slot is exposed as a top-level prop and can be filled with - primitive values, JSX/TSX, props objects, or render functions. This allows for more dynamic and reusable - component structures, similar to slots in other frameworks.{' '} - <Link href="/?path=/docs/concepts-developer-customizing-components-with-slots--docs"> - Customizing components with slots{' '} - </Link> - </span> - </div> - </div> - </div> + {hasArgAsProp && ( + <AdditionalApiDocs> + <b> + Native props are supported <span role="presentation">🙌</span> + </b> + <span> + All HTML attributes native to the + {getNativeElementsList(story.argTypes.as?.options)}, including all <code>aria-*</code> and{' '} + <code>data-*</code> attributes, can be applied as native props on this component. + </span> + </AdditionalApiDocs> + )} + {hasSlotMatch && ( + <AdditionalApiDocs> + <b> + Customizing components with slots <span role="presentation">🙌</span> + </b> + <span> + Slots in Fluent UI React components are designed to be modified or replaced, providing a flexible approach + to customizing components. Each slot is exposed as a top-level prop and can be filled with primitive values, + JSX/TSX, props objects, or render functions. This allows for more dynamic and reusable component structures, + similar to slots in other frameworks.{' '} + <Link href="/?path=/docs/concepts-developer-customizing-components-with-slots--docs"> + Customizing components with slots{' '} + </Link> + </span> + </AdditionalApiDocs> )} <ArgsTable of={component} /> </> ); }; + const RenderPrimaryStory = ({ primaryStory, skipPrimaryStory, From 71a0b6f3f4a214d96414f7989ee66795d9bb9094 Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Mon, 3 Mar 2025 13:40:00 +0100 Subject: [PATCH 18/28] remove unnecessary comments --- .../src/DocsComponents/FluentDocsPage.stories.tsx | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 0cd4f3675fc233..5d2a4a999fd494 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -202,18 +202,9 @@ const RenderArgsTable = ({ __docgenInfo: { props?: Record<string, { type: { name: string } }> }; [k: string]: unknown; }; - // type DocgenProp = { - // type: { name: string }; - // }; + const component = withSlotEnhancer(storyCopy).component as InternalComponentApi; - // const docGenProps = component?.__docgenInfo?.props; - // const hasArgSlotProp = docGenProps - // ? Object.values(docGenProps).some((prop: DocgenProp) => { - // const typeName = prop.type.name; - // console.log(typeName); // Debugging statement - // return typeName.startsWith('Slot') || typeName.startsWith('WithSlotShorthandValue'); - // }) - // : false; + const hasArgAsProp = story.argTypes.as && story.argTypes.as?.type?.name === 'enum'; return hideArgsTable ? null : ( From 3d540542ab2ed407d7300c64c46b90a1268b8582 Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Mon, 3 Mar 2025 14:04:59 +0100 Subject: [PATCH 19/28] revert changes --- apps/public-docsite-v9/.storybook/preview.js | 39 -------------------- 1 file changed, 39 deletions(-) diff --git a/apps/public-docsite-v9/.storybook/preview.js b/apps/public-docsite-v9/.storybook/preview.js index 37c64c681bf2c1..461d1c131c4103 100644 --- a/apps/public-docsite-v9/.storybook/preview.js +++ b/apps/public-docsite-v9/.storybook/preview.js @@ -59,42 +59,3 @@ export const parameters = { }, }, }; - -const slotRegex = /as\?:\s*"([^"]+)"/; - -/** - * - * @type {import('@storybook/types').ArgTypesEnhancer} - */ -const withSlotEnhancer = context => { - const updatedArgTypes = { ...context.argTypes }; - - Object.entries(updatedArgTypes).forEach(([key, argType]) => { - const type = argType.type; - if (!type || type.name !== 'other') { - return; - } - - const value = type.value; - - if (!value) { - return; - } - - if (value.includes('WithSlotShorthandValue')) { - const match = value.match(slotRegex); - if (match) { - updatedArgTypes[key].table.type.summary = `Slot<\"${match[1]}\">`; - } else { - updatedArgTypes[key].table.type.summary = `Slot`; - } - } - }); - - return updatedArgTypes; -}; - -/** - * @type {import('@storybook/types').ArgTypesEnhancer[]} - */ -export const argTypesEnhancers = [withSlotEnhancer]; From 80fde25f5294a77e55863e48c4665915b123d3d0 Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Wed, 12 Mar 2025 11:47:25 +0100 Subject: [PATCH 20/28] Refactor AdditionalApiDocs to use ReactElement instead of ReactNode --- .../src/DocsComponents/FluentDocsPage.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 5d2a4a999fd494..66fe32a9482d3f 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -177,7 +177,7 @@ function withSlotEnhancer(story: PreparedStory) { return component; } -const AdditionalApiDocs: React.FC<{ children: React.ReactNode }> = ({ children }) => { +const AdditionalApiDocs: React.FC<{ children: React.ReactElement }> = ({ children }) => { const styles = useStyles(); return ( <div className={styles.additionalInfo}> From 42a2fdea7015c0d298c5d99c16e16514830bf672 Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Wed, 12 Mar 2025 15:43:05 +0100 Subject: [PATCH 21/28] additional docs fix --- .../DocsComponents/FluentDocsPage.stories.tsx | 56 +++++++++++-------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 66fe32a9482d3f..3c451b43066a5a 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -55,14 +55,15 @@ const useStyles = makeStyles({ additionalInfo: { display: 'flex', flexDirection: 'column', - gap: tokens.spacingHorizontalM, + gap: tokens.spacingVerticalM, border: `1px solid ${tokens.colorNeutralStroke1}`, borderRadius: tokens.borderRadiusMedium, padding: tokens.spacingHorizontalM, margin: `0 ${tokens.spacingHorizontalM}`, }, additionalInfoIcon: { - alignSelf: 'flex-start', + // alignSelf: 'flex-start', + alignSelf: 'center', color: tokens.colorBrandForeground1, fontSize: '24px', marginRight: tokens.spacingHorizontalM, @@ -70,7 +71,8 @@ const useStyles = makeStyles({ additionalInfoMessage: { display: 'flex', flexDirection: 'row', - alignItems: 'flex-start', + // alignItems: 'flex-start', + alignItems: 'center', gap: tokens.spacingVerticalXS, }, infoIcon: { @@ -177,7 +179,7 @@ function withSlotEnhancer(story: PreparedStory) { return component; } -const AdditionalApiDocs: React.FC<{ children: React.ReactElement }> = ({ children }) => { +const AdditionalApiDocs: React.FC<{ children: React.ReactElement | React.ReactElement[] }> = ({ children }) => { const styles = useStyles(); return ( <div className={styles.additionalInfo}> @@ -211,30 +213,36 @@ const RenderArgsTable = ({ <> {hasArgAsProp && ( <AdditionalApiDocs> - <b> - Native props are supported <span role="presentation">🙌</span> - </b> - <span> - All HTML attributes native to the - {getNativeElementsList(story.argTypes.as?.options)}, including all <code>aria-*</code> and{' '} - <code>data-*</code> attributes, can be applied as native props on this component. - </span> + <p> + <b> + Native props are supported <span role="presentation">🙌</span> + <br /> + </b> + <span> + All HTML attributes native to the + {getNativeElementsList(story.argTypes.as?.options)}, including all <code>aria-*</code> and{' '} + <code>data-*</code> attributes, can be applied as native props on this component. + </span> + </p> </AdditionalApiDocs> )} {hasSlotMatch && ( <AdditionalApiDocs> - <b> - Customizing components with slots <span role="presentation">🙌</span> - </b> - <span> - Slots in Fluent UI React components are designed to be modified or replaced, providing a flexible approach - to customizing components. Each slot is exposed as a top-level prop and can be filled with primitive values, - JSX/TSX, props objects, or render functions. This allows for more dynamic and reusable component structures, - similar to slots in other frameworks.{' '} - <Link href="/?path=/docs/concepts-developer-customizing-components-with-slots--docs"> - Customizing components with slots{' '} - </Link> - </span> + <p> + <b> + Customizing components with slots <span role="presentation">🙌</span> + </b> + <br /> + <span> + Slots in Fluent UI React components are designed to be modified or replaced, providing a flexible approach + to customizing components. Each slot is exposed as a top-level prop and can be filled with primitive + values, JSX/TSX, props objects, or render functions. This allows for more dynamic and reusable component + structures, similar to slots in other frameworks.{' '} + <Link href="/?path=/docs/concepts-developer-customizing-components-with-slots--docs"> + Customizing components with slots{' '} + </Link> + </span> + </p> </AdditionalApiDocs> )} <ArgsTable of={component} /> From fb0662518d20cc5ed278d2eeeaf0b52377413ca2 Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Wed, 12 Mar 2025 16:27:30 +0100 Subject: [PATCH 22/28] refactor - deep copy and remove global flag --- .../DocsComponents/FluentDocsPage.stories.tsx | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 3c451b43066a5a..f4396ab3226c1c 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import cloneDeep from 'lodash/cloneDeep'; import { DocsContext, ArgsTable, @@ -18,6 +19,7 @@ import { DIR_ID, THEME_ID, themes } from '@fluentui/react-storybook-addon'; import { DirSwitch } from './DirSwitch.stories'; import { ThemePicker } from './ThemePicker.stories'; import { Toc, nameToHash } from './Toc.stories'; +import { has } from 'lodash'; type PrimaryStory = PreparedStory<Renderer>; @@ -144,10 +146,10 @@ const getNativeElementsList = (elements: SBEnumType['value']): JSX.Element => { }; const slotRegex = /as\?:\s*"([^"]+)"/; -let hasSlotMatch = false; function withSlotEnhancer(story: PreparedStory) { const updatedArgTypes = { ...story.argTypes }; - + const hasArgAsProp = story.argTypes.as && story.argTypes.as?.type?.name === 'enum'; + let hasArgAsSlot = false; type InternalComponentApi = { __docgenInfo: { props?: Record<string, { type: { name: string } }> }; [k: string]: unknown; @@ -162,7 +164,7 @@ function withSlotEnhancer(story: PreparedStory) { Object.entries(docGenProps).forEach(([key, argType]) => { const value: string = argType?.type?.name; if (value.includes('WithSlotShorthandValue')) { - hasSlotMatch = true; + hasArgAsSlot = true; const match = value.match(slotRegex); if (match) { component.__docgenInfo.props![key].type.name = `Slot<\"${match[1]}\">`; @@ -176,7 +178,7 @@ function withSlotEnhancer(story: PreparedStory) { } }); - return component; + return { component, hasArgAsSlot, hasArgAsProp }; } const AdditionalApiDocs: React.FC<{ children: React.ReactElement | React.ReactElement[] }> = ({ children }) => { @@ -199,15 +201,8 @@ const RenderArgsTable = ({ hideArgsTable: boolean; argTypes: StrictArgTypes; }) => { - const storyCopy = { ...story }; - type InternalComponentApi = { - __docgenInfo: { props?: Record<string, { type: { name: string } }> }; - [k: string]: unknown; - }; - - const component = withSlotEnhancer(storyCopy).component as InternalComponentApi; - - const hasArgAsProp = story.argTypes.as && story.argTypes.as?.type?.name === 'enum'; + const storyCopy = cloneDeep(story); + const { component, hasArgAsProp, hasArgAsSlot } = withSlotEnhancer(storyCopy); return hideArgsTable ? null : ( <> @@ -226,7 +221,7 @@ const RenderArgsTable = ({ </p> </AdditionalApiDocs> )} - {hasSlotMatch && ( + {hasArgAsSlot && ( <AdditionalApiDocs> <p> <b> From 3c3a2f4eb1d528e7fd41e7d88b2180146925cc50 Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Wed, 12 Mar 2025 16:42:30 +0100 Subject: [PATCH 23/28] cleanup --- .../src/DocsComponents/FluentDocsPage.stories.tsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index f4396ab3226c1c..39dbb12bcd6cbe 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import cloneDeep from 'lodash/cloneDeep'; +import { cloneDeep } from 'lodash'; import { DocsContext, ArgsTable, @@ -11,15 +11,13 @@ import { Stories, type DocsContextProps, } from '@storybook/addon-docs'; -import type { PreparedStory, Renderer, StrictArgTypes } from '@storybook/types'; -import type { SBEnumType } from '@storybook/csf'; +import type { PreparedStory, Renderer, StrictArgTypes, SBEnumType } from '@storybook/types'; import { makeStyles, shorthands, tokens, Link, Text } from '@fluentui/react-components'; import { InfoFilled } from '@fluentui/react-icons'; import { DIR_ID, THEME_ID, themes } from '@fluentui/react-storybook-addon'; import { DirSwitch } from './DirSwitch.stories'; import { ThemePicker } from './ThemePicker.stories'; import { Toc, nameToHash } from './Toc.stories'; -import { has } from 'lodash'; type PrimaryStory = PreparedStory<Renderer>; @@ -64,7 +62,6 @@ const useStyles = makeStyles({ margin: `0 ${tokens.spacingHorizontalM}`, }, additionalInfoIcon: { - // alignSelf: 'flex-start', alignSelf: 'center', color: tokens.colorBrandForeground1, fontSize: '24px', @@ -73,7 +70,6 @@ const useStyles = makeStyles({ additionalInfoMessage: { display: 'flex', flexDirection: 'row', - // alignItems: 'flex-start', alignItems: 'center', gap: tokens.spacingVerticalXS, }, @@ -195,7 +191,6 @@ const AdditionalApiDocs: React.FC<{ children: React.ReactElement | React.ReactEl const RenderArgsTable = ({ hideArgsTable, story, - argTypes, }: { story: PrimaryStory; hideArgsTable: boolean; From c6e3aafa8899f9a3543369ab111dbda29fcc269e Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Wed, 19 Mar 2025 13:13:56 +0100 Subject: [PATCH 24/28] fix for accordion --- .../DocsComponents/FluentDocsPage.stories.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 39dbb12bcd6cbe..0ba91467b2e82b 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -128,7 +128,10 @@ const VideoPreviews: React.FC<{ }; const getNativeElementsList = (elements: SBEnumType['value']): JSX.Element => { - const elementsArr = elements.map((el, idx) => [ + if (!elements) { + return <></>; + } + const elementsArr = elements?.map((el, idx) => [ <code key={idx}>{`<${el}>`}</code>, idx !== elements.length - 1 ? ', ' : ' ', ]); @@ -162,6 +165,7 @@ function withSlotEnhancer(story: PreparedStory) { if (value.includes('WithSlotShorthandValue')) { hasArgAsSlot = true; const match = value.match(slotRegex); + console.log('match', match); if (match) { component.__docgenInfo.props![key].type.name = `Slot<\"${match[1]}\">`; // @ts-expect-error - storybook doesn't ship proper types (value is missing) @@ -198,10 +202,10 @@ const RenderArgsTable = ({ }) => { const storyCopy = cloneDeep(story); const { component, hasArgAsProp, hasArgAsSlot } = withSlotEnhancer(storyCopy); - + const options = story.argTypes.as?.options; return hideArgsTable ? null : ( <> - {hasArgAsProp && ( + {hasArgAsProp && options && ( <AdditionalApiDocs> <p> <b> @@ -210,13 +214,13 @@ const RenderArgsTable = ({ </b> <span> All HTML attributes native to the - {getNativeElementsList(story.argTypes.as?.options)}, including all <code>aria-*</code> and{' '} - <code>data-*</code> attributes, can be applied as native props on this component. + {getNativeElementsList(options)}, including all <code>aria-*</code> and <code>data-*</code> attributes, + can be applied as native props on this component. </span> </p> </AdditionalApiDocs> )} - {hasArgAsSlot && ( + {hasArgAsSlot && options && ( <AdditionalApiDocs> <p> <b> From 4717b49313659ca99d051e035b68963f1c6349d6 Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Thu, 20 Mar 2025 10:54:24 +0100 Subject: [PATCH 25/28] subcomponents enhancement --- .../DocsComponents/FluentDocsPage.stories.tsx | 61 ++++++++++++------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 0ba91467b2e82b..15f7e58d167978 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -149,38 +149,53 @@ function withSlotEnhancer(story: PreparedStory) { const updatedArgTypes = { ...story.argTypes }; const hasArgAsProp = story.argTypes.as && story.argTypes.as?.type?.name === 'enum'; let hasArgAsSlot = false; + type InternalComponentApi = { - __docgenInfo: { props?: Record<string, { type: { name: string } }> }; + __docgenInfo: { + props?: Record<string, { type: { name: string } }>; + subcomponents?: Record<string, InternalComponentApi>; + }; [k: string]: unknown; }; - const component = story.component as InternalComponentApi; - const docGenProps = component?.__docgenInfo?.props; - - if (!docGenProps) { - return component; - } - Object.entries(docGenProps).forEach(([key, argType]) => { - const value: string = argType?.type?.name; - if (value.includes('WithSlotShorthandValue')) { - hasArgAsSlot = true; - const match = value.match(slotRegex); - console.log('match', match); - if (match) { - component.__docgenInfo.props![key].type.name = `Slot<\"${match[1]}\">`; - // @ts-expect-error - storybook doesn't ship proper types (value is missing) - updatedArgTypes[key].type.value = `Slot<\"${match[1]}\">`; - } else { - component.__docgenInfo.props![key].type.name = `Slot`; - // @ts-expect-error - storybook doesn't ship proper types (value is missing) - updatedArgTypes[key].type.value = `Slot`; + const checkPropsForSlotShorthandValue = (props: Record<string, { type: { name: string } }>) => { + Object.entries(props).forEach(([key, argType]) => { + const value: string = argType?.type?.name; + if (value.includes('WithSlotShorthandValue')) { + hasArgAsSlot = true; + const match = value.match(slotRegex); + if (match) { + props[key].type.name = `Slot<\"${match[1]}\">`; + // @ts-expect-error - storybook doesn't ship proper types (value is missing) + updatedArgTypes[key].type.value = `Slot<\"${match[1]}\">`; + } else { + props[key].type.name = `Slot`; + // @ts-expect-error - storybook doesn't ship proper types (value is missing) + updatedArgTypes[key].type.value = `Slot`; + } } + }); + }; + + const processComponent = (component: InternalComponentApi) => { + const docGenProps = component?.__docgenInfo?.props; + if (docGenProps) { + checkPropsForSlotShorthandValue(docGenProps); } - }); + + const subComponents = component?.__docgenInfo?.subcomponents; + if (subComponents) { + Object.values(subComponents).forEach(subcomponent => { + processComponent(subcomponent); + }); + } + }; + + const component = story.component as InternalComponentApi; + processComponent(component); return { component, hasArgAsSlot, hasArgAsProp }; } - const AdditionalApiDocs: React.FC<{ children: React.ReactElement | React.ReactElement[] }> = ({ children }) => { const styles = useStyles(); return ( From 2f21f83cdf77b79940f770e8aed7c9b9966fc22b Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Thu, 20 Mar 2025 11:00:51 +0100 Subject: [PATCH 26/28] remove argtypes --- .../src/DocsComponents/FluentDocsPage.stories.tsx | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index 15f7e58d167978..b2d29d31dc498e 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -11,7 +11,7 @@ import { Stories, type DocsContextProps, } from '@storybook/addon-docs'; -import type { PreparedStory, Renderer, StrictArgTypes, SBEnumType } from '@storybook/types'; +import type { PreparedStory, Renderer, SBEnumType } from '@storybook/types'; import { makeStyles, shorthands, tokens, Link, Text } from '@fluentui/react-components'; import { InfoFilled } from '@fluentui/react-icons'; import { DIR_ID, THEME_ID, themes } from '@fluentui/react-storybook-addon'; @@ -207,14 +207,7 @@ const AdditionalApiDocs: React.FC<{ children: React.ReactElement | React.ReactEl </div> ); }; -const RenderArgsTable = ({ - hideArgsTable, - story, -}: { - story: PrimaryStory; - hideArgsTable: boolean; - argTypes: StrictArgTypes; -}) => { +const RenderArgsTable = ({ hideArgsTable, story }: { story: PrimaryStory; hideArgsTable: boolean }) => { const storyCopy = cloneDeep(story); const { component, hasArgAsProp, hasArgAsSlot } = withSlotEnhancer(storyCopy); const options = story.argTypes.as?.options; From eb48240523f6befebfb7d0fac6ba96227713225d Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Wed, 9 Apr 2025 16:49:59 +0300 Subject: [PATCH 27/28] subcomponents enhance slot types --- .../DocsComponents/FluentDocsPage.stories.tsx | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index b2d29d31dc498e..ac957e0975ffb3 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -145,15 +145,14 @@ const getNativeElementsList = (elements: SBEnumType['value']): JSX.Element => { }; const slotRegex = /as\?:\s*"([^"]+)"/; + function withSlotEnhancer(story: PreparedStory) { - const updatedArgTypes = { ...story.argTypes }; const hasArgAsProp = story.argTypes.as && story.argTypes.as?.type?.name === 'enum'; let hasArgAsSlot = false; type InternalComponentApi = { __docgenInfo: { props?: Record<string, { type: { name: string } }>; - subcomponents?: Record<string, InternalComponentApi>; }; [k: string]: unknown; }; @@ -166,12 +165,8 @@ function withSlotEnhancer(story: PreparedStory) { const match = value.match(slotRegex); if (match) { props[key].type.name = `Slot<\"${match[1]}\">`; - // @ts-expect-error - storybook doesn't ship proper types (value is missing) - updatedArgTypes[key].type.value = `Slot<\"${match[1]}\">`; } else { props[key].type.name = `Slot`; - // @ts-expect-error - storybook doesn't ship proper types (value is missing) - updatedArgTypes[key].type.value = `Slot`; } } }); @@ -182,20 +177,20 @@ function withSlotEnhancer(story: PreparedStory) { if (docGenProps) { checkPropsForSlotShorthandValue(docGenProps); } - - const subComponents = component?.__docgenInfo?.subcomponents; - if (subComponents) { - Object.values(subComponents).forEach(subcomponent => { - processComponent(subcomponent); - }); - } }; const component = story.component as InternalComponentApi; processComponent(component); + if (story.subcomponents) { + Object.values(story.subcomponents).forEach((subcomponent: InternalComponentApi) => { + processComponent(subcomponent); + }); + } + return { component, hasArgAsSlot, hasArgAsProp }; } + const AdditionalApiDocs: React.FC<{ children: React.ReactElement | React.ReactElement[] }> = ({ children }) => { const styles = useStyles(); return ( @@ -208,9 +203,9 @@ const AdditionalApiDocs: React.FC<{ children: React.ReactElement | React.ReactEl ); }; const RenderArgsTable = ({ hideArgsTable, story }: { story: PrimaryStory; hideArgsTable: boolean }) => { - const storyCopy = cloneDeep(story); - const { component, hasArgAsProp, hasArgAsSlot } = withSlotEnhancer(storyCopy); + const { component, hasArgAsProp, hasArgAsSlot } = withSlotEnhancer(story); const options = story.argTypes.as?.options; + return hideArgsTable ? null : ( <> {hasArgAsProp && options && ( @@ -251,7 +246,6 @@ const RenderArgsTable = ({ hideArgsTable, story }: { story: PrimaryStory; hideAr </> ); }; - const RenderPrimaryStory = ({ primaryStory, skipPrimaryStory, From 68ee110dabbc3d9b915545c0c0ed98ad0ed4da9a Mon Sep 17 00:00:00 2001 From: Carla Muntean <carla.muntean@microsoft.com> Date: Thu, 10 Apr 2025 10:36:28 +0300 Subject: [PATCH 28/28] refactor --- .../DocsComponents/FluentDocsPage.stories.tsx | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx index ac957e0975ffb3..14694ba1e1cc15 100644 --- a/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx +++ b/apps/public-docsite-v9/src/DocsComponents/FluentDocsPage.stories.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import { cloneDeep } from 'lodash'; import { DocsContext, ArgsTable, @@ -128,9 +127,6 @@ const VideoPreviews: React.FC<{ }; const getNativeElementsList = (elements: SBEnumType['value']): JSX.Element => { - if (!elements) { - return <></>; - } const elementsArr = elements?.map((el, idx) => [ <code key={idx}>{`<${el}>`}</code>, idx !== elements.length - 1 ? ', ' : ' ', @@ -145,9 +141,12 @@ const getNativeElementsList = (elements: SBEnumType['value']): JSX.Element => { }; const slotRegex = /as\?:\s*"([^"]+)"/; - +/** + * NOTE: this function mutates original story argTypes including all story subcomponents if they are present + */ function withSlotEnhancer(story: PreparedStory) { - const hasArgAsProp = story.argTypes.as && story.argTypes.as?.type?.name === 'enum'; + const hasArgAsProp = story.argTypes.as?.type?.name === 'enum'; + const argAsProp = hasArgAsProp ? (story.argTypes.as.type as SBEnumType).value : null; let hasArgAsSlot = false; type InternalComponentApi = { @@ -157,7 +156,7 @@ function withSlotEnhancer(story: PreparedStory) { [k: string]: unknown; }; - const checkPropsForSlotShorthandValue = (props: Record<string, { type: { name: string } }>) => { + const transformPropsWithSlotShorthand = (props: Record<string, { type: { name: string } }>) => { Object.entries(props).forEach(([key, argType]) => { const value: string = argType?.type?.name; if (value.includes('WithSlotShorthandValue')) { @@ -172,23 +171,23 @@ function withSlotEnhancer(story: PreparedStory) { }); }; - const processComponent = (component: InternalComponentApi) => { + const transformComponent = (component: InternalComponentApi) => { const docGenProps = component?.__docgenInfo?.props; if (docGenProps) { - checkPropsForSlotShorthandValue(docGenProps); + transformPropsWithSlotShorthand(docGenProps); } }; const component = story.component as InternalComponentApi; - processComponent(component); + transformComponent(component); if (story.subcomponents) { Object.values(story.subcomponents).forEach((subcomponent: InternalComponentApi) => { - processComponent(subcomponent); + transformComponent(subcomponent); }); } - return { component, hasArgAsSlot, hasArgAsProp }; + return { component, hasArgAsSlot, hasArgAsProp, argAsProp }; } const AdditionalApiDocs: React.FC<{ children: React.ReactElement | React.ReactElement[] }> = ({ children }) => { @@ -203,12 +202,11 @@ const AdditionalApiDocs: React.FC<{ children: React.ReactElement | React.ReactEl ); }; const RenderArgsTable = ({ hideArgsTable, story }: { story: PrimaryStory; hideArgsTable: boolean }) => { - const { component, hasArgAsProp, hasArgAsSlot } = withSlotEnhancer(story); - const options = story.argTypes.as?.options; + const { component, hasArgAsProp, hasArgAsSlot, argAsProp } = withSlotEnhancer(story); return hideArgsTable ? null : ( <> - {hasArgAsProp && options && ( + {hasArgAsProp && ( <AdditionalApiDocs> <p> <b> @@ -217,13 +215,13 @@ const RenderArgsTable = ({ hideArgsTable, story }: { story: PrimaryStory; hideAr </b> <span> All HTML attributes native to the - {getNativeElementsList(options)}, including all <code>aria-*</code> and <code>data-*</code> attributes, + {getNativeElementsList(argAsProp!)}, including all <code>aria-*</code> and <code>data-*</code> attributes, can be applied as native props on this component. </span> </p> </AdditionalApiDocs> )} - {hasArgAsSlot && options && ( + {hasArgAsSlot && ( <AdditionalApiDocs> <p> <b> @@ -309,7 +307,7 @@ export const FluentDocsPage = () => { {videos && <VideoPreviews videos={videos} />} </div> <RenderPrimaryStory primaryStory={primaryStory} skipPrimaryStory={skipPrimaryStory} /> - <RenderArgsTable story={primaryStory} hideArgsTable={hideArgsTable} argTypes={primaryStoryContext.argTypes} /> + <RenderArgsTable story={primaryStory} hideArgsTable={hideArgsTable} /> <Stories /> </div> <div className={styles.toc}>