Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ module.exports = /** @type {Omit<StorybookConfig,'typescript'|'babel'>} */ ({
'@storybook/addon-knobs/preset',
'storybook-addon-performance',
'storybook-addon-export-to-codesandbox',
'@fluentui/react-storybook-addon',
],
webpackFinal: config => {
const tsPaths = new TsconfigPathsPlugin({
Expand Down
4 changes: 2 additions & 2 deletions .storybook/preview.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { withFluentProvider, withStrictMode } from '@fluentui/react-storybook';
import { withStrictMode } from '@fluentui/react-storybook';
import 'cypress-storybook/react';
import * as dedent from 'dedent';

/** @type {NonNullable<import('@storybook/react').Story['decorators']>} */
export const decorators = [withFluentProvider, withStrictMode];
export const decorators = [withStrictMode];

/** @type {import('@storybook/react').Parameters} */
export const parameters = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "experiment(storybook): Version picker",
"packageName": "@fluentui/react-components",
"email": "lingfangao@hotmail.com",
"dependentChangeType": "none"
}
2 changes: 2 additions & 0 deletions packages/react-components/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
STORYBOOK_CHROMATIC_APPID=6002298f95a00c00213f4d55.chromatic.com
STORYBOOK_VERSION_API_BASEURL=https://fluentstorybookversion.azurewebsites.net
12 changes: 12 additions & 0 deletions packages/react-components/.storybook/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,16 @@ addons.setConfig({
showPanel: true,
panelPosition: 'right',
theme,
toolbar: {
zoom: { hidden: true },
outline: { hidden: true },
eject: { hidden: true },
copy: { hidden: true },
fullscreen: { hidden: true },
'storybook/background': { hidden: true },
'storybook/viewport': { hidden: true },
'storybook/measure-addon/tool': { hidden: true },
'storybook/outline': { hidden: true },
'storybook/a11y/panel': { hidden: true },
},
});
5 changes: 4 additions & 1 deletion packages/react-components/.storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,7 @@ const options = {
export const decorators = [...rootPreview.decorators];

/** @type {typeof rootPreview.parameters} */
export const parameters = { ...rootPreview.parameters, options };
export const parameters = {
...rootPreview.parameters,
options,
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as React from 'react';
// eslint-disable-next-line import/no-extraneous-dependencies
import { Source } from '@storybook/addon-docs';
import { makeStyles } from '@fluentui/react-make-styles';

Expand Down
3 changes: 3 additions & 0 deletions packages/react-storybook-addon/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"react": "16.8.6"
},
"dependencies": {
"@fluentui/react-theme": "9.0.0-beta.1",
"@fluentui/react-provider": "9.0.0-beta.2",
"@fluentui/react-make-styles": "9.0.0-beta.1",
"tslib": "^2.1.0"
},
"peerDependencies": {
Expand Down
76 changes: 76 additions & 0 deletions packages/react-storybook-addon/src/ThemePicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import * as React from 'react';
import { IconButton, Icons, TooltipLinkList, WithTooltip } from '@storybook/components';

import { ThemeIds, themes, defaultTheme } from './theme';
import { THEME_ID } from './constants';
import { useGlobals } from './hooks';

export interface ThemeSelectorItem {
id: string;
title: string;
onClick: () => void;
value: string;
active: boolean;
}

function createThemeItems(
value: typeof themes,
changeTheme: (id: ThemeIds) => void,
getCurrentTheme: () => ThemeIds,
): ThemeSelectorItem[] {
return value.map(item => {
return {
id: item.id,
title: item.id === defaultTheme.id ? `${item.label} (Default)` : item.label,
onClick: () => {
changeTheme(item.id);
},
value: item.id,
active: getCurrentTheme() === item.id,
};
});
}

export const ThemePicker = () => {
const [globals, updateGlobals] = useGlobals();
const selectedThemeId = globals[THEME_ID] ?? defaultTheme.id;
const selectedTheme = themes.find(entry => entry.id === selectedThemeId);

const isActive = selectedThemeId !== defaultTheme.id;

const setTheme = React.useCallback(
(id: ThemeIds) => {
updateGlobals({ [THEME_ID]: id });
},
[updateGlobals],
);

const renderTooltip = React.useCallback(
(props: { onHide: () => void }) => {
return (
<TooltipLinkList
links={createThemeItems(
themes,
id => {
setTheme(id);
props.onHide();
},
() => selectedThemeId,
)}
/>
);
},
[selectedThemeId, setTheme],
);

return (
<>
<WithTooltip placement="top" trigger="click" closeOnClick tooltip={renderTooltip}>
<IconButton key={THEME_ID} title="Change Fluent theme" active={isActive}>
<Icons icon="chevrondown" />
Theme: {selectedTheme?.label}
</IconButton>
</WithTooltip>
</>
);
};
58 changes: 58 additions & 0 deletions packages/react-storybook-addon/src/VersionPicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import * as React from 'react';
import { Icons, TooltipLinkList, WithTooltip, IconButton } from '@storybook/components';
import { VERSION_ID } from './constants';

export interface VersionPickerItem {
id: string;
title: string;
onClick: () => void;
value: string;
active: boolean;
}

function createVersionItems(value: VersionEntry[]): VersionPickerItem[] {
return value.map(item => {
return {
id: item.version,
title: item.version,
onClick: () => {
const href = `https://${item.commit}--${process.env.STORYBOOK_CHROMATIC_APPID}.chromatic.com`;
window.parent.location.href = href;
},
value: item.version,
active: process.env.STORYBOOK_PACKAGE_VERISION === item.version,
};
});
}

interface VersionEntry {
version: string;
commit: string;
}

export const VersionPicker = () => {
const [versions, setVersions] = React.useState<VersionEntry[]>([]);

React.useEffect(() => {
fetch(`${process.env.STORYBOOK_VERSION_API_BASEURL}/api/GetVersions`)
.then(res => res.json())
.then(json => {
setVersions(json);
});
}, []);

const renderTooltip = React.useCallback(() => {
return <TooltipLinkList links={createVersionItems(versions)} />;
}, [versions]);

return (
<>
<WithTooltip placement="top" trigger="click" closeOnClick tooltip={renderTooltip}>
<IconButton key={VERSION_ID} title="Change Fluent theme">
<Icons icon="chevrondown" />
Version: {process.env.STORYBOOK_PACKAGE_VERISION}
</IconButton>
</WithTooltip>
</>
);
};
6 changes: 5 additions & 1 deletion packages/react-storybook-addon/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
// @TODO - add addon constants
export const ADDON_ID = 'storybook/fluentui-react-addon';
export const THEME_ID = `${ADDON_ID}/theme` as const;
export const VERSION_ID = `${ADDON_ID}/versions` as const;
export const PARAM_KEY = `myAddonParameter`;
export const EVENTS = {} as const;
16 changes: 16 additions & 0 deletions packages/react-storybook-addon/src/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useGlobals as useStorybookGlobals, Args as StorybookArgs } from '@storybook/api';
import { StoryContext as StorybookContext } from '@storybook/addons';

import { THEME_ID } from './constants';
import { ThemeIds } from './theme';

export interface StoryContext extends StorybookContext {
globals: Globals;
}
export interface Globals extends StorybookArgs {
[THEME_ID]?: ThemeIds;
}

export function useGlobals(): [Globals, (newGlobals: Globals) => void] {
return useStorybookGlobals();
}
Empty file.
21 changes: 20 additions & 1 deletion packages/react-storybook-addon/src/preset/manager.ts
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
// @TODO - Register the addon
import { addons, types } from '@storybook/addons';

import { ADDON_ID, THEME_ID, VERSION_ID } from '../constants';
import { ThemePicker } from '../ThemePicker';
import { VersionPicker } from '../VersionPicker';

addons.register(ADDON_ID, () => {
addons.add(VERSION_ID, {
title: 'Fluent Version Picker',
type: types.TOOL,
match: ({ viewMode }) => !!(viewMode && viewMode.match(/^(story|docs)$/)),
render: VersionPicker,
});
addons.add(THEME_ID, {
title: 'Fluent Theme Picker',
type: types.TOOL,
match: ({ viewMode }) => !!(viewMode && viewMode.match(/^(story|docs)$/)),
render: ThemePicker,
});
});
4 changes: 3 additions & 1 deletion packages/react-storybook-addon/src/preset/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@
* https://storybook.js.org/docs/react/writing-stories/decorators#gatsby-focus-wrapper
*/

export const decorators = [];
import { withFluentProvider } from '../withFluentProvider';

export const decorators = [withFluentProvider];
27 changes: 27 additions & 0 deletions packages/react-storybook-addon/src/theme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
webLightTheme,
webDarkTheme,
webHighContrastTheme,
teamsLightTheme,
teamsDarkTheme,
teamsHighContrastTheme,
Theme,
} from '@fluentui/react-theme';

export { FluentProvider } from '@fluentui/react-provider';

export const themes = [
{ id: 'web-light', label: 'Web Light', theme: webLightTheme },
{ id: 'web-dark', label: 'Web Dark', theme: webDarkTheme },
{ id: 'web-high-contrast', label: 'Web High Contrast', theme: webHighContrastTheme },
{ 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];

export type ThemeIds = typeof themes[number]['id'];
export type ThemeLabels = typeof themes[number]['label'];

export { Theme };
38 changes: 38 additions & 0 deletions packages/react-storybook-addon/src/withFluentProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import * as React from 'react';
import { StoryFn as StoryFunction } from '@storybook/addons';

import { themes, defaultTheme, FluentProvider } from './theme';
import { THEME_ID } from './constants';
import { Globals, StoryContext } from './hooks';

import { makeStyles } from '@fluentui/react-make-styles';

const useStyles = makeStyles({
root: theme => ({
padding: '10px',
fontFamily: theme.fontFamilyBase,
background: theme.colorNeutralBackground1,
}),
});

const getActiveFluentTheme = (globals: Globals) => {
const selectedThemeId = globals[THEME_ID];
const { theme } = themes.find(value => value.id === selectedThemeId) ?? defaultTheme;

return { theme };
};

export const withFluentProvider = (StoryFn: StoryFunction<React.ReactElement>, context: StoryContext) => {
const { theme } = getActiveFluentTheme(context.globals);
return (
<FluentProvider theme={theme}>
<FluentExampleContainer>{StoryFn()}</FluentExampleContainer>
</FluentProvider>
);
};

const FluentExampleContainer: React.FC = props => {
const styles = useStyles();

return <div className={styles.root}>{props.children}</div>;
};
4 changes: 2 additions & 2 deletions packages/react-storybook/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +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 { withFluentProvider, withStrictMode } from '@fluentui/react-storybook';
import { withStrictMode } from '@fluentui/react-storybook';

// Register decorators on global level
export const decorators = [withKnobs, withFluentProvider, withStrictMode];
export const decorators = [withKnobs, withStrictMode];
```
4 changes: 0 additions & 4 deletions packages/react-storybook/etc/react-storybook.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,9 @@

import * as React_2 from 'react';

// @public (undocumented)
export const withFluentProvider: (...args: any) => any;

// @public (undocumented)
export const withStrictMode: (storyFn: () => React_2.ReactNode) => JSX.Element;


// (No @packageDocumentation comment for this package)

```
1 change: 0 additions & 1 deletion packages/react-storybook/src/decorators/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export * from './withFluentProvider';
export * from './withStrictMode';
20 changes: 0 additions & 20 deletions packages/react-storybook/src/decorators/withFluentProvider.tsx

This file was deleted.

4 changes: 2 additions & 2 deletions packages/react-storybook/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { withFluentProvider, withStrictMode } from './index';
import { withStrictMode } from './index';

describe(`public api`, () => {
describe(`decorators`, () => {
it(`should work`, () => {
const decorators = [withFluentProvider, withStrictMode];
const decorators = [withStrictMode];

// @TODO - added proper tests
expect(decorators).toBeDefined();
Expand Down
2 changes: 1 addition & 1 deletion packages/storybook/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './decorators/index';
export { withFluentProvider, withStrictMode } from '@fluentui/react-storybook';
export { withStrictMode } from '@fluentui/react-storybook';