Skip to content

Commit

Permalink
feat(docs): Adding global direction switch to dynamically change betw…
Browse files Browse the repository at this point in the history
…een ltr and rtl in storybook (microsoft#29954)

* feat(docs): Adding global direction switch to dynamically change between ltr and rtl in storybook.

* Updating API.

* Moving dir switch to the same line as theme picker.
  • Loading branch information
khmakoto committed Dec 4, 2023
1 parent 96379f5 commit 419d760
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 8 deletions.
50 changes: 50 additions & 0 deletions apps/public-docsite-v9/src/DocsComponents/DirSwitch.stories.tsx
@@ -0,0 +1,50 @@
import * as React from 'react';
import { makeStyles, Label, Switch, useId, typographyStyles } from '@fluentui/react-components';
import type { SwitchProps } from '@fluentui/react-components';
import { DIR_ID } from '@fluentui/react-storybook-addon';
import addons from '@storybook/addons';

const useStyles = makeStyles({
container: {
alignItems: 'center',
display: 'flex',
justifyContent: 'start',
},
label: {
...typographyStyles.subtitle2,
},
});

/**
* Dir switch used in the react-components docs header
*/
export const DirSwitch: React.FC<{ dir?: 'ltr' | 'rtl' }> = ({ dir }) => {
const switchId = useId('dir-switch');

const styles = useStyles();

const [currentDir, setCurrentDir] = React.useState(dir);
const checked = currentDir === 'rtl';

const setGlobalDir = (newDir: 'ltr' | 'rtl'): void => {
addons.getChannel().emit('updateGlobals', { globals: { [DIR_ID]: newDir } });
};

const onChange = React.useCallback<NonNullable<SwitchProps['onChange']>>((_, data) => {
const newDir = data.checked ? 'rtl' : 'ltr';
setGlobalDir(newDir);
setCurrentDir(newDir);
}, []);

return (
<div className={styles.container}>
<Label className={styles.label} htmlFor={currentDir === 'ltr' ? undefined : switchId}>
LTR
</Label>
<Switch checked={checked} id={switchId} onChange={onChange} />
<Label className={styles.label} htmlFor={currentDir === 'rtl' ? switchId : undefined}>
RTL
</Label>
</div>
);
};
Expand Up @@ -11,9 +11,11 @@ import {
Stories,
} from '@storybook/addon-docs';
import { makeStyles, shorthands } from '@griffel/react';
import { Toc, nameToHash } from './Toc.stories';
import { THEME_ID, themes } from '@fluentui/react-storybook-addon';
import { tokens } from '@fluentui/react-components';
import { DIR_ID, THEME_ID, themes } from '@fluentui/react-storybook-addon';
import { DirSwitch } from './DirSwitch.stories';
import { ThemePicker } from './ThemePicker.stories';
import { Toc, nameToHash } from './Toc.stories';

const useStyles = makeStyles({
divider: {
Expand All @@ -38,11 +40,16 @@ const useStyles = makeStyles({
width: '200px',
flexGrow: 1,
},
globalTogglesContainer: {
columnGap: tokens.spacingHorizontalXXXL,
display: 'flex',
},
});

export const FluentDocsPage = () => {
const context = React.useContext(DocsContext);

const dir = context.parameters?.dir ?? context.globals?.[DIR_ID] ?? 'ltr';
const selectedTheme = themes.find(theme => theme.id === context.globals![THEME_ID]);
const stories = context.componentStories();
const primaryStory = stories[0];
Expand All @@ -65,7 +72,10 @@ export const FluentDocsPage = () => {

<div className={styles.wrapper}>
<div className={styles.container}>
<ThemePicker selectedThemeId={selectedTheme?.id} />
<div className={styles.globalTogglesContainer}>
<ThemePicker selectedThemeId={selectedTheme?.id} />
<DirSwitch dir={dir} />
</div>
<Subtitle />
<Description />
<hr className={styles.divider} />
Expand Down
Expand Up @@ -10,8 +10,13 @@ import { Parameters as Parameters_2 } from '@storybook/addons';
import { StoryContext } from '@storybook/addons';
import type { Theme } from '@fluentui/react-theme';

// @public (undocumented)
export const DIR_ID: "storybook_fluentui-react-addon_dir";

// @public
export interface FluentGlobals extends Args {
// (undocumented)
[DIR_ID]?: 'ltr' | 'rtl';
// (undocumented)
[STRICT_MODE_ID]?: boolean;
// (undocumented)
Expand Down
@@ -1,4 +1,5 @@
export const ADDON_ID = 'storybook_fluentui-react-addon';
export const THEME_ID = `${ADDON_ID}_theme` as const;

export const DIR_ID = `${ADDON_ID}_dir` as const;
export const STRICT_MODE_ID = `${ADDON_ID}_strict-mode` as const;
export const THEME_ID = `${ADDON_ID}_theme` as const;
Expand Up @@ -3,7 +3,7 @@ import * as React from 'react';
import { FluentProvider } from '@fluentui/react-provider';
import { Theme } from '@fluentui/react-theme';
import { themes, defaultTheme, ThemeIds } from '../theme';
import { THEME_ID } from '../constants';
import { DIR_ID, THEME_ID } from '../constants';
import { FluentGlobals, FluentStoryContext } from '../hooks';

const findTheme = (themeId?: ThemeIds) => {
Expand All @@ -25,12 +25,13 @@ export const withFluentProvider = (StoryFn: () => JSX.Element, context: FluentSt
const { mode } = parameters;
const isVrTest = mode === 'vr-test';

const dir = parameters.dir ?? globals[DIR_ID] ?? 'ltr';
const globalTheme = getActiveFluentTheme(globals);
const paramTheme = findTheme(parameters.fluentTheme);
const { theme } = paramTheme ?? globalTheme;

return (
<FluentProvider theme={theme} dir={parameters.dir}>
<FluentProvider theme={theme} dir={dir}>
{isVrTest ? StoryFn() : <FluentExampleContainer theme={theme}>{StoryFn()}</FluentExampleContainer>}
</FluentProvider>
);
Expand Down
3 changes: 2 additions & 1 deletion packages/react-components/react-storybook-addon/src/hooks.ts
@@ -1,7 +1,7 @@
import { useGlobals as useStorybookGlobals, Args as StorybookArgs } from '@storybook/api';
import { StoryContext as StorybookContext, Parameters } from '@storybook/addons';

import { STRICT_MODE_ID, THEME_ID } from './constants';
import { DIR_ID, STRICT_MODE_ID, THEME_ID } from './constants';
import type { ThemeIds } from './theme';

export interface FluentStoryContext extends StorybookContext {
Expand All @@ -13,6 +13,7 @@ export interface FluentStoryContext extends StorybookContext {
* Extends the storybook globals object to include fluent specific properties
*/
export interface FluentGlobals extends StorybookArgs {
[DIR_ID]?: 'ltr' | 'rtl';
[THEME_ID]?: ThemeIds;
[STRICT_MODE_ID]?: boolean;
}
Expand Down
@@ -1,5 +1,5 @@
export type { FluentGlobals, FluentParameters, FluentStoryContext } from './hooks';
export type { ThemeIds } from './theme';
export { themes } from './theme';
export { THEME_ID } from './constants';
export { DIR_ID, THEME_ID } from './constants';
export { parameters } from './hooks';

0 comments on commit 419d760

Please sign in to comment.