Skip to content

Commit

Permalink
Merge pull request #26004 from storybookjs/version-non-patch-from-8.0…
Browse files Browse the repository at this point in the history
….0-beta.2

Release: Prerelease 8.0.0-beta.3
  • Loading branch information
shilman authored Feb 17, 2024
2 parents 3ba1cf3 + 9b53955 commit 0a21bd6
Show file tree
Hide file tree
Showing 50 changed files with 1,262 additions and 334 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
## 7.6.16

- Addon Themes: Make type generic less strict - [#26042](https://github.com/storybookjs/storybook/pull/26042), thanks [@yannbf](https://github.com/yannbf)!
- Interaction: Make sure that adding spies doesn't cause infinite loops with self referencing args [#26019](https://github.com/storybookjs/storybook/pull/26019), thanks @kasperpeulen!

## 7.6.15

This release accidentally didn't contain anything.

## 7.6.14

- Core: Fix boolean `true` args in URL getting ignored - [#25950](https://github.com/storybookjs/storybook/pull/25950), thanks [@JReinhold](https://github.com/JReinhold)!

## 7.6.13

- Next.js: Fix frameworkOptions resolution - [#25907](https://github.com/storybookjs/storybook/pull/25907), thanks [@valentinpalkovic](https://github.com/valentinpalkovic)!
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.prerelease.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## 8.0.0-beta.3

- Addon-actions: Add spy to action for explicit actions - [#26033](https://github.com/storybookjs/storybook/pull/26033), thanks [@kasperpeulen](https://github.com/kasperpeulen)!
- Addon-themes: Make type generic less strict - [#26042](https://github.com/storybookjs/storybook/pull/26042), thanks [@yannbf](https://github.com/yannbf)!
- Addon-docs: Fix pnpm+Vite failing to build with `@storybook/theming` Rollup error - [#26024](https://github.com/storybookjs/storybook/pull/26024), thanks [@JReinhold](https://github.com/JReinhold)!
- CLI: Refactor to add autoblockers - [#25934](https://github.com/storybookjs/storybook/pull/25934), thanks [@ndelangen](https://github.com/ndelangen)!
- Codemod: Migrate to test package - [#25958](https://github.com/storybookjs/storybook/pull/25958), thanks [@kasperpeulen](https://github.com/kasperpeulen)!
- Portable stories: Only provide a play function wrapper if it exists - [#25974](https://github.com/storybookjs/storybook/pull/25974), thanks [@yannbf](https://github.com/yannbf)!
- Test: Bump user-event to 14.5.2 - [#25889](https://github.com/storybookjs/storybook/pull/25889), thanks [@kasperpeulen](https://github.com/kasperpeulen)!

## 8.0.0-beta.2

- Core: Fix boolean `true` args in URL getting ignored - [#25950](https://github.com/storybookjs/storybook/pull/25950), thanks [@JReinhold](https://github.com/JReinhold)!
Expand Down
101 changes: 99 additions & 2 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
<h1>Migration</h1>

- [From version 7.x to 8.0.0](#from-version-7x-to-800)
- [Type change in `composeStories` API](#type-change-in-composestories-api)
- [Tab addons are now routed to a query parameter](#tab-addons-are-now-routed-to-a-query-parameter)
- [Default keyboard shortcuts changed](#default-keyboard-shortcuts-changed)
- [Manager addons are now rendered with React 18](#manager-addons-are-now-rendered-with-react-18)
- [Removal of `storiesOf`-API](#removal-of-storiesof-api)
- [Removed deprecated shim packages](#removed-deprecated-shim-packages)
- [Framework-specific Vite plugins have to be explicitly added](#framework-specific-vite-plugins-have-to-be-explicitly-added)
- [For React:](#for-react)
- [For Vue:](#for-vue)
- [For Svelte (without Sveltekit):](#for-svelte-without-sveltekit)
- [For Preact:](#for-preact)
- [For Solid:](#for-solid)
- [For Qwik:](#for-qwik)
- [TurboSnap Vite plugin is no longer needed](#turbosnap-vite-plugin-is-no-longer-needed)
- [Implicit actions can not be used during rendering (for example in the play function)](#implicit-actions-can-not-be-used-during-rendering-for-example-in-the-play-function)
- [MDX related changes](#mdx-related-changes)
Expand Down Expand Up @@ -120,6 +127,7 @@
- [Story context is prepared before for supporting fine grained updates](#story-context-is-prepared-before-for-supporting-fine-grained-updates)
- [Changed decorator order between preview.js and addons/frameworks](#changed-decorator-order-between-previewjs-and-addonsframeworks)
- [Dark mode detection](#dark-mode-detection)
- [`addons.setConfig` should now be imported from `@storybook/manager-api`.](#addonssetconfig-should-now-be-imported-from-storybookmanager-api)
- [7.0 core addons changes](#70-core-addons-changes)
- [Removed auto injection of @storybook/addon-actions decorator](#removed-auto-injection-of-storybookaddon-actions-decorator)
- [Addon-backgrounds: Removed deprecated grid parameter](#addon-backgrounds-removed-deprecated-grid-parameter)
Expand Down Expand Up @@ -392,6 +400,23 @@

## From version 7.x to 8.0.0

### Type change in `composeStories` API

There is a TypeScript type change in the `play` function returned from `composeStories` or `composeStory` in `@storybook/react` or `@storybook/vue3`, where before it was always defined, now it is potentially undefined. This means that you might have to make a small change in your code, such as:

```ts
const { Primary } = composeStories(stories)

// before
await Primary.play(...)

// after
await Primary.play?.(...) // if you don't care whether the play function exists
await Primary.play!(...) // if you want a runtime error when the play function does not exist
```

There are plans to make the type of the play function be inferred based on your imported story's play function in a near future, so the types will be 100% accurate.

### Tab addons are now routed to a query parameter

The URL of a tab used to be: `http://localhost:6006/?path=/my-addon-tab/my-story`.
Expand Down Expand Up @@ -444,23 +469,82 @@ In Storybook 7, these packages existed for backwards compatibility, but were mar
- `@storybook/store` - this package has been merged into `@storybook/preview-api`.
- `@storybook/api` - this package has been replaced with `@storybook/manager-api`.

This section explains the rationale, and the required changed you might have to make: [New Addons API](#new-addons-api)
These sections explain the rationale, and the required changes you might have to make:

- [New Addons API](#new-addons-api)
- [`addons.setConfig` should now be imported from `@storybook/manager-api`.](#addonssetconfig-should-now-be-imported-from-storybookmanager-api)

### Framework-specific Vite plugins have to be explicitly added

In Storybook 7, we would automatically add frameworks-specific Vite plugins, e.g. `@vitejs/plugin-react` if not installed.
In Storybook 8 those plugins have to be added explicitly in the user's `vite.config.ts`:

#### For React:

```ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
});
```

#### For Vue:

```ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

export default defineConfig({
plugins: [vue()],
});
```

#### For Svelte (without Sveltekit):

```ts
import { defineConfig } from "vite";
import svelte from "@sveltejs/vite-plugin-svelte";

export default defineConfig({
plugins: [svelte()],
});
```

#### For Preact:

```ts
import { defineConfig } from "vite";
import preact from "@preact/preset-vite";

export default defineConfig({
plugins: [preact()],
});
```

#### For Solid:

```ts
import { defineConfig } from "vite";
import solid from "vite-plugin-solid";

export default defineConfig({
plugins: [solid()],
});
```

#### For Qwik:

```ts
import { defineConfig } from "vite";
import qwik from "vite-plugin-qwik";

export default defineConfig({
plugins: [qwik()],
});
```

### TurboSnap Vite plugin is no longer needed

At least in build mode, `builder-vite` now supports the `--webpack-stats-json` flag and will output `preview-stats.json`.
Expand Down Expand Up @@ -1949,6 +2033,19 @@ Earlier versions used the light theme by default, so if you don't set a theme an

To learn more about theming, read our [documentation](https://storybook.js.org/docs/react/configure/theming).

#### `addons.setConfig` should now be imported from `@storybook/manager-api`.

The previous package, `@storybook/addons`, is now deprecated and will be removed in 8.0.

```diff
- import { addons } from '@storybook/addons';
+ import { addons } from '@storybook/manager-api';

addons.setConfig({
// ...
})
```

### 7.0 core addons changes

#### Removed auto injection of @storybook/addon-actions decorator
Expand Down
1 change: 1 addition & 0 deletions code/addons/actions/src/runtime/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export function action(name: string, options: ActionOptions = {}): HandlerFuncti
channel.emit(EVENT_ID, actionDisplayToEmit);
};
handler.isAction = true;
handler.implicit = options.implicit;

return handler;
}
8 changes: 7 additions & 1 deletion code/addons/docs/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,14 @@ export const viteFinal = async (config: any, options: Options) => {
react,
'react-dom': reactDom,
'@mdx-js/react': mdx,
/**
* The following aliases are used to ensure a single instance of these packages are used in situations where they are duplicated
* The packages will be duplicated by the package manager when the user has react installed with another version than 18.2.0
*/
'@storybook/theming': dirname(require.resolve('@storybook/theming')),
'@storybook/components': dirname(require.resolve('@storybook/components')),
'@storybook/blocks': dirname(require.resolve('@storybook/blocks')),
},
dedupe: ['@storybook/theming', '@storybook/components', '@storybook/blocks'],
},
}),
};
Expand Down
63 changes: 42 additions & 21 deletions code/addons/interactions/src/preview.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/* eslint-disable no-underscore-dangle */
import type {
Args,
LoaderFunction,
ArgsEnhancer,
PlayFunction,
PlayFunctionContext,
Renderer,
StepLabel,
} from '@storybook/types';
import { fn, isMockFunction } from '@storybook/test';
import { instrument } from '@storybook/instrumenter';

export const { step: runStep } = instrument(
Expand All @@ -16,26 +16,47 @@ export const { step: runStep } = instrument(
{ intercept: true }
);

const instrumentSpies: LoaderFunction = ({ initialArgs }) => {
const argTypesWithAction = Object.entries(initialArgs).filter(
([, value]) =>
typeof value === 'function' &&
'_isMockFunction' in value &&
value._isMockFunction &&
!value._instrumented
);

return argTypesWithAction.reduce((acc, [key, value]) => {
const instrumented = instrument({ [key]: () => value }, { retain: true })[key];
acc[key] = instrumented();
// this enhancer is being called multiple times

value._instrumented = true;
return acc;
}, {} as Args);
const traverseArgs = (value: unknown, depth = 0, key?: string): any => {
// Make sure to not get in infinite loops with self referencing args
if (depth > 5) return value;
if (value == null) return value;
if (isMockFunction(value)) {
// Makes sure we get the arg name in the interactions panel
if (key) value.mockName(key);
return value;
}

// wrap explicit actions in a spy
if (
typeof value === 'function' &&
'isAction' in value &&
value.isAction &&
!('implicit' in value && value.implicit)
) {
const mock = fn(value as any);
if (key) mock.mockName(key);
return mock;
}

if (Array.isArray(value)) {
depth++;
return value.map((item) => traverseArgs(item, depth));
}

if (typeof value === 'object' && value.constructor === Object) {
depth++;
// We have to mutate the original object for this to survive HMR.
for (const [k, v] of Object.entries(value)) {
(value as Record<string, unknown>)[k] = traverseArgs(v, depth, k);
}
return value;
}
return value;
};

export const argsEnhancers = [instrumentSpies];
const wrapActionsInSpyFns: ArgsEnhancer<Renderer> = ({ initialArgs }) => traverseArgs(initialArgs);

export const argsEnhancers = [wrapActionsInSpyFns];

export const parameters = {
throwPlayFunctionExceptions: false,
Expand Down
3 changes: 2 additions & 1 deletion code/addons/themes/src/decorators/class-name.decorator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ const DEFAULT_ELEMENT_SELECTOR = 'html';

const classStringToArray = (classString: string) => classString.split(' ').filter(Boolean);

export const withThemeByClassName = <TRenderer extends Renderer = Renderer>({
// TODO check with @kasperpeulen: change the types so they can be correctly inferred from context e.g. <Story extends (...args: any[]) => any>
export const withThemeByClassName = <TRenderer extends Renderer = any>({
themes,
defaultTheme,
parentSelector = DEFAULT_ELEMENT_SELECTOR,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export interface DataAttributeStrategyConfiguration {
const DEFAULT_ELEMENT_SELECTOR = 'html';
const DEFAULT_DATA_ATTRIBUTE = 'data-theme';

export const withThemeByDataAttribute = <TRenderer extends Renderer = Renderer>({
// TODO check with @kasperpeulen: change the types so they can be correctly inferred from context e.g. <Story extends (...args: any[]) => any>
export const withThemeByDataAttribute = <TRenderer extends Renderer = any>({
themes,
defaultTheme,
parentSelector = DEFAULT_ELEMENT_SELECTOR,
Expand Down
3 changes: 2 additions & 1 deletion code/addons/themes/src/decorators/provider.decorator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export interface ProviderStrategyConfiguration {

const pluckThemeFromKeyPairTuple = ([_, themeConfig]: [string, Theme]): Theme => themeConfig;

export const withThemeFromJSXProvider = <TRenderer extends Renderer = Renderer>({
// TODO check with @kasperpeulen: change the types so they can be correctly inferred from context e.g. <Story extends (...args: any[]) => any>
export const withThemeFromJSXProvider = <TRenderer extends Renderer = any>({
Provider,
GlobalStyles,
defaultTheme,
Expand Down
Loading

0 comments on commit 0a21bd6

Please sign in to comment.