Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
4cbe225
fix(docs): fix syntax error when parse object-form code snippets with…
ia319 Nov 6, 2025
4d5e94b
Merge branch 'next' into bug/32951-source-transform-error
ia319 Nov 6, 2025
cac2ba8
Remove external action from Github pages documentation
sekeidesign Nov 6, 2025
77feb01
Fix typos and improve comments in GitHub Action
sekeidesign Nov 6, 2025
b562180
Merge branch 'next' into patch-1
sekeidesign Nov 10, 2025
7ec05ad
Merge branch 'next' into patch-1
jonniebigodes Nov 18, 2025
cc19677
Fix controls displaying as object instead of select for optional unio…
tanujbhaud Nov 27, 2025
e5644ea
Merge branch 'next' into bug/32951-source-transform-error
ia319 Dec 2, 2025
b609db6
revert source wrapping and suppress Prettier errors in autodocs
ia319 Dec 2, 2025
1fafd35
UI: Fix close button on popovers with controlled state
Sidnioulz Dec 3, 2025
b5d1354
UI: Fix incorrect aria markup for long ArgValue summaries
Sidnioulz Dec 3, 2025
6da6931
UI: Fix broken tooltip in ArgValue details
Sidnioulz Dec 3, 2025
6a920e5
refactor: Rename story for consistency
Sidnioulz Dec 3, 2025
37e4266
Ensure reset item only appears in globals toolbar when specified
mrginglymus Dec 4, 2025
bb9681a
UI: Make ArgValue summary button more robust
Sidnioulz Dec 5, 2025
3c02ed8
Merge branch 'next' into sidnioulz/issue-33248
Sidnioulz Dec 5, 2025
5862706
UI: Ensure ArgValue Func button is actually a button
Sidnioulz Dec 5, 2025
2dc5fa9
UI: Align summary styling with default button styling
Sidnioulz Dec 5, 2025
691632d
UI: Make vertical alignment of TestStatusIcon more robust
Sidnioulz Dec 8, 2025
d3b4545
Fix type errors and linting issues in optional union enum handling
tanujbhaud Dec 8, 2025
ba1691e
Merge branch 'next' into fix/controls-optional-union-enum
tanujbhaud Dec 8, 2025
d837343
Fix TypeScript type errors: add TSLiteralType with value property
tanujbhaud Dec 8, 2025
eb8ee2c
Merge branch 'storybookjs:next' into patch-1
sekeidesign Dec 8, 2025
a3cfa0b
Remove env variables
sekeidesign Dec 8, 2025
1d419de
Add vite to devDependencies if it isn't installed yet
ghengeveld Dec 9, 2025
d5540e0
Initial plan
Copilot Dec 9, 2025
6fdffd2
Fix unit tests for nextjs-to-nextjs-vite migration
Copilot Dec 9, 2025
24f576e
Extract vite version to constant and add clarifying comments
Copilot Dec 9, 2025
983f196
Export VITE_DEFAULT_VERSION constant and remove redundant mock
Copilot Dec 9, 2025
3461e40
Merge pull request #33318 from storybookjs/copilot/sub-pr-33316
valentinpalkovic Dec 9, 2025
c79af92
Merge branch 'bug/32951-source-transform-error' of https://github.com…
ia319 Dec 10, 2025
324b069
Merge branch 'next' into bug/32951-source-transform-error
ia319 Dec 10, 2025
53a9799
Merge pull request #32963 from ia319/bug/32951-source-transform-error
valentinpalkovic Dec 10, 2025
df61600
Initial plan
Copilot Dec 10, 2025
9c70c31
Fix type error: change undefined to null in getDependencyVersion mock
Copilot Dec 10, 2025
bb47faf
Merge pull request #33321 from storybookjs/copilot/sub-pr-33316
valentinpalkovic Dec 10, 2025
ed3ace5
Merge branch 'next-release' into next
storybook-bot Dec 10, 2025
6127326
Update CHANGELOG.md for v10.1.6 [skip ci]
storybook-bot Dec 10, 2025
677bc88
Normalise global toolbar reset value to undefined
Sidnioulz Dec 10, 2025
b21d8fe
Docs: Add tests for long enum/func control descriptions
Sidnioulz Dec 10, 2025
c79e8f4
Docs: Add missing copyEvent on a create command
Sidnioulz Dec 10, 2025
b9a48c6
Docs: Fix incorrect links in the migration guide
jonniebigodes Dec 10, 2025
7332a39
Add codemod to the docs and remove docs reference
jonniebigodes Dec 10, 2025
f472a62
Fix formatting
jonniebigodes Dec 10, 2025
023ee26
Controls: Force object control JSON mode to reset
Sidnioulz Dec 10, 2025
dd4d6d1
Remove duplicated sentence
jonniebigodes Dec 10, 2025
39d842d
Grammar fixes
jonniebigodes Dec 10, 2025
1f0e751
Merge pull request #33328 from storybookjs/docs_fix_monorepo_broken_l…
jonniebigodes Dec 10, 2025
17e3369
Merge branch 'next' into fix/controls-optional-union-enum
Sidnioulz Dec 10, 2025
17f09da
Merge branch 'next' into patch-1
jonniebigodes Dec 10, 2025
aaae5ca
Merge pull request #32974 from sekeidesign/patch-1
jonniebigodes Dec 10, 2025
d15032f
Merge pull request #33324 from storybookjs/sidnioulz/instrument-more-…
valentinpalkovic Dec 10, 2025
63585ce
Merge pull request #33330 from storybookjs/sidnioulz/issue-24316
valentinpalkovic Dec 10, 2025
cfe4488
Merge pull request #33316 from storybookjs/nextjs-vite-automigration-…
valentinpalkovic Dec 10, 2025
7cd8fe8
Merge pull request #33305 from storybookjs/sidnioulz/issue-31719
valentinpalkovic Dec 10, 2025
8b278b0
Merge pull request #33200 from tanujbhaud/fix/controls-optional-union…
valentinpalkovic Dec 10, 2025
08d73d9
Merge pull request #33264 from storybookjs/sidnioulz/issue-33248
valentinpalkovic Dec 10, 2025
bfd821e
Merge pull request #33276 from mrginglymus/fix-globals-reset
valentinpalkovic Dec 10, 2025
9932826
Write changelog for 10.2.0-alpha.6 [skip ci]
storybook-bot Dec 10, 2025
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 10.1.6

