From fd8c49537ac768c4937f4ef6325ec28bd522bc8f Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Sun, 2 Oct 2022 01:39:28 -0700 Subject: [PATCH 01/53] add utility functions for CSF test creation --- .../src/utilities/StoryDecorators.tsx | 21 ++++++++++++ .../src/utilities/getStoryVariant.ts | 32 +++++++++++++++++++ .../src/utilities/index.ts | 2 ++ 3 files changed, 55 insertions(+) create mode 100644 apps/vr-tests-react-components/src/utilities/StoryDecorators.tsx create mode 100644 apps/vr-tests-react-components/src/utilities/getStoryVariant.ts diff --git a/apps/vr-tests-react-components/src/utilities/StoryDecorators.tsx b/apps/vr-tests-react-components/src/utilities/StoryDecorators.tsx new file mode 100644 index 0000000000000..374f9e47e3f26 --- /dev/null +++ b/apps/vr-tests-react-components/src/utilities/StoryDecorators.tsx @@ -0,0 +1,21 @@ +import * as React from 'react'; +import { DecoratorFunction } from '@storybook/addons'; +import { webLightTheme, teamsHighContrastTheme, webDarkTheme } from '@fluentui/react-theme'; +import { FluentProvider } from '@fluentui/react-provider'; +import { ExtendedStoryFnReturnType } from './types'; + +export const DarkModeDecorator: DecoratorFunction = story => { + return {story()}; +}; + +export const HighContrastDecorator: DecoratorFunction = story => { + return {story()}; +}; + +export const RTLDecorator: DecoratorFunction = story => { + return ( + + {story()} + + ); +}; diff --git a/apps/vr-tests-react-components/src/utilities/getStoryVariant.ts b/apps/vr-tests-react-components/src/utilities/getStoryVariant.ts new file mode 100644 index 0000000000000..28412bc34b574 --- /dev/null +++ b/apps/vr-tests-react-components/src/utilities/getStoryVariant.ts @@ -0,0 +1,32 @@ +import { ComponentStory } from '@storybook/react'; +import { DarkModeDecorator, HighContrastDecorator, RTLDecorator } from './StoryDecorators'; + +export const DARK_MODE = 'Dark Mode'; +export const HIGH_CONTRAST = 'High Contrast'; +export const RTL = 'RTL'; + +/** + * Helper function that returns a RTL, Dark Mode or High Contrast variant of an existing story. + */ +export const getStoryVariant = (story: ComponentStory, variant: 'RTL' | 'Dark Mode' | 'High Contrast') => { + let decorator; + + if (variant === RTL) { + decorator = RTLDecorator; + } + + if (variant === DARK_MODE) { + decorator = DarkModeDecorator; + } + + if (variant === HIGH_CONTRAST) { + decorator = HighContrastDecorator; + } + + return { + ...story, + render: story, + storyName: `${story.storyName} - ${variant}`, + decorators: [decorator], + }; +}; diff --git a/apps/vr-tests-react-components/src/utilities/index.ts b/apps/vr-tests-react-components/src/utilities/index.ts index 12fc4954c5d70..d071a94751e8b 100644 --- a/apps/vr-tests-react-components/src/utilities/index.ts +++ b/apps/vr-tests-react-components/src/utilities/index.ts @@ -8,3 +8,5 @@ declare module '@storybook/addons' { } export * from './TestWrapperDecorator'; +export * from './StoryDecorators'; +export * from './getStoryVariant'; From 68f2c3c43f552ae8e7fc814c370f20c362edc66c Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Sun, 2 Oct 2022 02:10:33 -0700 Subject: [PATCH 02/53] chore: convert Button stories to CSF --- .../src/stories/Button.stories.tsx | 569 ------------------ .../src/stories/Button/Button.stories.tsx | 200 ++++++ 2 files changed, 200 insertions(+), 569 deletions(-) delete mode 100644 apps/vr-tests-react-components/src/stories/Button.stories.tsx create mode 100644 apps/vr-tests-react-components/src/stories/Button/Button.stories.tsx diff --git a/apps/vr-tests-react-components/src/stories/Button.stories.tsx b/apps/vr-tests-react-components/src/stories/Button.stories.tsx deleted file mode 100644 index 23c3f2e7077f1..0000000000000 --- a/apps/vr-tests-react-components/src/stories/Button.stories.tsx +++ /dev/null @@ -1,569 +0,0 @@ -import { storiesOf } from '@storybook/react'; -import * as React from 'react'; -import Screener from 'screener-storybook/src/screener'; -import { Button, CompoundButton, ToggleButton, MenuButton } from '@fluentui/react-button'; -import { bundleIcon, CalendarMonthFilled, CalendarMonthRegular } from '@fluentui/react-icons'; -import { makeStyles } from '@griffel/react'; - -const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular); - -const steps = new Screener.Steps() - .snapshot('default', { cropTo: '.testWrapper' }) - .hover('#button-id') - .snapshot('hover', { cropTo: '.testWrapper' }) - .mouseDown('#button-id') - .snapshot('pressed', { cropTo: '.testWrapper' }) - .end(); - -const buttonId = 'button-id'; - -const useStyles = makeStyles({ - longText: { - width: '280px', - }, -}); - -storiesOf('Button Converged', module) - .addDecorator(story => {story()}) - .addStory('Default', () => , { - includeRtl: true, - includeHighContrast: true, - includeDarkMode: true, - }) - .addStory('Circular', () => ( - - )) - .addStory('Outline', () => ( - - )) - .addStory( - 'Primary', - () => ( - - ), - { - includeHighContrast: true, - includeDarkMode: true, - }, - ) - .addStory( - 'Subtle', - () => ( - - ), - { - includeHighContrast: true, - includeDarkMode: true, - }, - ) - .addStory( - 'Transparent', - () => ( - - ), - { - includeHighContrast: true, - includeDarkMode: true, - }, - ) - .addStory( - 'Disabled', - () => ( - - ), - { - includeHighContrast: true, - includeDarkMode: true, - }, - ) - .addStory( - 'Outline Disabled', - () => ( - - ), - { - includeHighContrast: true, - includeDarkMode: true, - }, - ) - .addStory( - 'Primary Disabled', - () => ( - - ), - { includeHighContrast: true, includeDarkMode: true }, - ) - .addStory( - 'Subtle Disabled', - () => ( - - ), - { includeHighContrast: true, includeDarkMode: true }, - ) - .addStory( - 'Transparent Disabled', - () => ( - - ), - { includeHighContrast: true, includeDarkMode: true }, - ) - .addStory('Size small', () => ( - - )) - .addStory('Size large', () => ( - - )) - .addStory('Size small - with long text wrapping', () => { - const styles = useStyles(); - return ( - - ); - }) - .addStory('Size medium - with long text wrapping', () => { - const styles = useStyles(); - return ( - - ); - }) - .addStory('Size large - with long text wrapping', () => { - const styles = useStyles(); - return ( - - ); - }) - .addStory( - 'With icon before content', - () => ( - - ), - { - includeRtl: true, - }, - ) - .addStory( - 'With icon after content', - () => ( - - ), - { includeRtl: true }, - ) - .addStory('Icon only', () => ; + +export const DefaultRTL = getStoryVariant(Default, RTL); +export const DefaultHighContrast = getStoryVariant(Default, HIGH_CONTRAST); +export const DefaultDarkMode = getStoryVariant(Default, DARK_MODE); + +export const Circular = () => ( + +); + +export const Outline = () => ( + +); + +export const Primary = () => ( + +); + +export const PrimaryHighContrast = getStoryVariant(Primary, HIGH_CONTRAST); +export const PrimaryDarkMode = getStoryVariant(Primary, DARK_MODE); + +export const Subtle = () => ( + +); + +export const SubtleHighContrast = getStoryVariant(Subtle, HIGH_CONTRAST); +export const SubtleDarkMode = getStoryVariant(Subtle, DARK_MODE); + +export const Transparent = () => ( + +); + +export const TransparentHighContrast = getStoryVariant(Transparent, HIGH_CONTRAST); +export const TransparentDarkMode = getStoryVariant(Transparent, DARK_MODE); + +export const Disabled = () => ( + +); + +export const DisabledHighContrast = getStoryVariant(Disabled, HIGH_CONTRAST); +export const DisabledDarkMode = getStoryVariant(Disabled, DARK_MODE); + +export const OutlineDisabled = () => ( + +); + +export const OutlineDisabledHighContrast = getStoryVariant(OutlineDisabled, HIGH_CONTRAST); +export const OutlineDisabledDarkMode = getStoryVariant(OutlineDisabled, DARK_MODE); + +export const PrimaryDisabled = () => ( + +); + +export const PrimaryDisabledHighContrast = getStoryVariant(PrimaryDisabled, HIGH_CONTRAST); +export const PrimaryDisabledDarkMode = getStoryVariant(PrimaryDisabled, DARK_MODE); + +export const SubtleDisabled = () => ( + +); + +export const SubtleDisabledHighContrast = getStoryVariant(SubtleDisabled, HIGH_CONTRAST); +export const SubtleDisabledDarkMode = getStoryVariant(SubtleDisabled, DARK_MODE); + +export const TransparentDisabled = () => ( + +); + +export const TransparentDisabledHighContrast = getStoryVariant(TransparentDisabled, HIGH_CONTRAST); +export const TransparentDisabledDarkMode = getStoryVariant(TransparentDisabled, DARK_MODE); + +export const SizeSmall = () => ( + +); + +SizeSmall.storyName = 'Size small'; + +export const SizeLarge = () => ( + +); + +SizeLarge.storyName = 'Size large'; + +export const SizeSmallWithLongTextWrapping = () => { + const styles = useStyles(); + return ( + + ); +}; + +SizeSmallWithLongTextWrapping.storyName = 'Size small - with long text wrapping'; + +export const SizeMediumWithLongTextWrapping = () => { + const styles = useStyles(); + return ( + + ); +}; + +SizeMediumWithLongTextWrapping.storyName = 'Size medium - with long text wrapping'; + +export const SizeLargeWithLongTextWrapping = () => { + const styles = useStyles(); + return ( + + ); +}; + +SizeLargeWithLongTextWrapping.storyName = 'Size large - with long text wrapping'; + +export const WithIconBeforeContent = () => ( + +); + +WithIconBeforeContent.storyName = 'With icon before content'; + +export const WithIconBeforeContentRTL = getStoryVariant(WithIconBeforeContent, RTL); + +export const WithIconAfterContent = () => ( + +); + +WithIconAfterContent.storyName = 'With icon after content'; + +export const WithIconAfterContentRTL = getStoryVariant(WithIconAfterContent, RTL); + +export const IconOnly = () => ; export const DefaultRTL = getStoryVariant(Default, RTL); -export const DefaultHighContrast = getStoryVariant(Default, HIGH_CONTRAST); export const DefaultDarkMode = getStoryVariant(Default, DARK_MODE); +export const DefaultHighContrast = getStoryVariant(Default, HIGH_CONTRAST); export const Circular = () => ( ; + +export const ButtonDarkMode = { + render: Button, + parameters: { variant: DARK_MODE }, // story renders in Dark mode. +}; + +export const ButtonHighContrast = { + render: Button, + parameters: { variant: HIGH_CONTRAST }; // story renders in High Contrast mode. +} + +export const ButtonRTL = { + render: Button, + parameters: { variant: RTL }, // story renders in RTL. +}; + ``` From 794bd7f6fbc9c96db7818b54d2fe356356e018b0 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Mon, 10 Oct 2022 15:11:35 -0700 Subject: [PATCH 16/53] remove unneed peerDep --- packages/react-components/react-storybook/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/react-components/react-storybook/package.json b/packages/react-components/react-storybook/package.json index 290b65ba83ad4..434ee71641d77 100644 --- a/packages/react-components/react-storybook/package.json +++ b/packages/react-components/react-storybook/package.json @@ -36,8 +36,7 @@ "@types/react": ">=16.8.0 <18.0.0", "react": ">=16.8.0 <18.0.0", "@storybook/addon-knobs": "^6.0.28", - "@storybook/addons": "^6.0.28", - "@storybook/react": "^6.5.5" + "@storybook/addons": "^6.0.28" }, "beachball": { "disallowedChangeTypes": [ From f3068462f8eb3c66df12f4c82b09971b403e6f3c Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Mon, 10 Oct 2022 16:03:03 -0700 Subject: [PATCH 17/53] fix: typing --- .../src/decorators/withFluentVrTestVariants.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-components/react-storybook/src/decorators/withFluentVrTestVariants.tsx b/packages/react-components/react-storybook/src/decorators/withFluentVrTestVariants.tsx index ec430031650f4..bced594168eb3 100644 --- a/packages/react-components/react-storybook/src/decorators/withFluentVrTestVariants.tsx +++ b/packages/react-components/react-storybook/src/decorators/withFluentVrTestVariants.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import { FluentProvider } from '@fluentui/react-provider'; import { teamsHighContrastTheme, webDarkTheme, webLightTheme } from '@fluentui/react-theme'; -import { makeDecorator, DecoratorFunction } from '@storybook/addons'; -import type { StoryContext } from '@storybook/react'; +import { makeDecorator } from '@storybook/addons'; +import type { StoryContext } from '@storybook/addons'; export const DARK_MODE = 'DarkMode'; export const HIGH_CONTRAST = 'HighContrast'; @@ -27,7 +27,7 @@ type AssertedMakeDecorator = ({ parameterName, skipIfNoParametersOrOptions, wrapper, -}: AssertedMakeDecoratorOptions) => DecoratorFunction; +}: AssertedMakeDecoratorOptions) => () => React.ReactNode; export const withFluentVrTestVariants = ((makeDecorator as unknown) as AssertedMakeDecorator)({ name: 'withFluentVrTestVariants.', From fb87708ab46c08f137d00166a5293b5af2e62204 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Mon, 10 Oct 2022 16:03:22 -0700 Subject: [PATCH 18/53] Update API --- .../react-storybook/etc/react-storybook.api.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/react-components/react-storybook/etc/react-storybook.api.md b/packages/react-components/react-storybook/etc/react-storybook.api.md index 1290f16b5b06a..a78d1619f159d 100644 --- a/packages/react-components/react-storybook/etc/react-storybook.api.md +++ b/packages/react-components/react-storybook/etc/react-storybook.api.md @@ -4,7 +4,6 @@ ```ts -import { DecoratorFunction } from '@storybook/addons'; import * as React_2 from 'react'; // @public (undocumented) @@ -20,7 +19,7 @@ export const RTL = "Rtl"; export const withFluentProvider: (...args: any) => any; // @public (undocumented) -export const withFluentVrTestVariants: DecoratorFunction; +export const withFluentVrTestVariants: () => React_2.ReactNode; // @public (undocumented) export const withStrictMode: (storyFn: () => React_2.ReactNode) => JSX.Element; From 7bf18738bc1378b1e1bfa5e800dd3248879d5ede Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Wed, 12 Oct 2022 11:42:11 -0700 Subject: [PATCH 19/53] revert additions to react-storybook package --- .../decorators/withFluentVrTestVariants.tsx | 80 +++++++++++++++++++ .../react-storybook/src/decorators/index.ts | 1 - .../react-storybook/src/index.test.ts | 4 +- .../react-storybook/src/index.ts | 9 +-- 4 files changed, 83 insertions(+), 11 deletions(-) create mode 100644 packages/react-components/react-storybook-addon/src/decorators/withFluentVrTestVariants.tsx diff --git a/packages/react-components/react-storybook-addon/src/decorators/withFluentVrTestVariants.tsx b/packages/react-components/react-storybook-addon/src/decorators/withFluentVrTestVariants.tsx new file mode 100644 index 0000000000000..5efc1159b6df1 --- /dev/null +++ b/packages/react-components/react-storybook-addon/src/decorators/withFluentVrTestVariants.tsx @@ -0,0 +1,80 @@ +import * as React from 'react'; +import { FluentProvider } from '@fluentui/react-provider'; +import { teamsHighContrastTheme, webDarkTheme, webLightTheme } from '@fluentui/react-theme'; +import { makeDecorator } from '@storybook/addons'; +import type { StoryContext } from '@storybook/addons'; +import { useParameter } from '@storybook/api'; + +export const DARK_MODE = 'DarkMode'; +export const HIGH_CONTRAST = 'HighContrast'; +export const RTL = 'Rtl'; + +// MakeDecoratorOptions is not an exported interface by storybook so had to include necessary options +interface AssertedMakeDecoratorOptions { + name: string; + parameterName: string; + skipIfNoParametersOrOptions?: boolean; + wrapper: ( + storyFn: (context: StoryContext) => React.ReactNode, + context: StoryContext, + settings: { + parameters: typeof DARK_MODE | typeof HIGH_CONTRAST | typeof RTL; + }, + ) => React.ReactNode; +} + +type AssertedMakeDecorator = ({ + name, + parameterName, + skipIfNoParametersOrOptions, + wrapper, +}: AssertedMakeDecoratorOptions) => () => React.ReactNode; + +// export const withFluentVrTestVariants = ((makeDecorator as unknown) as AssertedMakeDecorator)({ +// name: 'withFluentVrTestVariants.', +// parameterName: 'vrTestVariant', +// skipIfNoParametersOrOptions: true, +// wrapper: (storyFn, context, { parameters }) => { +// console.log('parameter ', parameters); +// if (parameters === RTL) { +// return ( +// +// {storyFn(context)} +// +// ); +// } + +// if (parameters === DARK_MODE) { +// return {storyFn(context)}; +// } + +// if (parameters === HIGH_CONTRAST) { +// return {storyFn(context)}; +// } + +// return storyFn(context); +// }, +// }); + +export const withFluentVrTestVariants = (storyFn: () => JSX.Element, context: StoryContext) => { + const { variant } = context.parameters; + + // console.log('context', context); + if (variant === RTL) { + return ( + + {storyFn()} + + ); + } + + if (variant === DARK_MODE) { + return {storyFn()}; + } + + if (variant === HIGH_CONTRAST) { + return {storyFn()}; + } + + return storyFn(); +}; diff --git a/packages/react-components/react-storybook/src/decorators/index.ts b/packages/react-components/react-storybook/src/decorators/index.ts index fc01a36add316..ff044dce8afc1 100644 --- a/packages/react-components/react-storybook/src/decorators/index.ts +++ b/packages/react-components/react-storybook/src/decorators/index.ts @@ -1,3 +1,2 @@ export * from './withFluentProvider'; export * from './withStrictMode'; -export * from './withFluentVrTestVariants'; diff --git a/packages/react-components/react-storybook/src/index.test.ts b/packages/react-components/react-storybook/src/index.test.ts index b43c19d8229ea..3f2fe8451a862 100644 --- a/packages/react-components/react-storybook/src/index.test.ts +++ b/packages/react-components/react-storybook/src/index.test.ts @@ -1,9 +1,9 @@ -import { withFluentProvider, withFluentVrTestVariants, withStrictMode } from './index'; +import { withFluentProvider, withStrictMode } from './index'; describe(`public api`, () => { describe(`decorators`, () => { it(`should work`, () => { - const decorators = [withFluentProvider, withStrictMode, withFluentVrTestVariants]; + const decorators = [withFluentProvider, withStrictMode]; // @TODO - added proper tests expect(decorators).toBeDefined(); diff --git a/packages/react-components/react-storybook/src/index.ts b/packages/react-components/react-storybook/src/index.ts index a24f21148fefc..0a74f9e478521 100644 --- a/packages/react-components/react-storybook/src/index.ts +++ b/packages/react-components/react-storybook/src/index.ts @@ -1,8 +1 @@ -export { - withFluentProvider, - withStrictMode, - withFluentVrTestVariants, - DARK_MODE, - HIGH_CONTRAST, - RTL, -} from './decorators/index'; +export { withFluentProvider, withStrictMode } from './decorators/index'; From ed168ee6ee2f8b54993be9f0a5ac6262464cb761 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Wed, 12 Oct 2022 11:48:45 -0700 Subject: [PATCH 20/53] delete withFluentVrTestVariants --- .../src/decorators/withFluentProvider.tsx | 22 ++++++-- .../decorators/withFluentVrTestVariants.tsx | 55 ------------------- 2 files changed, 16 insertions(+), 61 deletions(-) delete mode 100644 packages/react-components/react-storybook/src/decorators/withFluentVrTestVariants.tsx diff --git a/packages/react-components/react-storybook-addon/src/decorators/withFluentProvider.tsx b/packages/react-components/react-storybook-addon/src/decorators/withFluentProvider.tsx index 7132f18de9f27..2a0b3419f6950 100644 --- a/packages/react-components/react-storybook-addon/src/decorators/withFluentProvider.tsx +++ b/packages/react-components/react-storybook-addon/src/decorators/withFluentProvider.tsx @@ -2,23 +2,33 @@ import * as React from 'react'; import { FluentProvider } from '@fluentui/react-provider'; import { Theme } from '@fluentui/react-theme'; - -import { themes, defaultTheme } from '../theme'; +import { themes, defaultTheme, ThemeIds } from '../theme'; import { THEME_ID } from '../constants'; import { FluentGlobals, FluentStoryContext } from '../hooks'; +const findTheme = (themeId?: ThemeIds) => { + if (!themeId) { + return; + } + return themes.find(value => value.id === themeId); +}; + const getActiveFluentTheme = (globals: FluentGlobals) => { const selectedThemeId = globals[THEME_ID]; - const { theme } = themes.find(value => value.id === selectedThemeId) ?? defaultTheme; + const { theme } = findTheme(selectedThemeId) ?? defaultTheme; return { theme }; }; export const withFluentProvider = (StoryFn: () => JSX.Element, context: FluentStoryContext) => { - const { theme } = getActiveFluentTheme(context.globals); + const { globals, parameters } = context; + + const globalTheme = getActiveFluentTheme(globals); + const paramTheme = findTheme(parameters.fluentTheme) ?? undefined; + const { theme } = paramTheme ?? globalTheme; return ( - + {StoryFn()} ); @@ -28,5 +38,5 @@ const FluentExampleContainer: React.FC<{ theme: Theme }> = props => { const { theme } = props; const backgroundColor = theme.colorNeutralBackground2; - return
{props.children}
; + return
{props.children}
; }; diff --git a/packages/react-components/react-storybook/src/decorators/withFluentVrTestVariants.tsx b/packages/react-components/react-storybook/src/decorators/withFluentVrTestVariants.tsx deleted file mode 100644 index bced594168eb3..0000000000000 --- a/packages/react-components/react-storybook/src/decorators/withFluentVrTestVariants.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import * as React from 'react'; -import { FluentProvider } from '@fluentui/react-provider'; -import { teamsHighContrastTheme, webDarkTheme, webLightTheme } from '@fluentui/react-theme'; -import { makeDecorator } from '@storybook/addons'; -import type { StoryContext } from '@storybook/addons'; - -export const DARK_MODE = 'DarkMode'; -export const HIGH_CONTRAST = 'HighContrast'; -export const RTL = 'Rtl'; - -// MakeDecoratorOptions is not an exported interface by storybook so had to include necessary options -interface AssertedMakeDecoratorOptions { - name: string; - parameterName: string; - skipIfNoParametersOrOptions?: boolean; - wrapper: ( - storyFn: (context: StoryContext) => React.ReactNode, - context: StoryContext, - settings: { - parameters: typeof DARK_MODE | typeof HIGH_CONTRAST | typeof RTL; - }, - ) => React.ReactNode; -} - -type AssertedMakeDecorator = ({ - name, - parameterName, - skipIfNoParametersOrOptions, - wrapper, -}: AssertedMakeDecoratorOptions) => () => React.ReactNode; - -export const withFluentVrTestVariants = ((makeDecorator as unknown) as AssertedMakeDecorator)({ - name: 'withFluentVrTestVariants.', - parameterName: 'vrTestVariant', - skipIfNoParametersOrOptions: true, - wrapper: (storyFn, context, { parameters }) => { - if (parameters === RTL) { - return ( - - {storyFn(context)} - - ); - } - - if (parameters === DARK_MODE) { - return {storyFn(context)}; - } - - if (parameters === HIGH_CONTRAST) { - return {storyFn(context)}; - } - - return storyFn(context); - }, -}); From d3765acfd699ac7a6e47d041ba9fdfa6137b97a5 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Wed, 12 Oct 2022 11:52:59 -0700 Subject: [PATCH 21/53] remove withFluentVrTestVariant --- .../decorators/withFluentVrTestVariants.tsx | 80 ------------------- 1 file changed, 80 deletions(-) delete mode 100644 packages/react-components/react-storybook-addon/src/decorators/withFluentVrTestVariants.tsx diff --git a/packages/react-components/react-storybook-addon/src/decorators/withFluentVrTestVariants.tsx b/packages/react-components/react-storybook-addon/src/decorators/withFluentVrTestVariants.tsx deleted file mode 100644 index 5efc1159b6df1..0000000000000 --- a/packages/react-components/react-storybook-addon/src/decorators/withFluentVrTestVariants.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import * as React from 'react'; -import { FluentProvider } from '@fluentui/react-provider'; -import { teamsHighContrastTheme, webDarkTheme, webLightTheme } from '@fluentui/react-theme'; -import { makeDecorator } from '@storybook/addons'; -import type { StoryContext } from '@storybook/addons'; -import { useParameter } from '@storybook/api'; - -export const DARK_MODE = 'DarkMode'; -export const HIGH_CONTRAST = 'HighContrast'; -export const RTL = 'Rtl'; - -// MakeDecoratorOptions is not an exported interface by storybook so had to include necessary options -interface AssertedMakeDecoratorOptions { - name: string; - parameterName: string; - skipIfNoParametersOrOptions?: boolean; - wrapper: ( - storyFn: (context: StoryContext) => React.ReactNode, - context: StoryContext, - settings: { - parameters: typeof DARK_MODE | typeof HIGH_CONTRAST | typeof RTL; - }, - ) => React.ReactNode; -} - -type AssertedMakeDecorator = ({ - name, - parameterName, - skipIfNoParametersOrOptions, - wrapper, -}: AssertedMakeDecoratorOptions) => () => React.ReactNode; - -// export const withFluentVrTestVariants = ((makeDecorator as unknown) as AssertedMakeDecorator)({ -// name: 'withFluentVrTestVariants.', -// parameterName: 'vrTestVariant', -// skipIfNoParametersOrOptions: true, -// wrapper: (storyFn, context, { parameters }) => { -// console.log('parameter ', parameters); -// if (parameters === RTL) { -// return ( -// -// {storyFn(context)} -// -// ); -// } - -// if (parameters === DARK_MODE) { -// return {storyFn(context)}; -// } - -// if (parameters === HIGH_CONTRAST) { -// return {storyFn(context)}; -// } - -// return storyFn(context); -// }, -// }); - -export const withFluentVrTestVariants = (storyFn: () => JSX.Element, context: StoryContext) => { - const { variant } = context.parameters; - - // console.log('context', context); - if (variant === RTL) { - return ( - - {storyFn()} - - ); - } - - if (variant === DARK_MODE) { - return {storyFn()}; - } - - if (variant === HIGH_CONTRAST) { - return {storyFn()}; - } - - return storyFn(); -}; From 1f26987d978f866c1c5b259b06d02e3d07fb6673 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Wed, 12 Oct 2022 12:18:24 -0700 Subject: [PATCH 22/53] feat: withFluentProvider now accepts fluentTheme and dir --- .../react-storybook-addon/src/components/ThemePicker.tsx | 7 +++++-- .../react-components/react-storybook-addon/src/hooks.ts | 8 +++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/react-components/react-storybook-addon/src/components/ThemePicker.tsx b/packages/react-components/react-storybook-addon/src/components/ThemePicker.tsx index 8d06603b3e645..d48dbf24dac82 100644 --- a/packages/react-components/react-storybook-addon/src/components/ThemePicker.tsx +++ b/packages/react-components/react-storybook-addon/src/components/ThemePicker.tsx @@ -1,9 +1,10 @@ import * as React from 'react'; import { IconButton, Icons, TooltipLinkList, WithTooltip } from '@storybook/components'; +import { useParameter } from '@storybook/api'; import { ThemeIds, themes, defaultTheme } from '../theme'; import { THEME_ID } from '../constants'; -import { useGlobals } from '../hooks'; +import { useGlobals, FluentParameters } from '../hooks'; export interface ThemeSelectorItem { id: string; @@ -33,7 +34,9 @@ function createThemeItems( export const ThemePicker = () => { const [globals, updateGlobals] = useGlobals(); - const selectedThemeId = globals[THEME_ID] ?? defaultTheme.id; + const fluentTheme: FluentParameters['fluentTheme'] = useParameter('fluentTheme'); + + const selectedThemeId = fluentTheme ? fluentTheme : globals[THEME_ID] ?? defaultTheme.id; const selectedTheme = themes.find(entry => entry.id === selectedThemeId); const isActive = selectedThemeId !== defaultTheme.id; diff --git a/packages/react-components/react-storybook-addon/src/hooks.ts b/packages/react-components/react-storybook-addon/src/hooks.ts index 649100df48ae8..0254f22f609f3 100644 --- a/packages/react-components/react-storybook-addon/src/hooks.ts +++ b/packages/react-components/react-storybook-addon/src/hooks.ts @@ -1,4 +1,4 @@ -import { useGlobals as useStorybookGlobals, Args as StorybookArgs } from '@storybook/api'; +import { useGlobals as useStorybookGlobals, Args as StorybookArgs, Parameters } from '@storybook/api'; import { StoryContext as StorybookContext } from '@storybook/addons'; import { THEME_ID } from './constants'; @@ -6,6 +6,7 @@ import { ThemeIds } from './theme'; export interface FluentStoryContext extends StorybookContext { globals: FluentGlobals; + parameters: FluentParameters; } /** @@ -18,3 +19,8 @@ export interface FluentGlobals extends StorybookArgs { export function useGlobals(): [FluentGlobals, (newGlobals: FluentGlobals) => void] { return useStorybookGlobals(); } + +export interface FluentParameters extends Parameters { + fluentTheme: ThemeIds; + dir: 'ltr' | 'rtl'; +} From 66c95ef92034ce3c4de6a02c7d00d4da143121ca Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Wed, 12 Oct 2022 12:35:30 -0700 Subject: [PATCH 23/53] Add exported theme constants --- .../react-storybook-addon/src/theme.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/react-components/react-storybook-addon/src/theme.ts b/packages/react-components/react-storybook-addon/src/theme.ts index 52484c9306368..447342ad141ee 100644 --- a/packages/react-components/react-storybook-addon/src/theme.ts +++ b/packages/react-components/react-storybook-addon/src/theme.ts @@ -8,12 +8,18 @@ import { import type { Theme } from '@fluentui/react-theme'; +export const WEB_LIGHT = 'web-light'; +export const WEB_DARK = 'web-dark'; +export const TEAMS_LIGHT = 'teams-light'; +export const TEAMS_DARK = 'teams-dark'; +export const TEAMS_HIGH_CONTRAST = 'teams-high-contrast'; + export const themes = [ - { id: 'web-light', label: 'Web Light', theme: webLightTheme }, - { id: 'web-dark', label: 'Web Dark', theme: webDarkTheme }, - { id: 'teams-light', label: 'Teams Light', theme: teamsLightTheme }, - { id: 'teams-dark', label: 'Teams Dark', theme: teamsDarkTheme }, - { id: 'teams-high-contrast', label: 'Teams High Contrast', theme: teamsHighContrastTheme }, + { id: WEB_LIGHT, label: 'Web Light', theme: webLightTheme }, + { id: WEB_DARK, label: 'Web Dark', theme: webDarkTheme }, + { id: TEAMS_LIGHT, label: 'Teams Light', theme: teamsLightTheme }, + { id: TEAMS_DARK, label: 'Teams Dark', theme: teamsDarkTheme }, + { id: TEAMS_HIGH_CONTRAST, label: 'Teams High Contrast', theme: teamsHighContrastTheme }, ] as const; export const defaultTheme = themes[0]; From ab22cd51fa4c424b464b18065f721b6415247feb Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Thu, 13 Oct 2022 03:33:20 -0700 Subject: [PATCH 24/53] feat: add isVrTest parameter --- .../src/decorators/withFluentProvider.tsx | 6 +++--- .../react-storybook-addon/src/hooks.ts | 16 ++++++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/react-components/react-storybook-addon/src/decorators/withFluentProvider.tsx b/packages/react-components/react-storybook-addon/src/decorators/withFluentProvider.tsx index 2a0b3419f6950..f79427b6fab7f 100644 --- a/packages/react-components/react-storybook-addon/src/decorators/withFluentProvider.tsx +++ b/packages/react-components/react-storybook-addon/src/decorators/withFluentProvider.tsx @@ -22,14 +22,14 @@ const getActiveFluentTheme = (globals: FluentGlobals) => { export const withFluentProvider = (StoryFn: () => JSX.Element, context: FluentStoryContext) => { const { globals, parameters } = context; - + const { isVrTest } = parameters; const globalTheme = getActiveFluentTheme(globals); - const paramTheme = findTheme(parameters.fluentTheme) ?? undefined; + const paramTheme = findTheme(parameters.fluentTheme); const { theme } = paramTheme ?? globalTheme; return ( - {StoryFn()} + {isVrTest ? StoryFn() : {StoryFn()}} ); }; diff --git a/packages/react-components/react-storybook-addon/src/hooks.ts b/packages/react-components/react-storybook-addon/src/hooks.ts index 0254f22f609f3..26c19856de549 100644 --- a/packages/react-components/react-storybook-addon/src/hooks.ts +++ b/packages/react-components/react-storybook-addon/src/hooks.ts @@ -10,17 +10,21 @@ export interface FluentStoryContext extends StorybookContext { } /** - * Extends the storybook globals object to include fluent specific propoerties + * Extends the storybook globals object to include fluent specific properties */ export interface FluentGlobals extends StorybookArgs { [THEME_ID]?: ThemeIds; } -export function useGlobals(): [FluentGlobals, (newGlobals: FluentGlobals) => void] { - return useStorybookGlobals(); +/** + * Extends the storybook parameters object to include fluent specific properties + */ +export interface FluentParameters extends Parameters { + dir?: 'ltr' | 'rtl'; + fluentTheme?: ThemeIds; + isVrTest?: boolean; } -export interface FluentParameters extends Parameters { - fluentTheme: ThemeIds; - dir: 'ltr' | 'rtl'; +export function useGlobals(): [FluentGlobals, (newGlobals: FluentGlobals) => void] { + return useStorybookGlobals(); } From 060d69623e580aeb8ed280e5370a6bb8300ce906 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Thu, 13 Oct 2022 03:34:07 -0700 Subject: [PATCH 25/53] Revert "Add usage of decorator to README" This reverts commit dcfcde39f3c7dfac22ecb96bc133c511e61a6adf. --- .../react-storybook/README.md | 29 ++----------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/packages/react-components/react-storybook/README.md b/packages/react-components/react-storybook/README.md index 64607466e8d42..bdc825fa64b22 100644 --- a/packages/react-components/react-storybook/README.md +++ b/packages/react-components/react-storybook/README.md @@ -22,33 +22,8 @@ You need to register fluentui decorators on your particular level (global/story/ // @filename: .storybook/preview.js import { withKnobs } from '@storybook/addon-knobs'; -import { withStrictMode, withFluentVrTestVariants } from '@fluentui/react-storybook'; +import { withStrictMode } from '@fluentui/react-storybook'; // Register decorators on global level -export const decorators = [withKnobs, withStrictMode, withFluentVrTestVariants]; -``` - -## withFluentVrTestVariants: - -```js -import { withFluentVrTestVariants, DARK_MODE, HIGH_CONTRAST, RTL } from '@fluentui/react-storybook'; -import { Button } from '@fluentui/react-components'; - -export const Button = () => ; - -export const ButtonDarkMode = { - render: Button, - parameters: { variant: DARK_MODE }, // story renders in Dark mode. -}; - -export const ButtonHighContrast = { - render: Button, - parameters: { variant: HIGH_CONTRAST }; // story renders in High Contrast mode. -} - -export const ButtonRTL = { - render: Button, - parameters: { variant: RTL }, // story renders in RTL. -}; - +export const decorators = [withKnobs, withStrictMode]; ``` From 18c3e6d2551e137a3f64b183b96420f027e2d67e Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Thu, 13 Oct 2022 03:48:09 -0700 Subject: [PATCH 26/53] update ReadMe --- .../react-storybook-addon/README.md | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/packages/react-components/react-storybook-addon/README.md b/packages/react-components/react-storybook-addon/README.md index 452ce80d947b8..1e95d5ecc715f 100644 --- a/packages/react-components/react-storybook-addon/README.md +++ b/packages/react-components/react-storybook-addon/README.md @@ -68,3 +68,34 @@ module.exports = { - > 💡 this will run `prestorybook` script that compiles addon implementation with all of its direct dependencies that live within monorepo, so it can be consumed by local storybook 2. Every time you do any change to implementation, after you ran your local storybook you'll need to manually run `yarn workspace @fluentui/react-storybook-addon build` to reflect those changes + +## Parameter Configuration + +- Three custom optional parameters can be set to alter behavior of the addon + 1. `dir` - determines whether to render story in `ltr` or `rtl` mode. Default is `undefined`. + 2. `fluentTheme` - determines whether to render story theme in `web-light`, `web-dark`, `teams-high-contrast`, `teams-dark`, or `teams-light`. Setting this + parameter will disable ability to dynamically change the theme within story canvas or doc. + 3. `isVrTest` - when set to `true`, this removes injected padding and background theme that's automatically applied from rendered story. + +```js +import { TEAMS_HIGH_CONTRAST, WEB_DARK, WEB_LIGHT } from '@fluentui/react-storybook-addon'; +import { Button } from '@fluentui/react-components'; + +export const Button = () => ; + +export const ButtonDarkMode = { + render: Button, + parameters: { fluentTheme: WEB_DARK }, // story renders in Dark mode. +}; + +export const ButtonHighContrast = { + render: Button, + parameters: { fluentTheme: TEAMS_HIGH_CONTRAST, isVrTest: true }; // story renders in High Contrast mode without injected padding and background style. +} + +export const ButtonRTL = { + render: Button, + parameters: { fluentTheme: WEB_LIGHT, dir: 'rtl', isVrTest: true}, // story renders in RTL, Web light mode and without injected padding and background style. +}; + +``` From 14847d92f4bd6910a7d0c5f3f65918f6b5878d23 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Thu, 13 Oct 2022 03:54:10 -0700 Subject: [PATCH 27/53] Add constants and FluentParameters to exports --- packages/react-components/react-storybook-addon/src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-components/react-storybook-addon/src/index.ts b/packages/react-components/react-storybook-addon/src/index.ts index ecb1744ced790..4a5bdd736135a 100644 --- a/packages/react-components/react-storybook-addon/src/index.ts +++ b/packages/react-components/react-storybook-addon/src/index.ts @@ -1,4 +1,4 @@ -export type { FluentGlobals, FluentStoryContext } from './hooks'; +export type { FluentGlobals, FluentParameters, FluentStoryContext } from './hooks'; export type { ThemeIds } from './theme'; -export { themes } from './theme'; +export { themes, TEAMS_DARK, TEAMS_HIGH_CONTRAST, TEAMS_LIGHT, WEB_DARK, WEB_LIGHT } from './theme'; export { THEME_ID } from './constants'; From 20091d7bb91074ebfe0742b1946ab5391ecd95bf Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Thu, 13 Oct 2022 03:55:38 -0700 Subject: [PATCH 28/53] Update API --- .../etc/react-storybook-addon.api.md | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md b/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md index c9d140b21ddb9..a60d1b5abd541 100644 --- a/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md +++ b/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md @@ -5,6 +5,7 @@ ```ts import { Args } from '@storybook/api'; +import { Parameters as Parameters_2 } from '@storybook/api'; import { StoryContext } from '@storybook/addons'; import type { Theme } from '@fluentui/react-theme'; @@ -14,12 +15,33 @@ export interface FluentGlobals extends Args { [THEME_ID]?: ThemeIds; } +// @public +export interface FluentParameters extends Parameters_2 { + // (undocumented) + dir?: 'ltr' | 'rtl'; + // (undocumented) + fluentTheme?: ThemeIds; + // (undocumented) + isVrTest?: boolean; +} + // @public (undocumented) export interface FluentStoryContext extends StoryContext { // (undocumented) globals: FluentGlobals; + // (undocumented) + parameters: FluentParameters; } +// @public (undocumented) +export const TEAMS_DARK = "teams-dark"; + +// @public (undocumented) +export const TEAMS_HIGH_CONTRAST = "teams-high-contrast"; + +// @public (undocumented) +export const TEAMS_LIGHT = "teams-light"; + // @public (undocumented) export const THEME_ID: "storybook/fluentui-react-addon/theme"; @@ -49,6 +71,12 @@ export const themes: readonly [{ readonly theme: Theme; }]; +// @public (undocumented) +export const WEB_DARK = "web-dark"; + +// @public (undocumented) +export const WEB_LIGHT = "web-light"; + // (No @packageDocumentation comment for this package) ``` From e840ba7141db7df3b5db18eae095275e84306200 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Thu, 13 Oct 2022 03:56:50 -0700 Subject: [PATCH 29/53] Revert "Update API" This reverts commit fb87708ab46c08f137d00166a5293b5af2e62204. --- .../react-storybook/etc/react-storybook.api.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/react-components/react-storybook/etc/react-storybook.api.md b/packages/react-components/react-storybook/etc/react-storybook.api.md index a78d1619f159d..1290f16b5b06a 100644 --- a/packages/react-components/react-storybook/etc/react-storybook.api.md +++ b/packages/react-components/react-storybook/etc/react-storybook.api.md @@ -4,6 +4,7 @@ ```ts +import { DecoratorFunction } from '@storybook/addons'; import * as React_2 from 'react'; // @public (undocumented) @@ -19,7 +20,7 @@ export const RTL = "Rtl"; export const withFluentProvider: (...args: any) => any; // @public (undocumented) -export const withFluentVrTestVariants: () => React_2.ReactNode; +export const withFluentVrTestVariants: DecoratorFunction; // @public (undocumented) export const withStrictMode: (storyFn: () => React_2.ReactNode) => JSX.Element; From 21eba2e5a72be790593be98154a38dc3251a9ece Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Thu, 13 Oct 2022 03:57:27 -0700 Subject: [PATCH 30/53] Revert "fix: typing and update API" This reverts commit bda9ea40291e1e694a3ff7b968b8490269a38ec9. --- .../react-storybook/etc/react-storybook.api.md | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/packages/react-components/react-storybook/etc/react-storybook.api.md b/packages/react-components/react-storybook/etc/react-storybook.api.md index 1290f16b5b06a..3b8bfcc94de54 100644 --- a/packages/react-components/react-storybook/etc/react-storybook.api.md +++ b/packages/react-components/react-storybook/etc/react-storybook.api.md @@ -3,28 +3,13 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts - -import { DecoratorFunction } from '@storybook/addons'; import * as React_2 from 'react'; -// @public (undocumented) -export const DARK_MODE = "DarkMode"; - -// @public (undocumented) -export const HIGH_CONTRAST = "HighContrast"; - -// @public (undocumented) -export const RTL = "Rtl"; - // @public (undocumented) export const withFluentProvider: (...args: any) => any; -// @public (undocumented) -export const withFluentVrTestVariants: DecoratorFunction; - // @public (undocumented) export const withStrictMode: (storyFn: () => React_2.ReactNode) => JSX.Element; // (No @packageDocumentation comment for this package) - ``` From 81de5233d94b8fa35eb180143530d4392370a572 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Sun, 16 Oct 2022 04:49:58 -0700 Subject: [PATCH 31/53] feedback: don't export constants, export FluentParameter type --- .../etc/react-storybook-addon.api.md | 15 --------------- .../react-storybook-addon/src/index.ts | 2 +- .../react-storybook-addon/src/theme.ts | 16 +++++----------- 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md b/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md index a60d1b5abd541..7260db227a34f 100644 --- a/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md +++ b/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md @@ -33,15 +33,6 @@ export interface FluentStoryContext extends StoryContext { parameters: FluentParameters; } -// @public (undocumented) -export const TEAMS_DARK = "teams-dark"; - -// @public (undocumented) -export const TEAMS_HIGH_CONTRAST = "teams-high-contrast"; - -// @public (undocumented) -export const TEAMS_LIGHT = "teams-light"; - // @public (undocumented) export const THEME_ID: "storybook/fluentui-react-addon/theme"; @@ -71,12 +62,6 @@ export const themes: readonly [{ readonly theme: Theme; }]; -// @public (undocumented) -export const WEB_DARK = "web-dark"; - -// @public (undocumented) -export const WEB_LIGHT = "web-light"; - // (No @packageDocumentation comment for this package) ``` diff --git a/packages/react-components/react-storybook-addon/src/index.ts b/packages/react-components/react-storybook-addon/src/index.ts index 4a5bdd736135a..d0b55796b9660 100644 --- a/packages/react-components/react-storybook-addon/src/index.ts +++ b/packages/react-components/react-storybook-addon/src/index.ts @@ -1,4 +1,4 @@ export type { FluentGlobals, FluentParameters, FluentStoryContext } from './hooks'; export type { ThemeIds } from './theme'; -export { themes, TEAMS_DARK, TEAMS_HIGH_CONTRAST, TEAMS_LIGHT, WEB_DARK, WEB_LIGHT } from './theme'; +export { themes } from './theme'; export { THEME_ID } from './constants'; diff --git a/packages/react-components/react-storybook-addon/src/theme.ts b/packages/react-components/react-storybook-addon/src/theme.ts index 447342ad141ee..52484c9306368 100644 --- a/packages/react-components/react-storybook-addon/src/theme.ts +++ b/packages/react-components/react-storybook-addon/src/theme.ts @@ -8,18 +8,12 @@ import { import type { Theme } from '@fluentui/react-theme'; -export const WEB_LIGHT = 'web-light'; -export const WEB_DARK = 'web-dark'; -export const TEAMS_LIGHT = 'teams-light'; -export const TEAMS_DARK = 'teams-dark'; -export const TEAMS_HIGH_CONTRAST = 'teams-high-contrast'; - export const themes = [ - { id: WEB_LIGHT, label: 'Web Light', theme: webLightTheme }, - { id: WEB_DARK, label: 'Web Dark', theme: webDarkTheme }, - { id: TEAMS_LIGHT, label: 'Teams Light', theme: teamsLightTheme }, - { id: TEAMS_DARK, label: 'Teams Dark', theme: teamsDarkTheme }, - { id: TEAMS_HIGH_CONTRAST, label: 'Teams High Contrast', theme: teamsHighContrastTheme }, + { id: 'web-light', label: 'Web Light', theme: webLightTheme }, + { id: 'web-dark', label: 'Web Dark', theme: webDarkTheme }, + { id: 'teams-light', label: 'Teams Light', theme: teamsLightTheme }, + { id: 'teams-dark', label: 'Teams Dark', theme: teamsDarkTheme }, + { id: 'teams-high-contrast', label: 'Teams High Contrast', theme: teamsHighContrastTheme }, ] as const; export const defaultTheme = themes[0]; From b5f378816a1794245bd352c8c4612a222481fac1 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Sun, 16 Oct 2022 05:01:16 -0700 Subject: [PATCH 32/53] feedback: replace isVrTest param with more dynamic mode param --- .../src/decorators/withFluentProvider.tsx | 4 +++- packages/react-components/react-storybook-addon/src/hooks.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/react-components/react-storybook-addon/src/decorators/withFluentProvider.tsx b/packages/react-components/react-storybook-addon/src/decorators/withFluentProvider.tsx index f79427b6fab7f..8d513eb8961f6 100644 --- a/packages/react-components/react-storybook-addon/src/decorators/withFluentProvider.tsx +++ b/packages/react-components/react-storybook-addon/src/decorators/withFluentProvider.tsx @@ -22,7 +22,9 @@ const getActiveFluentTheme = (globals: FluentGlobals) => { export const withFluentProvider = (StoryFn: () => JSX.Element, context: FluentStoryContext) => { const { globals, parameters } = context; - const { isVrTest } = parameters; + const { mode } = parameters; + const isVrTest = mode === 'vr-test'; + const globalTheme = getActiveFluentTheme(globals); const paramTheme = findTheme(parameters.fluentTheme); const { theme } = paramTheme ?? globalTheme; diff --git a/packages/react-components/react-storybook-addon/src/hooks.ts b/packages/react-components/react-storybook-addon/src/hooks.ts index 26c19856de549..7a2d27ccc9952 100644 --- a/packages/react-components/react-storybook-addon/src/hooks.ts +++ b/packages/react-components/react-storybook-addon/src/hooks.ts @@ -22,7 +22,7 @@ export interface FluentGlobals extends StorybookArgs { export interface FluentParameters extends Parameters { dir?: 'ltr' | 'rtl'; fluentTheme?: ThemeIds; - isVrTest?: boolean; + mode?: 'default' | 'vr-test'; } export function useGlobals(): [FluentGlobals, (newGlobals: FluentGlobals) => void] { From 4842eb93b92f604ee2f7bb7ad95186520588427f Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Sun, 16 Oct 2022 05:17:28 -0700 Subject: [PATCH 33/53] feedback: add parameters identity function and export --- packages/react-components/react-storybook-addon/src/hooks.ts | 4 ++++ packages/react-components/react-storybook-addon/src/index.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/packages/react-components/react-storybook-addon/src/hooks.ts b/packages/react-components/react-storybook-addon/src/hooks.ts index 7a2d27ccc9952..ac9a7055cef9f 100644 --- a/packages/react-components/react-storybook-addon/src/hooks.ts +++ b/packages/react-components/react-storybook-addon/src/hooks.ts @@ -28,3 +28,7 @@ export interface FluentParameters extends Parameters { export function useGlobals(): [FluentGlobals, (newGlobals: FluentGlobals) => void] { return useStorybookGlobals(); } + +export function parameters(options?: FluentParameters) { + return { dir: 'ltr', fluentTheme: 'web-light', mode: 'default', ...options }; +} diff --git a/packages/react-components/react-storybook-addon/src/index.ts b/packages/react-components/react-storybook-addon/src/index.ts index d0b55796b9660..7e02b8967b3ea 100644 --- a/packages/react-components/react-storybook-addon/src/index.ts +++ b/packages/react-components/react-storybook-addon/src/index.ts @@ -2,3 +2,4 @@ export type { FluentGlobals, FluentParameters, FluentStoryContext } from './hook export type { ThemeIds } from './theme'; export { themes } from './theme'; export { THEME_ID } from './constants'; +export { parameters } from './hooks'; From 83173292245f6d44df971414a0f43547b3ce469c Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Sun, 16 Oct 2022 05:17:39 -0700 Subject: [PATCH 34/53] Update API --- .../etc/react-storybook-addon.api.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md b/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md index 7260db227a34f..02800552969e2 100644 --- a/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md +++ b/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md @@ -22,7 +22,7 @@ export interface FluentParameters extends Parameters_2 { // (undocumented) fluentTheme?: ThemeIds; // (undocumented) - isVrTest?: boolean; + mode?: 'default' | 'vr-test'; } // @public (undocumented) @@ -33,6 +33,13 @@ export interface FluentStoryContext extends StoryContext { parameters: FluentParameters; } +// @public (undocumented) +export function parameters(options?: FluentParameters): { + dir: string; + fluentTheme: string; + mode: string; +}; + // @public (undocumented) export const THEME_ID: "storybook/fluentui-react-addon/theme"; From 55836b63c0e4ba1b4fda5b16be399a696e073286 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Sun, 16 Oct 2022 05:23:30 -0700 Subject: [PATCH 35/53] Update README --- .../react-components/react-storybook-addon/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/react-components/react-storybook-addon/README.md b/packages/react-components/react-storybook-addon/README.md index 1e95d5ecc715f..a11182fce4201 100644 --- a/packages/react-components/react-storybook-addon/README.md +++ b/packages/react-components/react-storybook-addon/README.md @@ -75,27 +75,28 @@ module.exports = { 1. `dir` - determines whether to render story in `ltr` or `rtl` mode. Default is `undefined`. 2. `fluentTheme` - determines whether to render story theme in `web-light`, `web-dark`, `teams-high-contrast`, `teams-dark`, or `teams-light`. Setting this parameter will disable ability to dynamically change the theme within story canvas or doc. - 3. `isVrTest` - when set to `true`, this removes injected padding and background theme that's automatically applied from rendered story. + 3. `mode` - when set to `vr-test`, this removes injected padding and background theme that's automatically applied from rendered story. Default is `default`. ```js -import { TEAMS_HIGH_CONTRAST, WEB_DARK, WEB_LIGHT } from '@fluentui/react-storybook-addon'; +import { FluentParameters, parameters } from '@fluentui/react-storybook-addon'; import { Button } from '@fluentui/react-components'; export const Button = () => ; export const ButtonDarkMode = { render: Button, - parameters: { fluentTheme: WEB_DARK }, // story renders in Dark mode. + parameters: { fluentTheme: 'web-dark' } as FluentParameters, // story renders in Dark mode. }; export const ButtonHighContrast = { render: Button, - parameters: { fluentTheme: TEAMS_HIGH_CONTRAST, isVrTest: true }; // story renders in High Contrast mode without injected padding and background style. + parameters: { fluentTheme: 'teams-high-contrast', mode: 'vr-test' } as FluentParameters; // story renders in High Contrast mode without injected padding and background style. } export const ButtonRTL = { render: Button, - parameters: { fluentTheme: WEB_LIGHT, dir: 'rtl', isVrTest: true}, // story renders in RTL, Web light mode and without injected padding and background style. + // parameters identity function will have all TS type annotations built in for intellisense. + parameters: parameters({ fluentTheme: 'web-light', dir: 'rtl', mode: 'vr-test'}), // story renders in RTL, Web light mode and without injected padding and background style. }; ``` From d1b213d0879e58065edf099dc5cc662a38cd16e2 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Sun, 16 Oct 2022 11:11:49 -0700 Subject: [PATCH 36/53] refactor: use withFluentProvider addon instead and configure parameters for VR stories --- .../.storybook/main.js | 2 ++ .../.storybook/preview.js | 9 ++----- apps/vr-tests-react-components/package.json | 1 + .../src/utilities/StoryDecorators.tsx | 21 ---------------- .../src/utilities/getStoryVariant.ts | 25 +++++++------------ .../src/utilities/index.ts | 1 - 6 files changed, 14 insertions(+), 45 deletions(-) delete mode 100644 apps/vr-tests-react-components/src/utilities/StoryDecorators.tsx diff --git a/apps/vr-tests-react-components/.storybook/main.js b/apps/vr-tests-react-components/.storybook/main.js index 66d036830a218..f5d8408fdc612 100644 --- a/apps/vr-tests-react-components/.storybook/main.js +++ b/apps/vr-tests-react-components/.storybook/main.js @@ -1,7 +1,9 @@ const path = require('path'); const { TsconfigPathsPlugin } = require('tsconfig-paths-webpack-plugin'); +const { loadWorkspaceAddon } = require('@fluentui/scripts/storybook'); module.exports = /** @type {import('../../../.storybook/main').StorybookBaseConfig} */ ({ + addons: [loadWorkspaceAddon('@fluentui/react-storybook-addon')], stories: ['../src/**/*.stories.tsx'], core: { builder: 'webpack5', diff --git a/apps/vr-tests-react-components/.storybook/preview.js b/apps/vr-tests-react-components/.storybook/preview.js index 191e2c99aa41b..da9d74b607622 100644 --- a/apps/vr-tests-react-components/.storybook/preview.js +++ b/apps/vr-tests-react-components/.storybook/preview.js @@ -53,13 +53,8 @@ setAddon({ }, }); -export const parameters = { layout: 'none' }; - -export const decorators = [ - /** @type {import("@storybook/csf").DecoratorFunction} */ story => ( - {story()} - ), -]; +/** @type {import("@fluentui/react-storybook-addon").FluentParameters} */ +export const parameters = { layout: 'none', mode: 'vr-test' }; // For static storybook per https://github.com/screener-io/screener-storybook#testing-with-static-storybook-app if (typeof window === 'object') { diff --git a/apps/vr-tests-react-components/package.json b/apps/vr-tests-react-components/package.json index d6c2208498a5f..f830fda47e453 100644 --- a/apps/vr-tests-react-components/package.json +++ b/apps/vr-tests-react-components/package.json @@ -43,6 +43,7 @@ "@fluentui/react-slider": "^9.0.8", "@fluentui/react-spinner": "^9.0.8", "@fluentui/react-spinbutton": "^9.0.5", + "@fluentui/react-storybook-addon": "^9.0.0-rc.1", "@fluentui/react-switch": "^9.0.9", "@fluentui/react-tabs": "^9.0.9", "@fluentui/react-table": "9.0.0-alpha.7", diff --git a/apps/vr-tests-react-components/src/utilities/StoryDecorators.tsx b/apps/vr-tests-react-components/src/utilities/StoryDecorators.tsx deleted file mode 100644 index 374f9e47e3f26..0000000000000 --- a/apps/vr-tests-react-components/src/utilities/StoryDecorators.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from 'react'; -import { DecoratorFunction } from '@storybook/addons'; -import { webLightTheme, teamsHighContrastTheme, webDarkTheme } from '@fluentui/react-theme'; -import { FluentProvider } from '@fluentui/react-provider'; -import { ExtendedStoryFnReturnType } from './types'; - -export const DarkModeDecorator: DecoratorFunction = story => { - return {story()}; -}; - -export const HighContrastDecorator: DecoratorFunction = story => { - return {story()}; -}; - -export const RTLDecorator: DecoratorFunction = story => { - return ( - - {story()} - - ); -}; diff --git a/apps/vr-tests-react-components/src/utilities/getStoryVariant.ts b/apps/vr-tests-react-components/src/utilities/getStoryVariant.ts index 7550a60a30c3e..48fd8229cbb88 100644 --- a/apps/vr-tests-react-components/src/utilities/getStoryVariant.ts +++ b/apps/vr-tests-react-components/src/utilities/getStoryVariant.ts @@ -1,5 +1,5 @@ import { ComponentStory } from '@storybook/react'; -import { DarkModeDecorator, HighContrastDecorator, RTLDecorator } from './StoryDecorators'; +import { parameters } from '@fluentui/react-storybook-addon'; export const DARK_MODE = 'Dark Mode'; export const HIGH_CONTRAST = 'High Contrast'; @@ -8,26 +8,19 @@ export const RTL = 'RTL'; /** * Helper function that returns a RTL, Dark Mode or High Contrast variant of an existing story. */ -export const getStoryVariant = (story: ComponentStory, variant: 'RTL' | 'Dark Mode' | 'High Contrast') => { - let decorator; +export const getStoryVariant = ( + story: ComponentStory, + variant: typeof DARK_MODE | typeof HIGH_CONTRAST | typeof RTL, +) => { const name = story.name.replace(/([a-z])([A-Z])/g, '$1 $2'); - - if (variant === RTL) { - decorator = RTLDecorator; - } - - if (variant === DARK_MODE) { - decorator = DarkModeDecorator; - } - - if (variant === HIGH_CONTRAST) { - decorator = HighContrastDecorator; - } + const fluentTheme = + variant === DARK_MODE ? 'web-dark' : variant === HIGH_CONTRAST ? 'teams-high-contrast' : 'web-light'; + const dir = variant === RTL ? 'rtl' : 'ltr'; return { ...story, render: story, storyName: `${story.storyName ?? name} - ${variant}`, - decorators: [decorator], + parameters: parameters({ fluentTheme, dir, mode: 'vr-test' }), }; }; diff --git a/apps/vr-tests-react-components/src/utilities/index.ts b/apps/vr-tests-react-components/src/utilities/index.ts index d071a94751e8b..e2de063e017a0 100644 --- a/apps/vr-tests-react-components/src/utilities/index.ts +++ b/apps/vr-tests-react-components/src/utilities/index.ts @@ -8,5 +8,4 @@ declare module '@storybook/addons' { } export * from './TestWrapperDecorator'; -export * from './StoryDecorators'; export * from './getStoryVariant'; From d888f928b85731ab96921ff6ff9ae6704e1e9dd8 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Thu, 20 Oct 2022 10:30:39 -0700 Subject: [PATCH 37/53] remove unintended prettier changes --- packages/react-components/react-persona/MIGRATION.md | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/react-components/react-persona/MIGRATION.md b/packages/react-components/react-persona/MIGRATION.md index 57e145ba51c7a..697c575bbd736 100644 --- a/packages/react-components/react-persona/MIGRATION.md +++ b/packages/react-components/react-persona/MIGRATION.md @@ -13,7 +13,6 @@ Here's how the API of v8's `Persona` compares to the one from v9's `Persona` com - ``` ``` - - `imageShouldFadeIn` => NOT SUPPORTED - `isOutOfOffice` => Use the `outOfOffice` prop of the `presence` slot. E.g.: `presence={{ outOfOffice: true }}` - `presence` => Use the `status` prop of the `presence` slot. E.g.: `presence={{ status: 'away' }}` From 6c6550a7d868f5595c7f4fb93114a902c229043b Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Sun, 16 Oct 2022 11:56:24 -0700 Subject: [PATCH 38/53] add react-storybook-addon and update github workflow --- .github/workflows/screener-build.yml | 4 ++++ apps/vr-tests-react-components/.storybook/main.js | 1 + 2 files changed, 5 insertions(+) diff --git a/.github/workflows/screener-build.yml b/.github/workflows/screener-build.yml index f4ddf2e6633f1..098a8a6a9b82b 100644 --- a/.github/workflows/screener-build.yml +++ b/.github/workflows/screener-build.yml @@ -272,6 +272,10 @@ jobs: printenv | sort ;\ echo "SHELLOPTS $SHELLOPTS" ;\ + - name: build @fluentui/react-storybook-addon + run: yarn workspace @fluentui/react-storybook-addon build + if: ${{env.SKIP_SCREENER_BUILD == 'false'}} + - name: build vr-tests-react-components storybook run: yarn workspace @fluentui/vr-tests-react-components screener:build if: ${{env.SKIP_SCREENER_BUILD == 'false'}} diff --git a/apps/vr-tests-react-components/.storybook/main.js b/apps/vr-tests-react-components/.storybook/main.js index f5d8408fdc612..7d8c374a4e61f 100644 --- a/apps/vr-tests-react-components/.storybook/main.js +++ b/apps/vr-tests-react-components/.storybook/main.js @@ -4,6 +4,7 @@ const { loadWorkspaceAddon } = require('@fluentui/scripts/storybook'); module.exports = /** @type {import('../../../.storybook/main').StorybookBaseConfig} */ ({ addons: [loadWorkspaceAddon('@fluentui/react-storybook-addon')], + stories: ['../src/**/*.stories.tsx'], core: { builder: 'webpack5', From 139aed9f61a3f80a8b07fd735c2fee92cd093fd0 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Sun, 16 Oct 2022 12:04:59 -0700 Subject: [PATCH 39/53] fix: build react-storybook-addon in screener CI --- .github/workflows/screener-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/screener-build.yml b/.github/workflows/screener-build.yml index 098a8a6a9b82b..a968727e1a1f3 100644 --- a/.github/workflows/screener-build.yml +++ b/.github/workflows/screener-build.yml @@ -273,7 +273,7 @@ jobs: echo "SHELLOPTS $SHELLOPTS" ;\ - name: build @fluentui/react-storybook-addon - run: yarn workspace @fluentui/react-storybook-addon build + run: yarn build --to @fluentui/react-storybook-addon if: ${{env.SKIP_SCREENER_BUILD == 'false'}} - name: build vr-tests-react-components storybook From 6cf51af21ec787b18903b5f1122d7ef70be290dc Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Sun, 16 Oct 2022 12:23:49 -0700 Subject: [PATCH 40/53] test: remove loadworkspaceaddon --- apps/vr-tests-react-components/.storybook/main.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/vr-tests-react-components/.storybook/main.js b/apps/vr-tests-react-components/.storybook/main.js index 7d8c374a4e61f..c87c619441da7 100644 --- a/apps/vr-tests-react-components/.storybook/main.js +++ b/apps/vr-tests-react-components/.storybook/main.js @@ -1,9 +1,8 @@ const path = require('path'); const { TsconfigPathsPlugin } = require('tsconfig-paths-webpack-plugin'); -const { loadWorkspaceAddon } = require('@fluentui/scripts/storybook'); module.exports = /** @type {import('../../../.storybook/main').StorybookBaseConfig} */ ({ - addons: [loadWorkspaceAddon('@fluentui/react-storybook-addon')], + addons: ['@fluentui/react-storybook-addon'], stories: ['../src/**/*.stories.tsx'], core: { From c0616d0d63fad1ee087c61db779d94eb5aab5c9d Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Sun, 16 Oct 2022 13:53:52 -0700 Subject: [PATCH 41/53] feat: add utils file to host reused stuff in various Button stories --- .../src/stories/Button/Button.stories.tsx | 23 +++-------------- .../stories/Button/CompoundButton.stories.tsx | 23 +++-------------- .../Button/CompoundButtonDefault.stories.tsx | 5 ++-- .../src/stories/Button/MenuButton.stories.tsx | 23 +++-------------- .../stories/Button/ToggleButton.stories.tsx | 23 +++-------------- .../src/stories/Button/utils.tsx | 25 +++++++++++++++++++ 6 files changed, 39 insertions(+), 83 deletions(-) create mode 100644 apps/vr-tests-react-components/src/stories/Button/utils.tsx diff --git a/apps/vr-tests-react-components/src/stories/Button/Button.stories.tsx b/apps/vr-tests-react-components/src/stories/Button/Button.stories.tsx index a146157cda10b..ca21b59d4ca52 100644 --- a/apps/vr-tests-react-components/src/stories/Button/Button.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Button/Button.stories.tsx @@ -1,33 +1,16 @@ import * as React from 'react'; -import Screener from 'screener-storybook/src/screener'; import { Button } from '@fluentui/react-button'; import { bundleIcon, CalendarMonthFilled, CalendarMonthRegular } from '@fluentui/react-icons'; -import { makeStyles } from '@griffel/react'; import { ComponentMeta } from '@storybook/react'; -import { getStoryVariant, DARK_MODE, HIGH_CONTRAST, RTL } from '../../utilities/index'; +import { getStoryVariant, DARK_MODE, HIGH_CONTRAST, RTL } from '../../utilities'; +import { buttonId, useStyles, ButtonDecorator } from './utils'; const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular); -const steps = new Screener.Steps() - .snapshot('default', { cropTo: '.testWrapper' }) - .hover('#button-id') - .snapshot('hover', { cropTo: '.testWrapper' }) - .mouseDown('#button-id') - .snapshot('pressed', { cropTo: '.testWrapper' }) - .end(); - -const buttonId = 'button-id'; - -const useStyles = makeStyles({ - longText: { - width: '280px', - }, -}); - export default { title: 'Button Converged', Component: Button, - decorators: [story => {story()}], + decorators: [ButtonDecorator], } as ComponentMeta; export const Default = () => ; diff --git a/apps/vr-tests-react-components/src/stories/Button/CompoundButton.stories.tsx b/apps/vr-tests-react-components/src/stories/Button/CompoundButton.stories.tsx index fe45ea529b103..c5ff7b2306f7b 100644 --- a/apps/vr-tests-react-components/src/stories/Button/CompoundButton.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Button/CompoundButton.stories.tsx @@ -1,33 +1,16 @@ import * as React from 'react'; -import Screener from 'screener-storybook/src/screener'; import { CompoundButton } from '@fluentui/react-button'; import { bundleIcon, CalendarMonthFilled, CalendarMonthRegular } from '@fluentui/react-icons'; -import { makeStyles } from '@griffel/react'; import { ComponentMeta } from '@storybook/react'; -import { getStoryVariant, RTL } from '../../utilities/index'; +import { getStoryVariant, RTL } from '../../utilities'; +import { buttonId, useStyles, ButtonDecorator } from './utils'; const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular); -const steps = new Screener.Steps() - .snapshot('default', { cropTo: '.testWrapper' }) - .hover('#button-id') - .snapshot('hover', { cropTo: '.testWrapper' }) - .mouseDown('#button-id') - .snapshot('pressed', { cropTo: '.testWrapper' }) - .end(); - -const buttonId = 'button-id'; - -const useStyles = makeStyles({ - longText: { - width: '280px', - }, -}); - export default { title: 'CompoundButton Converged', component: CompoundButton, - decorators: [story => {story()}], + decorators: [ButtonDecorator], } as ComponentMeta; export const Outline = () => ( diff --git a/apps/vr-tests-react-components/src/stories/Button/CompoundButtonDefault.stories.tsx b/apps/vr-tests-react-components/src/stories/Button/CompoundButtonDefault.stories.tsx index e0d1dad5a54f7..d1ee4973d32c0 100644 --- a/apps/vr-tests-react-components/src/stories/Button/CompoundButtonDefault.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Button/CompoundButtonDefault.stories.tsx @@ -3,12 +3,11 @@ import Screener from 'screener-storybook/src/screener'; import { CompoundButton } from '@fluentui/react-button'; import { bundleIcon, CalendarMonthFilled, CalendarMonthRegular } from '@fluentui/react-icons'; import { ComponentMeta } from '@storybook/react'; -import { getStoryVariant, RTL } from '../../utilities/index'; +import { getStoryVariant, RTL } from '../../utilities'; +import { buttonId } from './utils'; const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular); -const buttonId = 'button-id'; - export default { title: 'CompoundButton Converged', component: CompoundButton, diff --git a/apps/vr-tests-react-components/src/stories/Button/MenuButton.stories.tsx b/apps/vr-tests-react-components/src/stories/Button/MenuButton.stories.tsx index a9e92209f9117..a227773fa8210 100644 --- a/apps/vr-tests-react-components/src/stories/Button/MenuButton.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Button/MenuButton.stories.tsx @@ -1,33 +1,16 @@ import * as React from 'react'; -import Screener from 'screener-storybook/src/screener'; import { MenuButton } from '@fluentui/react-button'; import { bundleIcon, CalendarMonthFilled, CalendarMonthRegular } from '@fluentui/react-icons'; -import { makeStyles } from '@griffel/react'; import { ComponentMeta } from '@storybook/react'; -import { getStoryVariant, RTL } from '../../utilities/index'; +import { getStoryVariant, RTL } from '../../utilities'; +import { buttonId, useStyles, ButtonDecorator } from './utils'; const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular); -const steps = new Screener.Steps() - .snapshot('default', { cropTo: '.testWrapper' }) - .hover('#button-id') - .snapshot('hover', { cropTo: '.testWrapper' }) - .mouseDown('#button-id') - .snapshot('pressed', { cropTo: '.testWrapper' }) - .end(); - -const buttonId = 'button-id'; - -const useStyles = makeStyles({ - longText: { - width: '280px', - }, -}); - export default { title: 'MenuButton Converged', component: MenuButton, - decorators: [story => {story()}], + decorators: [ButtonDecorator], } as ComponentMeta; export const Default = () => Hello, world; diff --git a/apps/vr-tests-react-components/src/stories/Button/ToggleButton.stories.tsx b/apps/vr-tests-react-components/src/stories/Button/ToggleButton.stories.tsx index 597c073843f68..61e3579dc4aa7 100644 --- a/apps/vr-tests-react-components/src/stories/Button/ToggleButton.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Button/ToggleButton.stories.tsx @@ -1,33 +1,16 @@ import * as React from 'react'; -import Screener from 'screener-storybook/src/screener'; import { ToggleButton } from '@fluentui/react-button'; import { bundleIcon, CalendarMonthFilled, CalendarMonthRegular } from '@fluentui/react-icons'; -import { makeStyles } from '@griffel/react'; import { ComponentMeta } from '@storybook/react'; -import { DARK_MODE, getStoryVariant, HIGH_CONTRAST, RTL } from '../../utilities/index'; +import { getStoryVariant, DARK_MODE, HIGH_CONTRAST, RTL } from '../../utilities'; +import { buttonId, useStyles, ButtonDecorator } from './utils'; const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular); -const steps = new Screener.Steps() - .snapshot('default', { cropTo: '.testWrapper' }) - .hover('#button-id') - .snapshot('hover', { cropTo: '.testWrapper' }) - .mouseDown('#button-id') - .snapshot('pressed', { cropTo: '.testWrapper' }) - .end(); - -const buttonId = 'button-id'; - -const useStyles = makeStyles({ - longText: { - width: '280px', - }, -}); - export default { title: 'ToggleButton Converged', component: ToggleButton, - decorators: [story => {story()}], + decorators: [ButtonDecorator], } as ComponentMeta; export const Default = () => Hello, world; diff --git a/apps/vr-tests-react-components/src/stories/Button/utils.tsx b/apps/vr-tests-react-components/src/stories/Button/utils.tsx new file mode 100644 index 0000000000000..9753488161708 --- /dev/null +++ b/apps/vr-tests-react-components/src/stories/Button/utils.tsx @@ -0,0 +1,25 @@ +import * as React from 'react'; +import Screener from 'screener-storybook/src/screener'; +import { DecoratorFunction } from '@storybook/addons'; +import { ExtendedStoryFnReturnType } from '../../utilities/types'; +import { makeStyles } from '@griffel/react'; + +export const buttonId = 'button-id'; + +export const useStyles = makeStyles({ + longText: { + width: '280px', + }, +}); + +const steps = new Screener.Steps() + .snapshot('default', { cropTo: '.testWrapper' }) + .hover('#button-id') + .snapshot('hover', { cropTo: '.testWrapper' }) + .mouseDown('#button-id') + .snapshot('pressed', { cropTo: '.testWrapper' }) + .end(); + +export const ButtonDecorator: DecoratorFunction = story => { + return {story()} ; +}; From cd7b01dd99dc45e2e14ba54dd36067133dec4169 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Sun, 16 Oct 2022 14:33:09 -0700 Subject: [PATCH 42/53] refactor: add generalized withScreenerSteps decorator --- .../src/stories/Button/Button.stories.tsx | 6 ++-- .../stories/Button/CompoundButton.stories.tsx | 6 ++-- .../Button/CompoundButtonDefault.stories.tsx | 28 ++++++++----------- .../src/stories/Button/MenuButton.stories.tsx | 6 ++-- .../stories/Button/ToggleButton.stories.tsx | 6 ++-- .../stories/Button/{utils.tsx => utils.ts} | 9 +----- .../src/utilities/index.ts | 1 + .../src/utilities/withScreenerSteps.tsx | 15 ++++++++++ 8 files changed, 40 insertions(+), 37 deletions(-) rename apps/vr-tests-react-components/src/stories/Button/{utils.tsx => utils.ts} (56%) create mode 100644 apps/vr-tests-react-components/src/utilities/withScreenerSteps.tsx diff --git a/apps/vr-tests-react-components/src/stories/Button/Button.stories.tsx b/apps/vr-tests-react-components/src/stories/Button/Button.stories.tsx index ca21b59d4ca52..09f8c3b1f6328 100644 --- a/apps/vr-tests-react-components/src/stories/Button/Button.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Button/Button.stories.tsx @@ -2,15 +2,15 @@ import * as React from 'react'; import { Button } from '@fluentui/react-button'; import { bundleIcon, CalendarMonthFilled, CalendarMonthRegular } from '@fluentui/react-icons'; import { ComponentMeta } from '@storybook/react'; -import { getStoryVariant, DARK_MODE, HIGH_CONTRAST, RTL } from '../../utilities'; -import { buttonId, useStyles, ButtonDecorator } from './utils'; +import { getStoryVariant, withScreenerSteps, DARK_MODE, HIGH_CONTRAST, RTL } from '../../utilities'; +import { buttonId, steps, useStyles } from './utils'; const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular); export default { title: 'Button Converged', Component: Button, - decorators: [ButtonDecorator], + decorators: [story => withScreenerSteps({ story, steps })], } as ComponentMeta; export const Default = () => ; diff --git a/apps/vr-tests-react-components/src/stories/Button/CompoundButton.stories.tsx b/apps/vr-tests-react-components/src/stories/Button/CompoundButton.stories.tsx index c5ff7b2306f7b..4c067d60f8704 100644 --- a/apps/vr-tests-react-components/src/stories/Button/CompoundButton.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Button/CompoundButton.stories.tsx @@ -2,15 +2,15 @@ import * as React from 'react'; import { CompoundButton } from '@fluentui/react-button'; import { bundleIcon, CalendarMonthFilled, CalendarMonthRegular } from '@fluentui/react-icons'; import { ComponentMeta } from '@storybook/react'; -import { getStoryVariant, RTL } from '../../utilities'; -import { buttonId, useStyles, ButtonDecorator } from './utils'; +import { getStoryVariant, withScreenerSteps, RTL } from '../../utilities'; +import { buttonId, steps, useStyles } from './utils'; const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular); export default { title: 'CompoundButton Converged', component: CompoundButton, - decorators: [ButtonDecorator], + decorators: [story => withScreenerSteps({ story, steps })], } as ComponentMeta; export const Outline = () => ( diff --git a/apps/vr-tests-react-components/src/stories/Button/CompoundButtonDefault.stories.tsx b/apps/vr-tests-react-components/src/stories/Button/CompoundButtonDefault.stories.tsx index d1ee4973d32c0..3d73daf5f7d91 100644 --- a/apps/vr-tests-react-components/src/stories/Button/CompoundButtonDefault.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Button/CompoundButtonDefault.stories.tsx @@ -3,30 +3,24 @@ import Screener from 'screener-storybook/src/screener'; import { CompoundButton } from '@fluentui/react-button'; import { bundleIcon, CalendarMonthFilled, CalendarMonthRegular } from '@fluentui/react-icons'; import { ComponentMeta } from '@storybook/react'; -import { getStoryVariant, RTL } from '../../utilities'; +import { getStoryVariant, withScreenerSteps, RTL } from '../../utilities'; import { buttonId } from './utils'; const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular); +const steps = new Screener.Steps() + .snapshot('default', { cropTo: '.testWrapper' }) + // https://github.com/microsoft/fluentui/issues/21998 + // .hover('#button-id') + // .snapshot('hover', { cropTo: '.testWrapper' }) + .mouseDown('#button-id') + .snapshot('pressed', { cropTo: '.testWrapper' }) + .end(); + export default { title: 'CompoundButton Converged', component: CompoundButton, - decorators: [ - story => ( - - {story()} - - ), - ], + decorators: [story => withScreenerSteps({ story, steps })], } as ComponentMeta; export const Default = () => ( diff --git a/apps/vr-tests-react-components/src/stories/Button/MenuButton.stories.tsx b/apps/vr-tests-react-components/src/stories/Button/MenuButton.stories.tsx index a227773fa8210..492115ce9318c 100644 --- a/apps/vr-tests-react-components/src/stories/Button/MenuButton.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Button/MenuButton.stories.tsx @@ -2,15 +2,15 @@ import * as React from 'react'; import { MenuButton } from '@fluentui/react-button'; import { bundleIcon, CalendarMonthFilled, CalendarMonthRegular } from '@fluentui/react-icons'; import { ComponentMeta } from '@storybook/react'; -import { getStoryVariant, RTL } from '../../utilities'; -import { buttonId, useStyles, ButtonDecorator } from './utils'; +import { getStoryVariant, withScreenerSteps, RTL } from '../../utilities'; +import { buttonId, steps, useStyles } from './utils'; const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular); export default { title: 'MenuButton Converged', component: MenuButton, - decorators: [ButtonDecorator], + decorators: [story => withScreenerSteps({ story, steps })], } as ComponentMeta; export const Default = () => Hello, world; diff --git a/apps/vr-tests-react-components/src/stories/Button/ToggleButton.stories.tsx b/apps/vr-tests-react-components/src/stories/Button/ToggleButton.stories.tsx index 61e3579dc4aa7..4e8e4bff57ea6 100644 --- a/apps/vr-tests-react-components/src/stories/Button/ToggleButton.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Button/ToggleButton.stories.tsx @@ -2,15 +2,15 @@ import * as React from 'react'; import { ToggleButton } from '@fluentui/react-button'; import { bundleIcon, CalendarMonthFilled, CalendarMonthRegular } from '@fluentui/react-icons'; import { ComponentMeta } from '@storybook/react'; -import { getStoryVariant, DARK_MODE, HIGH_CONTRAST, RTL } from '../../utilities'; -import { buttonId, useStyles, ButtonDecorator } from './utils'; +import { getStoryVariant, withScreenerSteps, DARK_MODE, HIGH_CONTRAST, RTL } from '../../utilities'; +import { buttonId, steps, useStyles } from './utils'; const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular); export default { title: 'ToggleButton Converged', component: ToggleButton, - decorators: [ButtonDecorator], + decorators: [story => withScreenerSteps({ story, steps })], } as ComponentMeta; export const Default = () => Hello, world; diff --git a/apps/vr-tests-react-components/src/stories/Button/utils.tsx b/apps/vr-tests-react-components/src/stories/Button/utils.ts similarity index 56% rename from apps/vr-tests-react-components/src/stories/Button/utils.tsx rename to apps/vr-tests-react-components/src/stories/Button/utils.ts index 9753488161708..41cf2954cabb2 100644 --- a/apps/vr-tests-react-components/src/stories/Button/utils.tsx +++ b/apps/vr-tests-react-components/src/stories/Button/utils.ts @@ -1,7 +1,4 @@ -import * as React from 'react'; import Screener from 'screener-storybook/src/screener'; -import { DecoratorFunction } from '@storybook/addons'; -import { ExtendedStoryFnReturnType } from '../../utilities/types'; import { makeStyles } from '@griffel/react'; export const buttonId = 'button-id'; @@ -12,14 +9,10 @@ export const useStyles = makeStyles({ }, }); -const steps = new Screener.Steps() +export const steps = new Screener.Steps() .snapshot('default', { cropTo: '.testWrapper' }) .hover('#button-id') .snapshot('hover', { cropTo: '.testWrapper' }) .mouseDown('#button-id') .snapshot('pressed', { cropTo: '.testWrapper' }) .end(); - -export const ButtonDecorator: DecoratorFunction = story => { - return {story()} ; -}; diff --git a/apps/vr-tests-react-components/src/utilities/index.ts b/apps/vr-tests-react-components/src/utilities/index.ts index e2de063e017a0..9b57e0061e559 100644 --- a/apps/vr-tests-react-components/src/utilities/index.ts +++ b/apps/vr-tests-react-components/src/utilities/index.ts @@ -9,3 +9,4 @@ declare module '@storybook/addons' { export * from './TestWrapperDecorator'; export * from './getStoryVariant'; +export * from './withScreenerSteps'; diff --git a/apps/vr-tests-react-components/src/utilities/withScreenerSteps.tsx b/apps/vr-tests-react-components/src/utilities/withScreenerSteps.tsx new file mode 100644 index 0000000000000..f38886fbe9562 --- /dev/null +++ b/apps/vr-tests-react-components/src/utilities/withScreenerSteps.tsx @@ -0,0 +1,15 @@ +import * as React from 'react'; +import Screener, { Step } from 'screener-storybook/src/screener'; +import { StoryContext } from './types'; + +export const withScreenerSteps = ({ + story, + context, + steps, +}: { + story: () => React.ReactNode; + steps: Step[]; + context?: StoryContext; +}) => { + return {story()} ; +}; From 4488610ed7bcd43f6a4b64bdc3d5baae3428a6e7 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Sun, 16 Oct 2022 15:04:15 -0700 Subject: [PATCH 43/53] uncomment out flaky test --- .../src/stories/Button/Button.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vr-tests-react-components/src/stories/Button/Button.stories.tsx b/apps/vr-tests-react-components/src/stories/Button/Button.stories.tsx index 09f8c3b1f6328..c50d505dd8ae3 100644 --- a/apps/vr-tests-react-components/src/stories/Button/Button.stories.tsx +++ b/apps/vr-tests-react-components/src/stories/Button/Button.stories.tsx @@ -170,7 +170,7 @@ export const WithIconAfterContent = () => ( WithIconAfterContent.storyName = 'With icon after content'; -// export const WithIconAfterContentRTL = getStoryVariant(WithIconAfterContent, RTL); +export const WithIconAfterContentRTL = getStoryVariant(WithIconAfterContent, RTL); export const IconOnly = () => +); + +AsAnAnchor.storyName = 'As an anchor'; + export const Circular = () => ( ; + + it('should set the correct direction for story', () => { + const ltrStory = getStoryVariant(DefaultStory, DARK_MODE); + const rtlStory = getStoryVariant(DefaultStory, RTL); + + expect(ltrStory.parameters.dir).toBe('ltr'); + expect(rtlStory.parameters.dir).toBe('rtl'); + }); + + it('should set the correct theme for story', () => { + const darkModeStory = getStoryVariant(DefaultStory, DARK_MODE); + const highContrastStory = getStoryVariant(DefaultStory, HIGH_CONTRAST); + + expect(darkModeStory.parameters.fluentTheme).toBe('web-dark'); + expect(highContrastStory.parameters.fluentTheme).toBe('teams-high-contrast'); + }); + }); +}); From 5d7527f27feae6a33c4a8b0707e2255158359f12 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Tue, 1 Nov 2022 16:23:28 -0700 Subject: [PATCH 50/53] fix: make fluent storybook-addon a caret dep again to fix syncpack error --- apps/vr-tests-react-components/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/vr-tests-react-components/package.json b/apps/vr-tests-react-components/package.json index 99d34d2d37d4f..d1b71c1c23e6e 100644 --- a/apps/vr-tests-react-components/package.json +++ b/apps/vr-tests-react-components/package.json @@ -48,7 +48,7 @@ "@fluentui/react-slider": "^9.0.8", "@fluentui/react-spinner": "^9.0.8", "@fluentui/react-spinbutton": "^9.0.6", - "@fluentui/react-storybook-addon": "9.0.0-rc.1", + "@fluentui/react-storybook-addon": "^9.0.0-rc.1", "@fluentui/react-switch": "^9.0.9", "@fluentui/react-tabs": "^9.0.9", "@fluentui/react-table": "9.0.0-alpha.8", From e2ba1f00c1e6ac21c9b7b21cfba198763baf2a98 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Tue, 1 Nov 2022 17:42:03 -0700 Subject: [PATCH 51/53] fix(react-storybook-addon): update API --- .../react-storybook-addon/etc/react-storybook-addon.api.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md b/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md index 02800552969e2..684361e99da9f 100644 --- a/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md +++ b/packages/react-components/react-storybook-addon/etc/react-storybook-addon.api.md @@ -5,7 +5,8 @@ ```ts import { Args } from '@storybook/api'; -import { Parameters as Parameters_2 } from '@storybook/api'; +import { OptionsParameter } from '@storybook/addons'; +import { Parameters as Parameters_2 } from '@storybook/addons'; import { StoryContext } from '@storybook/addons'; import type { Theme } from '@fluentui/react-theme'; @@ -38,6 +39,10 @@ export function parameters(options?: FluentParameters): { dir: string; fluentTheme: string; mode: string; + fileName?: string | undefined; + options?: OptionsParameter | undefined; + layout?: "centered" | "fullscreen" | "padded" | "none" | undefined; + docsOnly?: boolean | undefined; }; // @public (undocumented) From 3d6983dec781386e1378bfde6a73206cad70c6c2 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Tue, 1 Nov 2022 19:44:32 -0700 Subject: [PATCH 52/53] nit: generalize extra screener-build step for v9 --- .github/workflows/screener-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/screener-build.yml b/.github/workflows/screener-build.yml index a968727e1a1f3..ad95963a40f80 100644 --- a/.github/workflows/screener-build.yml +++ b/.github/workflows/screener-build.yml @@ -272,8 +272,8 @@ jobs: printenv | sort ;\ echo "SHELLOPTS $SHELLOPTS" ;\ - - name: build @fluentui/react-storybook-addon - run: yarn build --to @fluentui/react-storybook-addon + - name: build vr-tests-react-components storybook + run: yarn lage build --to @fluentui/vr-tests-react-components if: ${{env.SKIP_SCREENER_BUILD == 'false'}} - name: build vr-tests-react-components storybook From 781e403f9b5618858c9ce9104437d949e202b994 Mon Sep 17 00:00:00 2001 From: Tristan Watanabe Date: Tue, 1 Nov 2022 20:33:25 -0700 Subject: [PATCH 53/53] test: add test for story naming --- .../src/utilities/utilities.test.tsx | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/apps/vr-tests-react-components/src/utilities/utilities.test.tsx b/apps/vr-tests-react-components/src/utilities/utilities.test.tsx index 9ab112eabf0d5..c8acd36d1b698 100644 --- a/apps/vr-tests-react-components/src/utilities/utilities.test.tsx +++ b/apps/vr-tests-react-components/src/utilities/utilities.test.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { getStoryVariant, DARK_MODE, HIGH_CONTRAST, RTL } from './getStoryVariant'; import { Button } from '@fluentui/react-button'; +import { ComponentStory } from '@storybook/react'; describe('utility functions', () => { describe('getStoryVariant', () => { @@ -22,5 +23,26 @@ describe('utility functions', () => { expect(darkModeStory.parameters.fluentTheme).toBe('web-dark'); expect(highContrastStory.parameters.fluentTheme).toBe('teams-high-contrast'); }); + + it('should set the correct name for story', () => { + const darkModeStory = getStoryVariant(DefaultStory, DARK_MODE); + const highContrastStory = getStoryVariant(DefaultStory, HIGH_CONTRAST); + const rtlStory = getStoryVariant(DefaultStory, RTL); + + expect(darkModeStory.storyName).toEqual('Default Story - Dark Mode'); + expect(highContrastStory.storyName).toEqual('Default Story - High Contrast'); + expect(rtlStory.storyName).toEqual('Default Story - RTL'); + + const buttonStory: ComponentStory = DefaultStory; + buttonStory.storyName = 'button'; + + const buttonDarkModeStory = getStoryVariant(buttonStory, DARK_MODE); + const buttonHighContrastStory = getStoryVariant(buttonStory, HIGH_CONTRAST); + const buttonRtlStory = getStoryVariant(buttonStory, RTL); + + expect(buttonDarkModeStory.storyName).toEqual('button - Dark Mode'); + expect(buttonHighContrastStory.storyName).toEqual('button - High Contrast'); + expect(buttonRtlStory.storyName).toEqual('button - RTL'); + }); }); });