diff --git a/apps/vr-tests-react-components/.storybook/preview.js b/apps/vr-tests-react-components/.storybook/preview.js index 4d58f82e03742c..35158e1c8750b9 100644 --- a/apps/vr-tests-react-components/.storybook/preview.js +++ b/apps/vr-tests-react-components/.storybook/preview.js @@ -69,4 +69,10 @@ setAddon({ }); /** @type {import("@fluentui/react-storybook-addon").FluentParameters} */ -export const parameters = { layout: 'none', mode: 'vr-test' }; +export const parameters = { + layout: 'none', + mode: 'vr-test', + reactStorybookAddon: { + disabledDecorators: ['AriaLive'], + }, +}; 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 952e79d996d901..33c63e5b47d7dc 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 @@ -31,6 +31,10 @@ export interface FluentParameters extends Parameters_2 { fluentTheme?: ThemeIds; // (undocumented) mode?: 'default' | 'vr-test'; + // (undocumented) + reactStorybookAddon?: { + disabledDecorators: ['AriaLive' | 'FluentProvider' | 'ReactStrictMode']; + }; } // @public (undocumented) @@ -46,6 +50,9 @@ export function parameters(options?: FluentParameters): { dir: string; fluentTheme: string; mode: string; + reactStorybookAddon?: { + disabledDecorators: ["AriaLive" | "FluentProvider" | "ReactStrictMode"]; + } | undefined; fileName?: string | undefined; options?: OptionsParameter | undefined; layout?: "centered" | "fullscreen" | "padded" | "none" | undefined; diff --git a/packages/react-components/react-storybook-addon/src/decorators/withAriaLive.tsx b/packages/react-components/react-storybook-addon/src/decorators/withAriaLive.tsx index adf4ceec180b8d..a607fb28a5c79d 100644 --- a/packages/react-components/react-storybook-addon/src/decorators/withAriaLive.tsx +++ b/packages/react-components/react-storybook-addon/src/decorators/withAriaLive.tsx @@ -1,17 +1,29 @@ +import { AriaLiveAnnouncer } from '@fluentui/react-aria'; import * as React from 'react'; -import { AriaLiveAnnouncer } from '@fluentui/react-aria'; +import { FluentStoryContext } from '../hooks'; +import { isDecoratorDisabled } from '../utils/isDecoratorDisabled'; + +export const withAriaLive = (Story: () => JSX.Element, context: FluentStoryContext) => { + if (isDecoratorDisabled(context, 'AriaLive')) { + return Story(); + } -export const withAriaLive = (StoryFn: () => JSX.Element) => { - return {StoryFn()}; + return ( + + + + ); }; const AriaLiveWrapper: React.FC<{ children: React.ReactNode }> = props => { const [mounted, setMounted] = React.useState(false); + React.useEffect(() => { // The AriaLiveAnnouncer appends an element to DOM in an effect // Trigger an extra renderer to make sure that doc examples that need to announce on mount can do so setMounted(true); }, []); + return {mounted && props.children}; }; 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 a13d68508160d4..467bed589a9d64 100644 --- a/packages/react-components/react-storybook-addon/src/decorators/withFluentProvider.tsx +++ b/packages/react-components/react-storybook-addon/src/decorators/withFluentProvider.tsx @@ -5,6 +5,7 @@ import { Theme } from '@fluentui/react-theme'; import { themes, defaultTheme, ThemeIds } from '../theme'; import { DIR_ID, THEME_ID } from '../constants'; import { FluentGlobals, FluentStoryContext } from '../hooks'; +import { isDecoratorDisabled } from '../utils/isDecoratorDisabled'; const findTheme = (themeId?: ThemeIds) => { if (!themeId) { @@ -23,8 +24,12 @@ const getActiveFluentTheme = (globals: FluentGlobals) => { export const withFluentProvider = (StoryFn: () => JSX.Element, context: FluentStoryContext) => { const { globals, parameters } = context; const { mode } = parameters; - const isVrTest = mode === 'vr-test'; + if (isDecoratorDisabled(context, 'FluentProvider')) { + return StoryFn(); + } + + const isVrTest = mode === 'vr-test'; const dir = parameters.dir ?? globals[DIR_ID] ?? 'ltr'; const globalTheme = getActiveFluentTheme(globals); const paramTheme = findTheme(parameters.fluentTheme); diff --git a/packages/react-components/react-storybook-addon/src/decorators/withReactStrictMode.tsx b/packages/react-components/react-storybook-addon/src/decorators/withReactStrictMode.tsx index d1aab6613e2d5b..3592371cd96527 100644 --- a/packages/react-components/react-storybook-addon/src/decorators/withReactStrictMode.tsx +++ b/packages/react-components/react-storybook-addon/src/decorators/withReactStrictMode.tsx @@ -2,8 +2,13 @@ import * as React from 'react'; import { STRICT_MODE_ID } from '../constants'; import { FluentStoryContext } from '../hooks'; +import { isDecoratorDisabled } from '../utils/isDecoratorDisabled'; export const withReactStrictMode = (StoryFn: () => JSX.Element, context: FluentStoryContext) => { + if (isDecoratorDisabled(context, 'ReactStrictMode')) { + return StoryFn(); + } + const isActive = context.globals[STRICT_MODE_ID] ?? false; return {StoryFn()}; diff --git a/packages/react-components/react-storybook-addon/src/hooks.ts b/packages/react-components/react-storybook-addon/src/hooks.ts index bfdd1b644c9aee..9a22aaa2eaecd2 100644 --- a/packages/react-components/react-storybook-addon/src/hooks.ts +++ b/packages/react-components/react-storybook-addon/src/hooks.ts @@ -25,6 +25,7 @@ export interface FluentParameters extends Parameters { dir?: 'ltr' | 'rtl'; fluentTheme?: ThemeIds; mode?: 'default' | 'vr-test'; + reactStorybookAddon?: { disabledDecorators: ['AriaLive' | 'FluentProvider' | 'ReactStrictMode'] }; } export function useGlobals(): [FluentGlobals, (newGlobals: FluentGlobals) => void] { diff --git a/packages/react-components/react-storybook-addon/src/utils/isDecoratorDisabled.ts b/packages/react-components/react-storybook-addon/src/utils/isDecoratorDisabled.ts new file mode 100644 index 00000000000000..9295f69a4a992c --- /dev/null +++ b/packages/react-components/react-storybook-addon/src/utils/isDecoratorDisabled.ts @@ -0,0 +1,7 @@ +import type { FluentParameters, FluentStoryContext } from '../hooks'; + +type DecoratorName = NonNullable['disabledDecorators'][number]; + +export function isDecoratorDisabled(context: FluentStoryContext, decoratorName: DecoratorName): boolean { + return context.parameters.reactStorybookAddon?.disabledDecorators?.includes(decoratorName) ?? false; +}