- Manager: Do not display non-existing shortcuts in the settings page - [#32711](https://github.com/storybookjs/storybook/pull/32711), thanks @DKER2!
- Preview: Enforce inert body if manager is focus-trapped - [#33186](https://github.com/storybookjs/storybook/pull/33186), thanks @Sidnioulz!
- Telemetry: Await pending operations in getLastEvents to prevent race conditions - [#33285](https://github.com/storybookjs/storybook/pull/33285), thanks @valentinpalkovic!
- UI: Fix keyboard navigation bug for "reset" option in `Select` - [#33268](https://github.com/storybookjs/storybook/pull/33268), thanks @Sidnioulz!

## 10.1.5

- Addon-Vitest: Isolate error reasons during postinstall - [#33295](https://github.com/storybookjs/storybook/pull/33295), thanks @valentinpalkovic!
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.prerelease.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## 10.2.0-alpha.6

- Controls: Fix displaying as object instead of select for optional union types - [#33200](https://github.com/storybookjs/storybook/pull/33200), thanks @tanujbhaud!
- Controls: Force object control JSON mode to reset - [#33330](https://github.com/storybookjs/storybook/pull/33330), thanks @Sidnioulz!
- Docs-Blocks: Fix broken tooltip in ArgValue details - [#33264](https://github.com/storybookjs/storybook/pull/33264), thanks @Sidnioulz!
- Manager: Ensure reset item only appears in globals toolbar when specified - [#33276](https://github.com/storybookjs/storybook/pull/33276), thanks @mrginglymus!
- Nextjs-Vite: Install `vite` during migration if not installed yet - [#33316](https://github.com/storybookjs/storybook/pull/33316), thanks @ghengeveld!
- UI: Make vertical alignment of TestStatusIcon more robust - [#33305](https://github.com/storybookjs/storybook/pull/33305), thanks @Sidnioulz!

## 10.2.0-alpha.5

- Addon-Vitest: Added timeout for fetching localhost 6006 during global setup. - [#33232](https://github.com/storybookjs/storybook/pull/33232), thanks @snippy4!
Expand Down
690 changes: 341 additions & 349 deletions MIGRATION.md

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion code/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,6 @@ const parameters = {
plugins: [prettierPluginBabel, prettierPluginEstree],
});
} catch (error) {
console.error(error);
return source;
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import React from 'react';

import { ResetWrapper } from 'storybook/internal/components';

import type { Meta, StoryObj } from '@storybook/react-vite';

import { expect, screen } from 'storybook/test';

import { ArgRow } from './ArgRow';
import { TableWrapper } from './ArgsTable';

Expand All @@ -10,7 +14,7 @@ export default {
title: 'Components/ArgsTable/ArgRow',

decorators: [
(getStory: any) => (
(getStory) => (
<ResetWrapper>
<TableWrapper>
<tbody>{getStory()}</tbody>
Expand All @@ -21,7 +25,7 @@ export default {
argTypes: {
updateArgs: { action: 'updateArgs' },
},
};
} satisfies Meta<typeof ArgRow>;

export const String = {
args: {
Expand Down Expand Up @@ -309,6 +313,52 @@ export const Func = {
},
};

export const LongFunc = {
args: {
row: {
...Func.args.row,
table: {
...Func.args.row.table,
defaultValue: {
summary: 'func',
detail: `(a, b) => {
// Calculate various metrics between a and b
const lengthA = a.length;
const lengthB = b.length;

// Determine the longer string
const maxLength = Math.max(lengthA, lengthB);
const minLength = Math.min(lengthA, lengthB);

// Calculate similarity score
let matchCount = 0;
for (let i = 0; i < minLength; i++) {
if (a[i] === b[i]) {
matchCount++;
}
}

// Compute weighted average
const similarity = (matchCount / maxLength) * 100;

// Generate result string
const result = \`Similarity: \${similarity.toFixed(2)}%, Length diff: \${Math.abs(lengthA - lengthB)}\`;

return result;
}`,
},
},
},
},
play: async ({ canvas }) => {
const funcButton = canvas.getByRole('button', { name: 'func' });
funcButton.click();
expect(
await screen.findByText(/Calculate various metrics between a and b/)
).toBeInTheDocument();
},
} satisfies StoryObj<typeof ArgRow>;

const enumeration =
'"search" | "arrow-to-bottom" | "arrow-to-right" | "bell" | "check" | "check-circle"';
export const Enum = {
Expand Down Expand Up @@ -345,7 +395,20 @@ export const LongEnum = {
},
},
},
};
play: async ({ canvas, step }) => {
await step('Expand long enum', async () => {
canvas.getByRole('button', { name: 'Show 26 more...' }).click();
expect(await canvas.findByText(/exclamation-triangle/)).toBeVisible();
});
await step('Collapse long enum', async () => {
(await canvas.findByRole('button', { name: 'Show less...' })).click();
expect(await canvas.findByText(/exclamation-triangle/)).not.toBeVisible();
});
await step('Re-expand for visual test', async () => {
(await canvas.findByRole('button', { name: 'Show 26 more...' })).click();
});
},
} satisfies StoryObj<typeof ArgRow>;

const complexUnion =
'((a: string | SVGSVGElement) => void) | RefObject<SVGSVGElement | number> | [a|b] | {a|b}';
Expand Down
88 changes: 60 additions & 28 deletions code/addons/docs/src/blocks/components/ArgsTable/ArgValue.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import type { FC } from 'react';
import React, { useState } from 'react';

import { SyntaxHighlighter, TooltipProvider, codeCommon } from 'storybook/internal/components';
import { PopoverProvider, SyntaxHighlighter, codeCommon } from 'storybook/internal/components';

import { ChevronSmallDownIcon, ChevronSmallUpIcon } from '@storybook/icons';

import { uniq } from 'es-toolkit/array';
import memoize from 'memoizerific';
import { styled } from 'storybook/theming';

import type { PropSummaryValue } from './types';
Expand Down Expand Up @@ -37,6 +36,27 @@ const Summary = styled.div<{ isExpanded?: boolean }>(({ isExpanded }) => ({
minWidth: 100,
}));

const DetailsContainer = styled.details({
display: 'flex',
flexDirection: 'column',
summary: {
order: 2,
},
'summary::-webkit-details-marker': {
display: 'none',
},
'summary::marker': {
content: 'none',
},
});

const AlignedDetails = styled.div({
display: 'flex',
flexDirection: 'column',
flexWrap: 'wrap',
alignItems: 'flex-start',
});

const Text = styled.span<{ simple?: boolean }>(codeCommon, ({ theme, simple = false }) => ({
flex: '0 0 auto',
fontFamily: theme.typography.fonts.mono,
Expand All @@ -57,29 +77,40 @@ const Text = styled.span<{ simple?: boolean }>(codeCommon, ({ theme, simple = fa
}),
}));

const ExpandButton = styled.button(({ theme }) => ({
const ExpandButton = styled.summary(({ theme }) => ({
fontFamily: theme.typography.fonts.mono,
color: theme.color.secondary,
marginBottom: '4px',
cursor: 'pointer',
lineHeight: 'normal',
margin: '0 0 4px',
padding: '1px 6px',
background: 'none',
border: 'none',
}));

const Expandable = styled.div(codeCommon, ({ theme }) => ({
const Expandable = styled.button(codeCommon, ({ theme }) => ({
fontFamily: theme.typography.fonts.mono,
color: theme.color.secondary,
fontSize: theme.typography.size.s1, // overrides codeCommon
margin: 0,
whiteSpace: 'nowrap',
display: 'flex',
alignItems: 'center',
cursor: 'pointer',
'&:hover': {
border:
theme.base === 'light' ? '1px solid hsl(0 0 0 / 0.15)' : '1px solid hsl(0 0 100 / 0.15)',
},
'&:focus-visible': {
outline: `2px solid ${theme.color.secondary}`,
outlineOffset: '2px',
},
}));

const Detail = styled.div<{ width: string }>(({ theme, width }) => ({
width,
const Detail = styled.div(({ theme }) => ({
minWidth: 200,
maxWidth: 800,
padding: 15,
paddingRight: 16,
// Don't remove the mono fontFamily here even if it seems useless, this is used by the browser to calculate the length of a "ch" unit.
fontFamily: theme.typography.fonts.mono,
fontSize: theme.typography.size.s1,
Expand Down Expand Up @@ -107,12 +138,6 @@ const ArgText: FC<ArgTextProps> = ({ text, simple }) => {
return <Text simple={simple}>{text}</Text>;
};

const calculateDetailWidth = memoize(1000)((detail: string): string => {
const lines = detail.split(/\r?\n/);

return `${Math.max(...lines.map((x) => x.length))}ch`;
});

const getSummaryItems = (summary: string) => {
if (!summary) {
return [summary];
Expand All @@ -123,13 +148,16 @@ const getSummaryItems = (summary: string) => {
return uniq(summaryItems);
};

const renderSummaryItems = (summaryItems: string[], isExpanded = true) => {
let items = summaryItems;
if (!isExpanded) {
items = summaryItems.slice(0, ITEMS_BEFORE_EXPANSION);
}
const renderSummaryItems = (summaryItems: string[]) => {
return summaryItems
.slice(0, ITEMS_BEFORE_EXPANSION)
.map((item) => <ArgText key={item} text={item === '' ? '""' : item} />);
};

return items.map((item) => <ArgText key={item} text={item === '' ? '""' : item} />);
const renderExpandedItems = (summaryItems: string[]) => {
return summaryItems
.slice(ITEMS_BEFORE_EXPANSION)
.map((item) => <ArgText key={item} text={item === '' ? '""' : item} />);
};

const ArgSummary: FC<ArgSummaryProps> = ({ value, initialExpandedArgs }) => {
Expand Down Expand Up @@ -160,25 +188,29 @@ const ArgSummary: FC<ArgSummaryProps> = ({ value, initialExpandedArgs }) => {

return hasManyItems ? (
<Summary isExpanded={isExpanded}>
{renderSummaryItems(summaryItems, isExpanded)}
<ExpandButton onClick={() => setIsExpanded(!isExpanded)}>
{isExpanded ? 'Show less...' : `Show ${itemsCount - ITEMS_BEFORE_EXPANSION} more...`}
</ExpandButton>
{renderSummaryItems(summaryItems)}
<DetailsContainer open={isExpanded} onToggle={(e) => setIsExpanded(e.currentTarget.open)}>
<AlignedDetails>{renderExpandedItems(summaryItems)}</AlignedDetails>
<ExpandButton role="button">
{isExpanded ? 'Show less...' : `Show ${itemsCount - ITEMS_BEFORE_EXPANSION} more...`}
</ExpandButton>
</DetailsContainer>
</Summary>
) : (
<Summary>{renderSummaryItems(summaryItems)}</Summary>
);
}

return (
<TooltipProvider
<PopoverProvider
placement="bottom"
visible={isOpen}
onVisibleChange={(isVisible) => {
setIsOpen(isVisible);
}}
tooltip={
<Detail width={calculateDetailWidth(detail)}>
hasCloseButton
popover={
<Detail>
<SyntaxHighlighter language="jsx" format={false}>
{detail}
</SyntaxHighlighter>
Expand All @@ -189,7 +221,7 @@ const ArgSummary: FC<ArgSummaryProps> = ({ value, initialExpandedArgs }) => {
<span>{summaryAsString}</span>
{isOpen ? <ChevronUpIcon /> : <ChevronDownIcon />}
</Expandable>
</TooltipProvider>
</PopoverProvider>
);
};

Expand Down
8 changes: 7 additions & 1 deletion code/addons/docs/src/blocks/controls/Object.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ export const ObjectControl: FC<ObjectProps> = ({ name, value, onChange, argType
}
}, [forceVisible]);

// Use string value as key to force re-render on Arg value reset.
const jsonString = useMemo(() => {
return JSON.stringify(data ?? '', null, 2);
}, [data]);

if (!hasData) {
return (
<Button
Expand All @@ -226,7 +231,8 @@ export const ObjectControl: FC<ObjectProps> = ({ name, value, onChange, argType
id={getControlId(name)}
minRows={3}
name={name}
defaultValue={value === null ? '' : JSON.stringify(value, null, 2)}
key={jsonString}
defaultValue={jsonString}
onBlur={(event: FocusEvent<HTMLTextAreaElement>) => updateRaw(event.target.value)}
placeholder="Edit JSON string..."
autoFocus={forceVisible}
Expand Down
6 changes: 3 additions & 3 deletions code/addons/vitest/src/components/TestProviderRender.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,9 @@ export const TestProviderRender: FC<TestProviderRenderProps> = ({
});
}}
>
<TestStatusIcon status={componentTestStatusIcon} isRunning={isRunning} />
{componentTestStatusValueToStoryIds['status-value:error'].length +
componentTestStatusValueToStoryIds['status-value:warning'].length || null}
<TestStatusIcon status={componentTestStatusIcon} isRunning={isRunning} />
</ActionList.Button>
</ActionList.Item>

Expand Down Expand Up @@ -343,12 +343,12 @@ export const TestProviderRender: FC<TestProviderRenderProps> = ({
}
>
<a href="/coverage/index.html" target="_blank">
{currentRun.coverageSummary.percentage}%
<TestStatusIcon
isRunning={isRunning}
percentage={currentRun.coverageSummary.percentage}
status={currentRun.coverageSummary.status}
/>
{currentRun.coverageSummary.percentage}%
</a>
</ActionList.Button>
) : (
Expand Down Expand Up @@ -412,9 +412,9 @@ export const TestProviderRender: FC<TestProviderRenderProps> = ({
});
}}
>
<TestStatusIcon status={a11yStatusIcon} isRunning={isRunning} />
{a11yStatusValueToStoryIds['status-value:error'].length +
a11yStatusValueToStoryIds['status-value:warning'].length || null}
<TestStatusIcon status={a11yStatusIcon} isRunning={isRunning} />
</ActionList.Button>
</ActionList.Item>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const PopoverProvider = ({
},
[onVisibleChange]
);
const onHide = useCallback(() => setIsOpen(false), []);
const onHide = useCallback(() => onOpenChange(false), [onOpenChange]);

return (
<DialogTrigger
Expand Down
Loading
Loading