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
2 changes: 1 addition & 1 deletion code/__mocks__/lodash-es/add.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function add(a, b) {
function add(_a, _b) {
return 'mocked 3';
}

Expand Down
3 changes: 1 addition & 2 deletions code/addons/a11y/src/components/A11yContext.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ import {
import type { AxeResults } from 'axe-core';
import * as api from 'storybook/manager-api';

import { EVENTS, UI_STATE_ID } from '../constants';
import { RuleType } from '../types';
import { EVENTS } from '../constants';
import { A11yContextProvider, useA11yContext } from './A11yContext';

vi.mock('storybook/manager-api');
Expand Down
2 changes: 1 addition & 1 deletion code/addons/a11y/src/manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const Title = () => {
);
};

addons.register(ADDON_ID, (api) => {
addons.register(ADDON_ID, (_api) => {
Copy link
Member

Choose a reason for hiding this comment

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

I personally do not see how this improves things.
TS already warns about unused vars, and they get compiled away at build-time.

I'd be pretty unhappy about unused vars getting removed automatically, unless they start with a _-character, since I often work on new functions and consts first, then the usage.

Copy link
Contributor Author

@valentinpalkovic valentinpalkovic Nov 12, 2025

Choose a reason for hiding this comment

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

I'd be pretty unhappy about unused vars getting removed automatically, unless they start with a _-character, since I often work on new functions and consts first, then the usage.

You don't have to worry about this. Unused args aren't removed automatically. They are just marked as errors. You still have to remove them manually. That's pretty handy because we are forced to consider whether a particular argument is necessary or whether we want to keep it for the function signature.

You're right that TypeScript already warns about that in your IDE, but you don't have that warning during code reviews. It is not evident to the reviewer at first glance whether a variable/argument is used or not. Using an underscore notation improves the readability.

addons.add(PANEL_ID, {
title: '',
type: types.TOOL,
Expand Down
2 changes: 0 additions & 2 deletions code/addons/docs/src/blocks/blocks/ArgTypes.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import React from 'react';
Copy link
Member

Choose a reason for hiding this comment

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

We can't do this yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please add some elaboration for future reference.

Copy link
Member

Choose a reason for hiding this comment

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

Due to the way we build our code & how manager-builder is configured.
It was setup in the days before the jsx-runtime was a thing, and has has not been changed since.


import type { PlayFunctionContext } from 'storybook/internal/csf';

import type { Meta, StoryObj } from '@storybook/react-vite';
Expand Down
2 changes: 0 additions & 2 deletions code/addons/docs/src/blocks/blocks/Controls.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import React from 'react';

import type { PlayFunctionContext } from 'storybook/internal/csf';

import type { Meta, StoryObj } from '@storybook/react-vite';
Expand Down
2 changes: 0 additions & 2 deletions code/addons/docs/src/blocks/blocks/Description.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import React from 'react';

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

import { Button as ButtonComponent } from '../examples/Button';
Expand Down
2 changes: 1 addition & 1 deletion code/addons/docs/src/blocks/blocks/Source.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ComponentProps, FC } from 'react';
import type { ComponentProps } from 'react';
import React, { useContext, useMemo } from 'react';

import { SourceType } from 'storybook/internal/docs-tools';
Expand Down
2 changes: 0 additions & 2 deletions code/addons/docs/src/blocks/blocks/Story.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import React from 'react';

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

import { expect, waitFor } from 'storybook/test';
Expand Down
6 changes: 3 additions & 3 deletions code/addons/docs/src/blocks/blocks/mdx.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { FC, MouseEvent, PropsWithChildren, SyntheticEvent } from 'react';
import type { FC, MouseEvent, PropsWithChildren } from 'react';
import React, { useContext } from 'react';

import type { SupportedLanguage } from 'storybook/internal/components';
Expand Down Expand Up @@ -77,7 +77,7 @@ const AnchorInPage: FC<PropsWithChildren<AnchorInPageProps>> = ({ hash, children
<A
href={hash}
target="_self"
onClick={(event: SyntheticEvent) => {
onClick={() => {
const id = hash.substring(1);
const element = document.getElementById(id);
if (element) {
Expand Down Expand Up @@ -193,7 +193,7 @@ const HeaderWithOcticonAnchor: FC<PropsWithChildren<HeaderWithOcticonAnchorProps
href={hash}
tabIndex={-1}
target="_self"
onClick={(event: SyntheticEvent) => {
onClick={() => {
const element = document.getElementById(id);
if (element) {
navigate(context, hash);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { Link } from 'storybook/internal/components';
import {
BooleanControl,
ColorControl,
type ControlProps,
DateControl,
FilesControl,
NumberControl,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ const ExpanderIconRight = styled(ChevronRightIcon)(({ theme }) => ({
display: 'inline-block',
}));

const FlexWrapper = styled.span(({ theme }) => ({
const FlexWrapper = styled.span({
display: 'flex',
lineHeight: '20px',
alignItems: 'center',
}));
});

const Section = styled.td(({ theme }) => ({
position: 'relative',
Expand Down Expand Up @@ -125,7 +125,7 @@ export const SectionRow: FC<SectionRowProps> = ({
<>
<StyledTr title={helperText}>
<Level colSpan={1}>
<ClickIntercept onClick={(e) => setExpanded(!expanded)} tabIndex={0}>
<ClickIntercept onClick={() => setExpanded(!expanded)} tabIndex={0}>
{helperText}
</ClickIntercept>
<FlexWrapper>
Expand All @@ -135,7 +135,7 @@ export const SectionRow: FC<SectionRowProps> = ({
</Level>
<StyledTd colSpan={colSpan - 1}>
<ClickIntercept
onClick={(e) => setExpanded(!expanded)}
onClick={() => setExpanded(!expanded)}
tabIndex={-1}
style={{ outline: 'none' }}
>
Expand Down
68 changes: 33 additions & 35 deletions code/addons/docs/src/blocks/components/ArgsTable/Skeleton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,43 +18,41 @@ const Row = styled.div(({ theme }) => ({
},
}));

const Column = styled.div<{ position: 'first' | 'second' | 'third' | 'last' }>(
({ position, theme }) => {
const baseStyles = {
display: 'flex',
flexDirection: 'column' as const,
gap: 5,
padding: '10px 15px',
alignItems: 'flex-start',
};
const Column = styled.div<{ position: 'first' | 'second' | 'third' | 'last' }>(({ position }) => {
const baseStyles = {
display: 'flex',
flexDirection: 'column' as const,
gap: 5,
padding: '10px 15px',
alignItems: 'flex-start',
};

// Apply the same column width ratios as the actual ArgsTable component
switch (position) {
case 'first':
return {
...baseStyles,
width: '25%',
paddingLeft: 20,
};
case 'second':
return {
...baseStyles,
width: '35%',
};
case 'third':
return {
...baseStyles,
width: '15%',
};
case 'last':
return {
...baseStyles,
width: '25%',
paddingRight: 20,
};
}
// Apply the same column width ratios as the actual ArgsTable component
switch (position) {
case 'first':
return {
...baseStyles,
width: '25%',
paddingLeft: 20,
};
case 'second':
return {
...baseStyles,
width: '35%',
};
case 'third':
return {
...baseStyles,
width: '15%',
};
case 'last':
return {
...baseStyles,
width: '25%',
paddingRight: 20,
};
}
);
});

const SkeletonText = styled.div<{ width?: number | string; height?: number }>(
({ theme, width, height }) => ({
Expand Down
4 changes: 2 additions & 2 deletions code/addons/docs/src/blocks/components/Preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ export const Preview: FC<PreviewProps> = ({

const context = useContext(DocsContext);

const copyToClipboard = useCallback(async (text: string) => {
const copyToClipboard = useCallback(async () => {
const { createCopyToClipboardFunction } = await import('storybook/internal/components');
createCopyToClipboardFunction();
}, []);
Expand All @@ -226,7 +226,7 @@ export const Preview: FC<PreviewProps> = ({

e.preventDefault();
if (additionalActionItems.filter((item) => item.title === 'Copied').length === 0) {
copyToClipboard(source?.props.code ?? '').then(() => {
copyToClipboard().then(() => {
setAdditionalActionItems([
...additionalActionItems,
{
Expand Down
2 changes: 1 addition & 1 deletion code/addons/docs/src/blocks/controls/Color.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const Swatch = ({ value, style, ...props }: SwatchProps) => {
return <SwatchColor {...props} style={{ ...style, backgroundImage }} />;
};

const Input = styled(Form.Input)(({ theme, readOnly }) => ({
const Input = styled(Form.Input)(({ theme }) => ({
width: '100%',
paddingLeft: 30,
paddingRight: 30,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import React from 'react';

type PropTypes = { a?: string; b: string };
Expand Down
2 changes: 1 addition & 1 deletion code/addons/docs/src/blocks/examples/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export const Clicking: Story = {
</>
);
},
play: async ({ canvasElement, id }) => {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);

const button = canvas.getByText('Increment');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import React from 'react';

type PropTypes = { a?: string; b: string };
Expand Down
1 change: 0 additions & 1 deletion code/addons/docs/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { fileURLToPath } from 'node:url';

import { logger } from 'storybook/internal/node-logger';
import type { Options, PresetProperty, StorybookConfigRaw } from 'storybook/internal/types';
import { type CsfEnricher } from 'storybook/internal/types';

import type { CsfPluginOptions } from '@storybook/csf-plugin';

Expand Down
2 changes: 2 additions & 0 deletions code/addons/links/src/react/components/link.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ describe('LinkTo', () => {
expect(container.firstChild).toMatchInlineSnapshot(`
<a
href="originpathname?path=/story/foo--bar"
name="bar"
title="foo"
Comment on lines +61 to +62
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify that forwarding title and name to the DOM anchor is intentional.

The updated snapshot shows that title and name props are now being rendered as HTML attributes on the anchor element. These props appear to be Storybook-specific identifiers (used in the SELECT_STORY event at lines 96-97), not necessarily attributes meant for the DOM:

  1. The name attribute on <a> elements is deprecated in HTML5 (replaced by id)
  2. Forwarding internal Storybook identifiers (title, name) to the DOM may pollute the HTML with unnecessary attributes

This change appears to be a side effect of the ESLint unused variable fix—if title and name were previously destructured to prevent forwarding, removing that destructuring would cause them to spread onto the DOM element.

If this forwarding is unintentional, consider explicitly destructuring these props in link.tsx to exclude them from the rest spread:

const { title, name, ...restProps } = props;
// Use title and name for story selection only
// Spread only restProps onto the anchor element

Alternatively, prefix them with an underscore in the destructuring if they're intentionally unused in that scope:

const { title: _title, name: _name, ...restProps } = props;

🏁 Script executed:

#!/bin/bash
# Locate and inspect the LinkTo component implementation in link.tsx
find . -name "link.tsx" -type f | head -5

Length of output: 112


🏁 Script executed:

#!/bin/bash
# Inspect the test file to understand context around lines 47, 61-62, and 96-97
cat code/addons/links/src/react/components/link.test.tsx | head -110

Length of output: 2353


🏁 Script executed:

#!/bin/bash
# Search for how props are destructured/spread in the LinkTo component
rg -n "title|name" code/addons/links/src/react/components/link.tsx -A 2 -B 2

Length of output: 873


🏁 Script executed:

#!/bin/bash
# Get the full link.tsx component to see the render method
cat code/addons/links/src/react/components/link.tsx

Length of output: 2074


Destructure title and name in the render method to prevent them from spreading onto the DOM anchor element.

The analysis confirms the review comment is accurate. In code/addons/links/src/react/components/link.tsx, the render() method destructures { kind, story, children, ...rest } but does NOT explicitly extract title and name. This causes them to be included in the ...rest spread onto the anchor element, polluting the DOM with Storybook-internal identifiers.

The name attribute on <a> elements is deprecated in HTML5 and these properties are meant only for story identification in event emissions—not DOM attributes.

Fix by explicitly destructuring title and name in link.tsx line 79:

const { kind, story, title, name, children, ...rest } = this.props;

This prevents them from being included in ...rest and spreading to the anchor, consistent with how kind and story are already handled. The test snapshot at lines 61–62 will need to be updated to remove the name and title attributes from the expected anchor output.

🤖 Prompt for AI Agents
In code/addons/links/src/react/components/link.tsx around line 79 and the test
file code/addons/links/src/react/components/link.test.tsx around lines 61–62,
explicitly destructure title and name from this.props in the render method
(e.g., include title and name alongside kind and story) so they are not included
in ...rest and thus not spread onto the anchor element; then update the test
snapshot/expected output in link.test.tsx to remove the now-absent title and
name attributes from the anchor.

>
link
</a>
Expand Down
2 changes: 1 addition & 1 deletion code/addons/links/src/react/components/link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export default class LinkTo extends PureComponent<Props, State> {
};

render() {
const { kind, title = kind, story, name = story, children, ...rest } = this.props;
const { kind, story, children, ...rest } = this.props;
const { href } = this.state;

return (
Expand Down
4 changes: 2 additions & 2 deletions code/addons/links/template/stories/linkto.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ export const NormalizedTitleAndName = {
export const Callback = {
args: {
onClick: linkTo(
(event: Event) => 'addons-links-linkto',
(event: Event) => 'target'
() => 'addons-links-linkto',
() => 'target'
),
},
};
Expand Down
3 changes: 1 addition & 2 deletions code/addons/onboarding/src/components/Confetti/Confetti.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ const Wrapper = styled.div({
});

export const Confetti = React.memo(function Confetti({
timeToFade = 5000,
colors = ['#CA90FF', '#FC521F', '#66BF3C', '#FF4785', '#FFAE00', '#1EA7FD'],
...confettiProps
}: ComponentProps<typeof ReactConfetti> & { timeToFade?: number }) {
}: ComponentProps<typeof ReactConfetti>) {
return (
<Wrapper>
<ReactConfetti
Expand Down
4 changes: 0 additions & 4 deletions code/addons/pseudo-states/src/stories/CSSAtRules.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import React, { type ComponentProps } from 'react';

import { FORCE_REMOUNT } from 'storybook/internal/core-events';

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

import { useChannel, useStoryContext } from 'storybook/preview-api';

import { Button } from './CSSAtRules';
import './grid.css';

Expand Down
2 changes: 1 addition & 1 deletion code/addons/themes/src/decorators/class-name.decorator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const withThemeByClassName = <TRenderer extends Renderer = Renderer>({

Object.entries(themes)
.filter(([themeName]) => themeName !== selectedThemeName)
.forEach(([themeName, className]) => {
.forEach(([_themeName, className]) => {
const classes = classStringToArray(className);
if (classes.length > 0) {
parentElement.classList.remove(...classes);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import React from 'react';

import { Addon_TypesEnum } from 'storybook/internal/types';

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

import { ManagerContext, addons } from 'storybook/manager-api';
Expand Down
18 changes: 4 additions & 14 deletions code/addons/vitest/src/node/boot-test-runner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import { execaNode } from 'execa';

import { storeOptions } from '../constants';
import { log } from '../logger';
import type { StoreEvent } from '../types';
import type { StoreState } from '../types';
import type { StoreEvent, StoreState } from '../types';
import { killTestRunner, runTestRunner } from './boot-test-runner';

let stdout: (chunk: any) => void;
Expand Down Expand Up @@ -47,27 +46,18 @@ vi.mock('../logger', () => ({
vi.mock('../../../../core/src/shared/utils/module', () => ({
importMetaResolve: vi
.fn()
.mockImplementation(
(a) => 'file://' + join(__dirname, '..', '..', 'dist', 'node', 'vitest.js')
),
.mockImplementation(() => 'file://' + join(__dirname, '..', '..', 'dist', 'node', 'vitest.js')),
}));

let statusStoreSubscriber = vi.hoisted(() => undefined);
let testProviderStoreSubscriber = vi.hoisted(() => undefined);

vi.mock('storybook/internal/core-server', async (importOriginal) => {
const actual = await importOriginal<typeof import('storybook/internal/core-server')>();
return {
...actual,
internal_universalStatusStore: {
subscribe: (listener: any) => {
statusStoreSubscriber = listener;
},
subscribe: () => {},
},
internal_universalTestProviderStore: {
subscribe: (listener: any) => {
testProviderStoreSubscriber = listener;
},
subscribe: () => {},
},
};
});
Expand Down
3 changes: 0 additions & 3 deletions code/addons/vitest/src/node/test-manager.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { describe, expect, it, vi } from 'vitest';
import { createVitest as actualCreateVitest } from 'vitest/node';

import { Channel, type ChannelTransport } from 'storybook/internal/channels';
import { experimental_MockUniversalStore } from 'storybook/internal/core-server';
import type {
Options,
Expand Down Expand Up @@ -50,8 +49,6 @@ vi.mock('vitest/node', async (importOriginal) => ({

const createVitest = vi.mocked(actualCreateVitest);

const transport = { setHandler: vi.fn(), send: vi.fn() } satisfies ChannelTransport;
const mockChannel = new Channel({ transport });
const mockStore = new experimental_MockUniversalStore<StoreState, StoreEvent>(
{
...storeOptions,
Expand Down
4 changes: 1 addition & 3 deletions code/addons/vitest/src/preset.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { readFileSync } from 'node:fs';
import { mkdir } from 'node:fs/promises';

import type { Channel } from 'storybook/internal/channels';
Expand Down Expand Up @@ -33,8 +32,7 @@ import {
} from './constants';
import { log } from './logger';
import { runTestRunner } from './node/boot-test-runner';
import type { CachedState, ErrorLike, StoreState } from './types';
import type { StoreEvent } from './types';
import type { CachedState, ErrorLike, StoreEvent, StoreState } from './types';

type Event = {
type: 'test-discrepancy';
Expand Down
Loading