diff --git a/code/core/src/preview-api/modules/store/csf/normalizeInputTypes.test.ts b/code/core/src/preview-api/modules/store/csf/normalizeInputTypes.test.ts index 33b8f26e9625..e0dfe199c133 100644 --- a/code/core/src/preview-api/modules/store/csf/normalizeInputTypes.test.ts +++ b/code/core/src/preview-api/modules/store/csf/normalizeInputTypes.test.ts @@ -3,7 +3,7 @@ import { describe, expect, it } from 'vitest'; import { normalizeInputType, normalizeInputTypes } from './normalizeInputTypes'; describe('normalizeInputType', () => { - it('does nothing to strict types', () => { + it('normalizes strict types and sets disable: false when type is present', () => { expect( normalizeInputType( { @@ -18,12 +18,29 @@ describe('normalizeInputType', () => { ).toEqual({ name: 'name', type: { name: 'string' }, - control: { type: 'text' }, + control: { type: 'text', disable: false }, description: 'description', defaultValue: 'defaultValue', }); }); + it('preserves strict types with explicit disable', () => { + expect( + normalizeInputType( + { + name: 'name', + type: { name: 'string' }, + control: { type: 'text', disable: true }, + }, + 'arg' + ) + ).toEqual({ + name: 'name', + type: { name: 'string' }, + control: { type: 'text', disable: true }, + }); + }); + it('fills in unstrict types', () => { expect( normalizeInputType( @@ -38,12 +55,40 @@ describe('normalizeInputType', () => { ).toEqual({ name: 'arg', type: { name: 'string' }, - control: { type: 'text' }, + control: { type: 'text', disable: false }, description: 'description', defaultValue: 'defaultValue', }); }); + it('sets disable: false when control type is specified to override inherited disable', () => { + expect( + normalizeInputType( + { + control: { type: 'select' }, + }, + 'arg' + ) + ).toEqual({ + name: 'arg', + control: { type: 'select', disable: false }, + }); + }); + + it('preserves explicit disable: true in control object', () => { + expect( + normalizeInputType( + { + control: { type: 'select', disable: true }, + }, + 'arg' + ) + ).toEqual({ + name: 'arg', + control: { type: 'select', disable: true }, + }); + }); + it('preserves disabled control via shortcut', () => { expect( normalizeInputType( diff --git a/code/core/src/preview-api/modules/store/csf/normalizeInputTypes.ts b/code/core/src/preview-api/modules/store/csf/normalizeInputTypes.ts index e36f81cc9c06..9426b0c2333f 100644 --- a/code/core/src/preview-api/modules/store/csf/normalizeInputTypes.ts +++ b/code/core/src/preview-api/modules/store/csf/normalizeInputTypes.ts @@ -11,8 +11,19 @@ const normalizeType = (type: InputType['type']): StrictInputType['type'] => { return typeof type === 'string' ? { name: type } : type; }; -const normalizeControl = (control: InputType['control']): StrictInputType['control'] => - typeof control === 'string' ? { type: control } : control; +const normalizeControl = (control: InputType['control']): StrictInputType['control'] => { + if (typeof control === 'string') { + // When explicitly setting a control type, ensure disable is false to override + // any inherited disable: true from parent argTypes (fixes #27091) + return { type: control, disable: false }; + } + // If control is an object with a type but no explicit disable, set disable: false + // to ensure it overrides any inherited disable: true + if (control && typeof control === 'object' && 'type' in control && !('disable' in control)) { + return { ...control, disable: false }; + } + return control; +}; export const normalizeInputType = (inputType: InputType, key: string): StrictInputType => { const { type, control, ...rest } = inputType;