Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI: refactor Canvas component so we can improve types for PREVIEW addons and TAB addons #23311

Merged
merged 21 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7f518f2
add more jsdoc
ndelangen Jul 4, 2023
a175244
types refactor & cleanup
ndelangen Jul 4, 2023
a51e2ef
fixes
ndelangen Jul 4, 2023
82f3a92
cleaning up types, make a special case for PREVIEW types addons, beca…
ndelangen Jul 5, 2023
ce322de
miniscule improvements in jsdoc/types
ndelangen Jul 5, 2023
fe2ac2f
overhaul addon types a bit more, make type for preview wrapper correc…
ndelangen Jul 5, 2023
fac7c0c
cleanup
ndelangen Jul 5, 2023
d39674f
fixes
ndelangen Jul 5, 2023
343f7ad
Merge branch 'norbert/page-addons-refactor' into norbert/addon-types-…
ndelangen Jul 5, 2023
cc39db8
Merge branch 'norbert/page-addons-refactor' into norbert/addon-types-…
ndelangen Jul 6, 2023
ae3a05b
Merge branch 'norbert/addon-types-follow-up' of github.com:storybookj…
ndelangen Jul 6, 2023
3b6b8aa
Merge branch 'norbert/page-addons-refactor' into norbert/addon-types-…
ndelangen Jul 6, 2023
cef21fc
Merge branch 'norbert/page-addons-refactor' into norbert/addon-types-…
ndelangen Jul 6, 2023
c863eb7
Merge branch 'norbert/page-addons-refactor' into norbert/addon-types-…
ndelangen Jul 6, 2023
4b705f6
Merge branch 'norbert/page-addons-refactor' into norbert/addon-types-…
ndelangen Jul 7, 2023
0e572a2
Merge branch 'norbert/page-addons-refactor' into norbert/addon-types-…
ndelangen Jul 10, 2023
7953660
Merge branch 'norbert/page-addons-refactor' into norbert/addon-types-…
ndelangen Jul 11, 2023
5acde6d
Merge branch 'norbert/page-addons-refactor' into norbert/addon-types-…
ndelangen Jul 11, 2023
8573eb1
Merge branch 'norbert/page-addons-refactor' into norbert/addon-types-…
ndelangen Jul 12, 2023
6382df6
Merge branch 'norbert/page-addons-refactor' into norbert/addon-types-…
ndelangen Jul 12, 2023
a80b1ff
Merge branch 'norbert/page-addons-refactor' into norbert/addon-types-…
ndelangen Jul 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 6 additions & 6 deletions code/lib/manager-api/src/modules/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type {
StoryPreparedPayload,
DocsPreparedPayload,
API_DocsEntry,
API_ViewMode,
} from '@storybook/types';
import {
PRELOAD_ENTRIES,
Expand Down Expand Up @@ -59,7 +60,6 @@ const STORY_INDEX_PATH = './index.json';
type Direction = -1 | 1;
type ParameterName = string;

type ViewMode = 'story' | 'info' | 'settings' | string | undefined;
type StoryUpdate = Partial<
Pick<API_StoryEntry, 'prepared' | 'parameters' | 'initialArgs' | 'argTypes' | 'args'>
>;
Expand All @@ -77,7 +77,7 @@ type DocsUpdate = Partial<Pick<API_DocsEntry, 'prepared' | 'parameters'>>;

export interface SubState extends API_LoadedRefData {
storyId: StoryId;
viewMode: ViewMode;
viewMode: API_ViewMode;
status: StatusState;
}

Expand Down Expand Up @@ -110,13 +110,13 @@ export interface SubAPI {
* @param {StoryId} [story] - The ID of the story to select.
* @param {Object} [obj] - An optional object containing additional options.
* @param {string} [obj.ref] - The ref ID of the story to select.
* @param {ViewMode} [obj.viewMode] - The view mode to display the story in.
* @param {API_ViewMode} [obj.viewMode] - The view mode to display the story in.
* @returns {void}
*/
selectStory: (
kindOrId?: string,
story?: StoryId,
obj?: { ref?: string; viewMode?: ViewMode }
obj?: { ref?: string; viewMode?: API_ViewMode }
) => void;
/**
* Returns the current story's data, including its ID, kind, name, and parameters.
Expand Down Expand Up @@ -595,7 +595,7 @@ export const init: ModuleFn<SubAPI, SubState, true> = ({
viewMode,
}: {
storyId: string;
viewMode: ViewMode;
viewMode: API_ViewMode;
[k: string]: any;
}) {
const { sourceType } = getEventMetadata(this, fullAPI);
Expand Down Expand Up @@ -720,7 +720,7 @@ export const init: ModuleFn<SubAPI, SubState, true> = ({
story?: StoryName;
name?: StoryName;
storyId: string;
viewMode: ViewMode;
viewMode: API_ViewMode;
}) {
const { ref } = getEventMetadata(this, fullAPI);

Expand Down
59 changes: 48 additions & 11 deletions code/lib/types/src/modules/addons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,8 @@ export type BaseStory<TArgs, StoryFnReturnType> =
| Addon_BaseStoryObject<TArgs, StoryFnReturnType>;

export interface Addon_RenderOptions {
active?: boolean;
key?: string;
active: boolean;
key: string;
}

/**
Expand All @@ -314,14 +314,57 @@ export type ReactJSXElement = {

export type Addon_Type = Addon_BaseType | Addon_PageType;
export interface Addon_BaseType {
/**
* The title of the addon.
* This can be a simple string, but it can also be a React.FunctionComponent or a React.ReactElement.
*/
title: FCWithoutChildren | string | ReactElement | ReactNode;
/**
* The type of the addon.
* @example Addon_TypesEnum.PANEL
*/
type: Addon_Types;
/**
* The unique id of the addon.
* @warn This will become non-optional in 8.0
*
* This needs to be globally unique, so we recommend prefixing it with your org name or npm package name.
*
* Do not prefix with `storybook`, this is reserved for core storybook feature and core addons.
*
* @example 'my-org-name/my-addon-name'
*/
id?: string;
/**
* This component will wrap your `render` function.
*
* With it you can determine if you want your addon to be rendered or not.
*
* This is to facilitate addons keeping state, and keep listening for events even when they are not currently on screen/rendered.
*/
route?: (routeOptions: RouterData) => string;
/**
* This will determine the value of `active` prop of your render function.
*/
match?: (matchOptions: RouterData) => boolean;
render: (renderOptions: Addon_RenderOptions) => any | null;
/**
* The actual contents of your addon.
*
* This is called as a function, so if you want to use hooks,
* your function needs to return a JSX.Element within which components are rendered
*/
render: (renderOptions: Addon_RenderOptions) => ReactElement<any, any> | null;
/**
* @unstable
*/
paramKey?: string;
/**
* @unstable
*/
disabled?: boolean;
/**
* @unstable
*/
hidden?: boolean;
}

Expand Down Expand Up @@ -405,7 +448,7 @@ export enum Addon_TypesEnum {
*/
PANEL = 'panel',
/**
* This adds items in the toolbar above the canvas - on the right side.
* This adds items in the toolbar above the canvas - on the left side.
*/
TOOL = 'tool',
/**
Expand All @@ -414,7 +457,7 @@ export enum Addon_TypesEnum {
TOOLEXTRA = 'toolextra',
/**
* This adds wrapper components around the canvas/iframe component storybook renders.
* @unstable
* @unstable this API is not stable yet, and is likely to change in 8.0.
*/
PREVIEW = 'preview',
/**
Expand All @@ -428,9 +471,3 @@ export enum Addon_TypesEnum {
*/
NOTES_ELEMENT = 'notes-element',
}

// type A = OrString<'bla' | 'foo'>;

// type OrString<T extends string> = T | (string & {});

// const x: A = 'ffffff';
14 changes: 6 additions & 8 deletions code/lib/types/src/modules/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,17 @@
import type { RenderData } from '../../../router/src/types';
import type { Channel } from '../../../channels/src';
import type { ThemeVars } from '../../../theming/src/types';
import type { ViewMode } from './csf';
import type { DocsOptions } from './core-common';
import type { API_HashEntry, API_IndexHash } from './api-stories';
import type { SetStoriesStory, SetStoriesStoryData } from './channelApi';
import type { Addon_Collection, Addon_Type } from './addons';
import type { Addon_Collection, Addon_RenderOptions, Addon_Type } from './addons';
import type { StoryIndex } from './storyIndex';

export type API_ViewMode = 'story' | 'info' | 'settings' | 'page' | undefined | string;
type OrString<T extends string> = T | (string & {});

export interface API_RenderOptions {
active: boolean;
key: string;
}
export type API_ViewMode = OrString<'story' | 'docs' | 'settings'> | undefined;

export type API_RenderOptions = Addon_RenderOptions;

export interface API_RouteOptions {
storyId: string;
Expand Down Expand Up @@ -62,7 +60,7 @@ export interface API_Provider<API> {

export type API_IframeRenderer = (
storyId: string,
viewMode: ViewMode,
viewMode: API_ViewMode,
id: string,
baseUrl: string,
scale: number,
Expand Down
4 changes: 2 additions & 2 deletions code/lib/types/src/modules/channelApi.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { API_ViewMode } from './api';
import type {
Args,
ArgTypes,
ComponentId,
Parameters,
StoryId,
StoryKind,
ViewMode,
Globals,
GlobalTypes,
} from './csf';
Expand All @@ -23,7 +23,7 @@ export interface SetStoriesStory {
[optionName: string]: any;
};
docsOnly?: boolean;
viewMode?: ViewMode;
viewMode?: API_ViewMode;
[parameterName: string]: any;
};
argTypes?: ArgTypes;
Expand Down
10 changes: 8 additions & 2 deletions code/lib/types/src/modules/csf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,19 @@ export type {
Tag,
} from '@storybook/csf';

export type ViewMode = ViewModeBase | 'story' | 'info' | 'settings' | string | undefined;
type OrString<T extends string> = T | (string & {});

export type ViewMode = OrString<ViewModeBase | 'settings'> | undefined;

type Layout = 'centered' | 'fullscreen' | 'padded' | 'none';

export interface StorybookParameters {
options?: Addon_OptionsParameter;
/** The layout property defines basic styles added to the preview body where the story is rendered. If you pass 'none', no styles are applied. */
/**
* The layout property defines basic styles added to the preview body where the story is rendered.
*
* If you pass `none`, no styles are applied.
*/
layout?: Layout;
}

Expand Down
11 changes: 5 additions & 6 deletions code/ui/manager/src/components/preview/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@ import { defaultWrappers, ApplyWrappers } from './wrappers';
import { ToolbarComp } from './toolbar';
import { FramesRenderer } from './FramesRenderer';

import type { PreviewProps } from './utils/types';
import type { PreviewProps, Wrapper } from './utils/types';

const { FEATURES } = global;

const getWrappers = (getFn: API['getElements']) =>
Object.values(getFn<Addon_BaseType>(types.PREVIEW));
const getTabs = (getFn: API['getElements']) => Object.values(getFn<Addon_BaseType>(types.TAB));
const getWrappers = (getFn: API['getElements']) => Object.values(getFn(types.PREVIEW));
const getTabs = (getFn: API['getElements']) => Object.values(getFn(types.TAB));

const canvasMapper = ({ state, api }: Combo) => ({
storyId: state.storyId,
Expand Down Expand Up @@ -58,7 +57,7 @@ const createCanvas = (id: string, baseUrl = 'iframe.html', withLoader = true): A
active,
}) => {
const wrappers = useMemo(
() => [...defaultWrappers, ...getWrappers(getElements)],
() => [...defaultWrappers, ...getWrappers(getElements)] as Wrapper[],
[getElements, ...defaultWrappers]
);

Expand Down Expand Up @@ -211,7 +210,7 @@ const Preview = React.memo<PreviewProps>(function Preview(props) {
const key = t.id || t.key || i;
return (
<Fragment key={key}>
<Location>{(lp) => <Render active={match(lp)} />}</Location>
<Location>{(lp) => <Render key={key} active={match(lp)} />}</Location>
ndelangen marked this conversation as resolved.
Show resolved Hide resolved
</Fragment>
);
})}
Expand Down
8 changes: 3 additions & 5 deletions code/ui/manager/src/components/preview/utils/types.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import type { FunctionComponent, ReactNode } from 'react';
import type { State, API, LeafEntry } from '@storybook/manager-api';
import type { StoryId } from '@storybook/types';

export type ViewMode = State['viewMode'];
import type { API_ViewMode, StoryId } from '@storybook/types';

export interface PreviewProps {
api: API;
viewMode: ViewMode;
viewMode: API_ViewMode;
refs: State['refs'];
storyId: StoryId;
entry: LeafEntry;
Expand Down Expand Up @@ -60,7 +58,7 @@ export interface FramesRendererProps {
refId: string;
baseUrl: string;
scale: number;
viewMode: ViewMode;
viewMode: API_ViewMode;
queryParams: State['customQueryParams'];
refs: State['refs'];
}
4 changes: 2 additions & 2 deletions code/ui/manager/src/components/preview/wrappers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ export const ApplyWrappers: FC<ApplyWrappersProps> = ({
);
};

export const defaultWrappers = [
export const defaultWrappers: Wrapper[] = [
{
render: (p) => (
<IframeWrapper id="storybook-preview-wrapper" hidden={!p.active}>
{p.children}
</IframeWrapper>
),
} as Wrapper,
},
];