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

Preview: Simplify docsMode #18729

Merged
merged 6 commits into from
Jul 18, 2022
Merged
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
22 changes: 4 additions & 18 deletions lib/api/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@ export interface Combo {

interface ProviderData {
provider: provider.Provider;
docsMode: boolean;
}

export type ManagerProviderProps = RouterData &
ProviderData & {
docsMode: boolean;
children: ReactNode | ((props: Combo) => ReactNode);
};

Expand Down Expand Up @@ -189,22 +189,9 @@ class ManagerProvider extends Component<ManagerProviderProps, State> {
setState: (stateChange: Partial<State>, callback) => this.setState(stateChange, callback),
});

const routeData = { location, path, viewMode, singleStory, storyId, refId };
const routeData = { location, path, viewMode, singleStory, storyId, refId, docsMode };

// Initialize the state to be the initial (persisted) state of the store.
// This gives the modules the chance to read the persisted state, apply their defaults
// and override if necessary
const docsModeState = {
layout: { showToolbar: false, showPanel: false },
ui: { docsMode: true },
};

this.state = store.getInitialState(
getInitialState({
...routeData,
...(docsMode ? docsModeState : null),
})
);
this.state = store.getInitialState(getInitialState(routeData));

const apiData = {
navigate,
Expand Down Expand Up @@ -245,8 +232,7 @@ class ManagerProvider extends Component<ManagerProviderProps, State> {
location: props.location,
path: props.path,
refId: props.refId,
// if its a docsOnly page, even the 'story' view mode is considered 'docs'
viewMode: (props.docsMode && props.viewMode) === 'story' ? 'docs' : props.viewMode,
viewMode: props.viewMode,
storyId: props.storyId,
};
}
Expand Down
7 changes: 6 additions & 1 deletion lib/api/src/lib/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,11 @@ export interface PreparedStoryIndex {

export const transformSetStoriesStoryDataToStoriesHash = (
data: SetStoriesStoryData,
{ provider }: { provider: Provider }
{ provider, docsMode }: { provider: Provider; docsMode: boolean }
) =>
transformStoryIndexToStoriesHash(transformSetStoriesStoryDataToPreparedStoryIndex(data), {
provider,
docsMode,
});

const transformSetStoriesStoryDataToPreparedStoryIndex = (
Expand Down Expand Up @@ -339,8 +340,10 @@ export const transformStoryIndexToStoriesHash = (
index: PreparedStoryIndex,
{
provider,
docsMode,
}: {
provider: Provider;
docsMode: boolean;
}
): StoriesHash => {
if (!index.v) throw new Error('Composition: Missing stories.json version');
Expand All @@ -361,6 +364,8 @@ export const transformStoryIndexToStoriesHash = (
}

const storiesHashOutOfOrder = Object.values(entryValues).reduce((acc, item) => {
if (docsMode && item.type !== 'docs') return acc;

// First, split the title into a set of names, separated by '/' and trimmed.
const { title } = item;
const groups = title.trim().split(TITLE_PATH_SEPARATOR);
Expand Down
6 changes: 2 additions & 4 deletions lib/api/src/modules/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { dedent } from 'ts-dedent';
import merge from '../lib/merge';
import type { State, ModuleFn } from '../index';

const { DOCS_MODE, document } = global;
const { document } = global;

export type PanelPositions = 'bottom' | 'right';
export type ActiveTabsType = 'sidebar' | 'canvas' | 'addons';
Expand Down Expand Up @@ -38,7 +38,6 @@ export interface UI {
name?: string;
url?: string;
enableShortcuts: boolean;
docsMode: boolean;
}

export interface SubState {
Expand Down Expand Up @@ -73,11 +72,10 @@ export interface UIOptions {
const defaultState: SubState = {
ui: {
enableShortcuts: true,
docsMode: false,
},
layout: {
initialActive: ActiveTabs.CANVAS,
showToolbar: !DOCS_MODE,
showToolbar: true,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The toolbar will hide automatically as all entries are docs

isFullscreen: false,
showPanel: true,
showNav: true,
Expand Down
8 changes: 3 additions & 5 deletions lib/api/src/modules/refs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ const map = (
};

export const init: ModuleFn<SubAPI, SubState, void> = (
{ store, provider, singleStory },
{ store, provider, singleStory, docsMode },
{ runCheck = true } = {}
) => {
const api: SubAPI = {
Expand Down Expand Up @@ -249,12 +249,10 @@ export const init: ModuleFn<SubAPI, SubState, void> = (
if (setStoriesData) {
storiesHash = transformSetStoriesStoryDataToStoriesHash(
map(setStoriesData, ref, { storyMapper }),
{
provider,
}
{ provider, docsMode }
);
} else if (storyIndex) {
storiesHash = transformStoryIndexToStoriesHash(storyIndex, { provider });
storiesHash = transformStoryIndexToStoriesHash(storyIndex, { provider, docsMode });
}
if (storiesHash) storiesHash = addRefIds(storiesHash, ref);

Expand Down
10 changes: 4 additions & 6 deletions lib/api/src/modules/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import type {
import type { Args, ModuleFn } from '../index';
import type { ComposedRef } from './refs';

const { DOCS_MODE, FEATURES, fetch } = global;
const { FEATURES, fetch } = global;
const STORY_INDEX_PATH = './index.json';

type Direction = -1 | 1;
Expand Down Expand Up @@ -122,6 +122,7 @@ export const init: ModuleFn<SubAPI, SubState, true> = ({
provider,
storyId: initialStoryId,
viewMode: initialViewMode,
docsMode,
}) => {
const api: SubAPI = {
storyId: toId,
Expand Down Expand Up @@ -194,11 +195,6 @@ export const init: ModuleFn<SubAPI, SubState, true> = ({
const { storiesHash, storyId, refs, refId } = store.getState();
const story = api.getData(storyId, refId);

if (DOCS_MODE) {
api.jumpToComponent(direction);
return;
}
Comment on lines -197 to -200
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This happens naturally as all entries are docs, we don't have to skip over any.


// cannot navigate when there's no current selection
if (!story) {
return;
Expand All @@ -215,6 +211,7 @@ export const init: ModuleFn<SubAPI, SubState, true> = ({
// Now create storiesHash by reordering the above by group
const hash = transformSetStoriesStoryDataToStoriesHash(input, {
provider,
docsMode,
});

await store.setState({
Expand Down Expand Up @@ -362,6 +359,7 @@ export const init: ModuleFn<SubAPI, SubState, true> = ({
setStoryList: async (storyIndex: StoryIndex) => {
const hash = transformStoryIndexToStoriesHash(storyIndex, {
provider,
docsMode,
});

await store.setState({
Expand Down
1 change: 0 additions & 1 deletion lib/api/src/tests/layout.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ beforeEach(() => {
currentState = {
ui: {
enableShortcuts: true,
docsMode: false,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We weren't using this

},
layout: {
showToolbar: true,
Expand Down
160 changes: 136 additions & 24 deletions lib/api/src/tests/stories.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1181,36 +1181,58 @@ describe('stories API', () => {
expect(storedStoriesHash['component-c--story-4'].type).toBe('story');
});

// Skip this for now, will come back soon
it.skip('prefers parameters.docsOnly to inferred docsOnly status', async () => {
mockStories.mockReset().mockReturnValue({
'component-a--docs': {
type: 'story',
title: 'Component A',
name: 'Docs', // Called 'Docs' rather than 'Page'
importPath: './path/to/component-a.ts',
parameters: {
docsOnly: true,
describe('when DOCS_MODE = true', () => {
it('strips out story entries', async () => {
mockStories.mockReset().mockReturnValue({
'component-a--page': {
id: 'component-a--page',
title: 'Component A',
name: 'Page',
importPath: './path/to/component-a.ts',
},
},
});
'component-a--story-2': {
id: 'component-a--story-2',
title: 'Component A',
name: 'Story 2',
importPath: './path/to/component-a.ts',
},
'component-b': {
type: 'docs',
id: 'component-b--docs',
title: 'Component B',
name: 'Docs',
importPath: './path/to/component-b.ts',
storiesImports: [],
},
'component-c--story-4': {
id: 'component-c--story-4',
title: 'Component c',
name: 'Story 4',
importPath: './path/to/component-c.ts',
},
});

const navigate = jest.fn();
const store = createMockStore();
const fullAPI = Object.assign(new EventEmitter(), {
setStories: jest.fn(),
});
const navigate = jest.fn();
const store = createMockStore();
const fullAPI = Object.assign(new EventEmitter(), {
setStories: jest.fn(),
});

const { api, init } = initStories({ store, navigate, provider, fullAPI });
Object.assign(fullAPI, api);
const { api, init } = initStories({
store,
navigate,
provider,
fullAPI,
docsMode: true,
} as any);
Object.assign(fullAPI, api);

await init();
await init();

const { storiesHash: storedStoriesHash } = store.getState();
const { storiesHash: storedStoriesHash } = store.getState();

// We need exact key ordering, even if in theory JS doesn't guarantee it
expect(Object.keys(storedStoriesHash)).toEqual(['component-a', 'component-a--docs']);
expect(storedStoriesHash['component-a--docs'].parameters.docsOnly).toBe(true);
expect(Object.keys(storedStoriesHash)).toEqual(['component-b', 'component-b--docs']);
});
});
});

Expand Down Expand Up @@ -1354,6 +1376,96 @@ describe('stories API', () => {
});
});

it('prefers parameters.docsOnly to inferred docsOnly status', async () => {
const navigate = jest.fn();
const store = createMockStore();
const fullAPI = Object.assign(new EventEmitter(), {
setOptions: jest.fn(),
findRef: jest.fn(),
});

const { api, init } = initStories({ store, navigate, provider, fullAPI } as any);
Object.assign(fullAPI, api);

await init();

const setStoriesPayload = {
v: 2,
globalParameters: { global: 'global' },
kindParameters: { a: { kind: 'kind' } },
stories: {
'component-a--docs': {
type: 'story',
kind: 'Component A',
name: 'Docs', // Called 'Docs' rather than 'Page'
importPath: './path/to/component-a.ts',
parameters: {
docsOnly: true,
},
},
},
};
fullAPI.emit(SET_STORIES, setStoriesPayload);

const { storiesHash: storedStoriesHash } = store.getState();
expect(storedStoriesHash['component-a--docs']).toMatchObject({
type: 'docs',
id: 'component-a--docs',
parent: 'component-a',
title: 'Component A',
name: 'Docs',
});
});

describe('when DOCS_MODE = true', () => {
it('strips out stories entries', async () => {
const navigate = jest.fn();
const store = createMockStore();
const fullAPI = Object.assign(new EventEmitter(), {
setOptions: jest.fn(),
findRef: jest.fn(),
});

const { api, init } = initStories({
store,
navigate,
provider,
fullAPI,
docsMode: true,
} as any);
Object.assign(fullAPI, api);

await init();

const setStoriesPayload = {
v: 2,
globalParameters: { global: 'global' },
kindParameters: { a: { kind: 'kind' } },
stories: {
'component-a--docs': {
type: 'story',
kind: 'Component A',
name: 'Docs', // Called 'Docs' rather than 'Page'
importPath: './path/to/component-a.ts',
parameters: {
docsOnly: true,
},
},
'component-a--story': {
title: 'Story',
kind: 'Component A',
importPath: './path/to/component-a.ts',
parameters: { story: 'story' },
},
},
};
fullAPI.emit(SET_STORIES, setStoriesPayload);

const { storiesHash: storedStoriesHash } = store.getState();
expect(Object.keys(storedStoriesHash)).toEqual(['component-a', 'component-a--docs']);
});
});

it('normalizes parameters and calls setRef for external stories', () => {
const fullAPI = Object.assign(new EventEmitter());
const navigate = jest.fn();
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/src/components/sidebar/Refs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { AuthBlock, ErrorBlock, LoaderBlock, EmptyBlock } from './RefBlocks';
import { RefIndicator } from './RefIndicator';
import { Tree } from './Tree';
import { CollapseIcon } from './TreeNode';
import { DEFAULT_REF_ID } from './data';
import { DEFAULT_REF_ID } from './Sidebar';
import { Highlight, RefType } from './types';
import { getStateType } from './utils';

Expand Down
2 changes: 1 addition & 1 deletion lib/ui/src/components/sidebar/Search.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { stories } from './mockdata.large';
import { Search } from './Search';
import { SearchResults } from './SearchResults';
import { noResults } from './SearchResults.stories';
import { DEFAULT_REF_ID } from './data';
import { DEFAULT_REF_ID } from './Sidebar';
import { Selection } from './types';

const refId = DEFAULT_REF_ID;
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/src/components/sidebar/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import global from 'global';
import { transparentize } from 'polished';
import React, { useMemo, useRef, useState, useCallback } from 'react';

import { DEFAULT_REF_ID } from './data';
import { DEFAULT_REF_ID } from './Sidebar';
import {
CombinedDataset,
SearchItem,
Expand Down
Loading