From 7e88ba6396a285955698c1668c80f75d779177a2 Mon Sep 17 00:00:00 2001 From: Utkarsh Maurya Date: Tue, 28 Jul 2026 04:40:28 +0530 Subject: [PATCH 1/6] added default ellipsis truncation to ListItemText Signed-off-by: Utkarsh Maurya --- src/base/ListItemText/ListItemText.tsx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/base/ListItemText/ListItemText.tsx b/src/base/ListItemText/ListItemText.tsx index 158ef40d7..580f03dbe 100644 --- a/src/base/ListItemText/ListItemText.tsx +++ b/src/base/ListItemText/ListItemText.tsx @@ -3,6 +3,20 @@ import { ListItemTextProps as MuiListItemTextProps } from '@mui/material'; -export function ListItemText(props: MuiListItemTextProps): JSX.Element { - return ; +export function ListItemText({ + slotProps, + ...props +}: MuiListItemTextProps): JSX.Element { + const { primary, secondary, root } = slotProps ?? {}; + + return ( + + ); } From 6db452e462aff2275bb4d7c27ca66f7a68f2e4a8 Mon Sep 17 00:00:00 2001 From: Utkarsh Maurya Date: Tue, 28 Jul 2026 23:44:48 +0530 Subject: [PATCH 2/6] Preserve ownerState callbacks in ListItemText slotProps Signed-off-by: Utkarsh Maurya --- src/base/ListItemText/ListItemText.tsx | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/base/ListItemText/ListItemText.tsx b/src/base/ListItemText/ListItemText.tsx index 580f03dbe..ad13b490f 100644 --- a/src/base/ListItemText/ListItemText.tsx +++ b/src/base/ListItemText/ListItemText.tsx @@ -3,18 +3,30 @@ import { ListItemTextProps as MuiListItemTextProps } from '@mui/material'; +function withNoWrapDefault( + slotProp: T | ((ownerState: any) => T) | undefined +) { + if (typeof slotProp === 'function') { + return (ownerState: any) => ({ + noWrap: true, + ...slotProp(ownerState) + }); + } + return { noWrap: true, ...slotProp }; +} + export function ListItemText({ slotProps, ...props }: MuiListItemTextProps): JSX.Element { - const { primary, secondary, root } = slotProps ?? {}; + const { primary, secondary } = slotProps ?? {}; return ( From a5d611b2aa1c25d48c9a6dd6da4243b71137a240 Mon Sep 17 00:00:00 2001 From: Utkarsh Maurya Date: Wed, 29 Jul 2026 00:30:58 +0530 Subject: [PATCH 3/6] removed any with ListItemTextOwnerState type Signed-off-by: Utkarsh Maurya --- src/base/ListItemText/ListItemText.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/base/ListItemText/ListItemText.tsx b/src/base/ListItemText/ListItemText.tsx index ad13b490f..d918482b5 100644 --- a/src/base/ListItemText/ListItemText.tsx +++ b/src/base/ListItemText/ListItemText.tsx @@ -2,12 +2,13 @@ import { ListItemText as MuiListItemText, ListItemTextProps as MuiListItemTextProps } from '@mui/material'; +import type { ListItemTextOwnerState } from '@mui/material/ListItemText'; function withNoWrapDefault( - slotProp: T | ((ownerState: any) => T) | undefined + slotProp: T | ((ownerState: ListItemTextOwnerState) => T) | undefined ) { if (typeof slotProp === 'function') { - return (ownerState: any) => ({ + return (ownerState: ListItemTextOwnerState) => ({ noWrap: true, ...slotProp(ownerState) }); From 43971cc4b1d17ba444cbba73e2f18b5d640e993a Mon Sep 17 00:00:00 2001 From: Utkarsh Maurya Date: Wed, 5 Aug 2026 01:28:05 +0530 Subject: [PATCH 4/6] added explicit return type Signed-off-by: Utkarsh Maurya --- src/base/ListItemText/ListItemText.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base/ListItemText/ListItemText.tsx b/src/base/ListItemText/ListItemText.tsx index d918482b5..cb1c7c2a4 100644 --- a/src/base/ListItemText/ListItemText.tsx +++ b/src/base/ListItemText/ListItemText.tsx @@ -6,14 +6,14 @@ import type { ListItemTextOwnerState } from '@mui/material/ListItemText'; function withNoWrapDefault( slotProp: T | ((ownerState: ListItemTextOwnerState) => T) | undefined -) { +):T | ((ownerState: ListItemTextOwnerState) => T) { if (typeof slotProp === 'function') { return (ownerState: ListItemTextOwnerState) => ({ noWrap: true, ...slotProp(ownerState) }); } - return { noWrap: true, ...slotProp }; + return { noWrap: true, ...slotProp } as T; } export function ListItemText({ From a07266409575b446a7f53608be012a4ee4ba3f96 Mon Sep 17 00:00:00 2001 From: Utkarsh Maurya Date: Wed, 5 Aug 2026 01:32:36 +0530 Subject: [PATCH 5/6] fixed indentation Signed-off-by: Utkarsh Maurya --- src/base/ListItemText/ListItemText.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/ListItemText/ListItemText.tsx b/src/base/ListItemText/ListItemText.tsx index cb1c7c2a4..aa5e88d88 100644 --- a/src/base/ListItemText/ListItemText.tsx +++ b/src/base/ListItemText/ListItemText.tsx @@ -6,7 +6,7 @@ import type { ListItemTextOwnerState } from '@mui/material/ListItemText'; function withNoWrapDefault( slotProp: T | ((ownerState: ListItemTextOwnerState) => T) | undefined -):T | ((ownerState: ListItemTextOwnerState) => T) { +): T | ((ownerState: ListItemTextOwnerState) => T) { if (typeof slotProp === 'function') { return (ownerState: ListItemTextOwnerState) => ({ noWrap: true, From 4085dc2d0f4a40409b75d27d2372c8cbe46221ac Mon Sep 17 00:00:00 2001 From: Utkarsh Maurya Date: Sun, 13 Sep 2026 04:16:36 +0530 Subject: [PATCH 6/6] test: add unit tests for ListItemText slotProps and noWrap overrides Signed-off-by: Utkarsh Maurya --- src/__testing__/ListItemText.test.tsx | 197 ++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 src/__testing__/ListItemText.test.tsx diff --git a/src/__testing__/ListItemText.test.tsx b/src/__testing__/ListItemText.test.tsx new file mode 100644 index 000000000..e26d8ce70 --- /dev/null +++ b/src/__testing__/ListItemText.test.tsx @@ -0,0 +1,197 @@ +import { render, screen } from '@testing-library/react'; +import React from 'react'; +import { ListItemText } from '../base/ListItemText'; + +describe('ListItemText', () => { + describe('default truncation behavior', () => { + it('applies noWrap by default to primary text', () => { + render(); + const primaryElement = screen.getByText('Truncated Primary'); + expect(primaryElement.classList.contains('MuiTypography-noWrap')).toBe(true); + }); + + it('applies noWrap by default to secondary text', () => { + render(); + const secondaryElement = screen.getByText('Truncated Secondary'); + expect(secondaryElement.classList.contains('MuiTypography-noWrap')).toBe(true); + }); + }); + + describe('object-valued slotProps', () => { + it('preserves custom slotProps on primary while keeping noWrap by default', () => { + render( + + }} + /> + ); + const primaryElement = screen.getByTestId('custom-primary'); + expect(primaryElement.classList.contains('MuiTypography-noWrap')).toBe(true); + expect(primaryElement.classList.contains('custom-class')).toBe(true); + }); + + it('preserves custom slotProps on secondary while keeping noWrap by default', () => { + render( + + }} + /> + ); + const secondaryElement = screen.getByTestId('custom-secondary'); + expect(secondaryElement.classList.contains('MuiTypography-noWrap')).toBe(true); + expect(secondaryElement.classList.contains('custom-class-secondary')).toBe(true); + }); + + it('allows consumer to explicitly override noWrap to false on primary', () => { + render( + + ); + const primaryElement = screen.getByTestId('multiline-primary'); + expect(primaryElement.classList.contains('MuiTypography-noWrap')).toBe(false); + }); + + it('allows consumer to explicitly override noWrap to false on secondary', () => { + render( + + ); + const secondaryElement = screen.getByTestId('multiline-secondary'); + expect(secondaryElement.classList.contains('MuiTypography-noWrap')).toBe(false); + }); + }); + + describe('function-valued slotProps', () => { + it('executes primary slot callback with ownerState and retains noWrap by default', () => { + const primaryFn = jest.fn((ownerState) => ({ + 'data-testid': 'callback-primary', + className: ownerState.inset ? 'is-inset' : 'not-inset' + })); + + render( + + ); + + expect(primaryFn).toHaveBeenCalled(); + const ownerStateArg = primaryFn.mock.calls[0][0]; + expect(ownerStateArg.inset).toBe(true); + + const primaryElement = screen.getByTestId('callback-primary'); + expect(primaryElement.classList.contains('MuiTypography-noWrap')).toBe(true); + expect(primaryElement.classList.contains('is-inset')).toBe(true); + }); + + it('executes secondary slot callback with ownerState and retains noWrap by default', () => { + const secondaryFn = jest.fn(() => ({ + 'data-testid': 'callback-secondary', + className: 'dynamic-secondary' + })); + + render( + + ); + + expect(secondaryFn).toHaveBeenCalled(); + const secondaryElement = screen.getByTestId('callback-secondary'); + expect(secondaryElement.classList.contains('MuiTypography-noWrap')).toBe(true); + expect(secondaryElement.classList.contains('dynamic-secondary')).toBe(true); + }); + + it('allows function callback to explicitly override noWrap to false on primary', () => { + render( + ({ + noWrap: false, + 'data-testid': 'multiline-fn-primary' + }) + }} + /> + ); + const primaryElement = screen.getByTestId('multiline-fn-primary'); + expect(primaryElement.classList.contains('MuiTypography-noWrap')).toBe(false); + }); + + it('allows function callback to explicitly override noWrap to false on secondary', () => { + render( + ({ + noWrap: false, + 'data-testid': 'multiline-fn-secondary' + }) + }} + /> + ); + const secondaryElement = screen.getByTestId('multiline-fn-secondary'); + expect(secondaryElement.classList.contains('MuiTypography-noWrap')).toBe(false); + }); + }); + + describe('preservation of root slot and other props', () => { + it('preserves root slotProps', () => { + render( + + }} + /> + ); + const rootElement = screen.getByTestId('custom-root-slot'); + expect(rootElement.classList.contains('custom-root-class')).toBe(true); + }); + + it('forwards top-level props to root element', () => { + render( + + ); + const rootElement = screen.getByTestId('top-level-root'); + expect(rootElement.classList.contains('top-level-class')).toBe(true); + }); + }); +});