Skip to content

Commit 88e1398

Browse files
authored
fix(MessageItem): enable details view if Link overflows (#6859)
Also outline that `wrappingType="None"` is required if a `Link` is used as `titleText`. Fixes #6857
1 parent 0d41841 commit 88e1398

File tree

4 files changed

+75
-9
lines changed

4 files changed

+75
-9
lines changed

packages/main/src/components/MessageView/MessageItem.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export interface MessageItemPropTypes extends CommonProps {
2222
/**
2323
* Specifies the title of the message
2424
*
25-
* __Note:__ Although this prop accepts all HTML Elements, it is strongly recommended that you only use text or `Link` in order to preserve the intended design.
25+
* __Note:__ Although this prop accepts all HTML Elements, it is strongly recommended that you only use text or `Link` (with `wrappingType="None"`) in order to preserve the intended design.
2626
*/
2727
titleText: ReactNode;
2828

@@ -96,12 +96,20 @@ const MessageItem = forwardRef<ListItemCustomDomRef, MessageItemPropTypes>((prop
9696

9797
const hasChildren = Children.count(children);
9898
useEffect(() => {
99-
const titleTextObserver = new ResizeObserver(([titleTextSpan]) => {
100-
if (titleTextSpan.target.scrollWidth > titleTextSpan.target.clientWidth) {
101-
setIsTitleTextIsOverflowing(true);
102-
} else {
103-
setIsTitleTextIsOverflowing(false);
99+
const titleTextObserver = new ResizeObserver(([titleTextSpanEntry]) => {
100+
const child = titleTextSpanEntry.target.children[0];
101+
const target = titleTextSpanEntry.target;
102+
const isTargetOverflowing = target.scrollWidth > target.clientWidth;
103+
let isChildOverflowing = false;
104+
105+
if (!isTargetOverflowing) {
106+
const firstChild = child?.shadowRoot?.firstChild as HTMLAnchorElement | undefined;
107+
if (firstChild) {
108+
isChildOverflowing = firstChild.scrollWidth > firstChild.clientWidth;
109+
}
104110
}
111+
112+
setIsTitleTextIsOverflowing(isTargetOverflowing || isChildOverflowing);
105113
});
106114
if (!hasChildren && titleTextRef.current) {
107115
titleTextObserver.observe(titleTextRef.current);

packages/main/src/components/MessageView/MessageView.cy.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import WrappingType from '@ui5/webcomponents/dist/types/WrappingType.js';
12
import ValueState from '@ui5/webcomponents-base/dist/types/ValueState.js';
3+
import { Link } from '@ui5/webcomponents-react';
24
import { useRef } from 'react';
35
import { MessageItem } from './MessageItem';
46
import { MessageView } from './index.js';
@@ -169,4 +171,46 @@ describe('MessageView', () => {
169171
cy.findByText('SubtitleText').should('not.exist');
170172
cy.findByText('1337').should('not.exist');
171173
});
174+
175+
it('MessageItem - titleText overflow', () => {
176+
const selectSpy = cy.spy().as('select');
177+
cy.mount(
178+
<MessageView style={{ width: '500px' }} showDetailsPageHeader onItemSelect={selectSpy}>
179+
<MessageItem
180+
data-testid="item1"
181+
titleText={
182+
<Link wrappingType={WrappingType.None}>
183+
Long Error Message Type without children/details including a Link as `titleText` which has
184+
wrappingType="None" applied. - The details view is only available if the `titleText` is not fully visible.
185+
It is NOT recommended to use long titles!
186+
</Link>
187+
}
188+
type={ValueState.Negative}
189+
counter={3}
190+
/>
191+
<MessageItem
192+
data-testid="item2"
193+
titleText={
194+
'Long Empty Message Type (no title, no subtitle, no children/details) - The details view is only available if the `titleText` is not fully visible. It is NOT recommended to use long titles!'
195+
}
196+
groupName={'Products'}
197+
/>
198+
<MessageItem data-testid="item3" titleText="Error" type={ValueState.Negative} groupName="Group1" />
199+
</MessageView>
200+
);
201+
202+
cy.get('[name="slim-arrow-right"]').should('be.visible').and('have.length', 2);
203+
204+
cy.findByTestId('item1').click();
205+
cy.get('@select').should('have.been.calledOnce');
206+
cy.get('[name="slim-arrow-left"]').should('be.visible').and('have.length', 1).click();
207+
208+
cy.findByTestId('item2').click();
209+
cy.get('@select').should('have.been.calledTwice');
210+
cy.get('[name="slim-arrow-left"]').should('be.visible').and('have.length', 1).click();
211+
212+
cy.findByTestId('item3').click();
213+
cy.get('@select').should('have.been.calledTwice');
214+
cy.get('[name="slim-arrow-left"]').should('not.exist');
215+
});
172216
});

packages/main/src/components/MessageView/MessageView.stories.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import { generateMessageItems } from '@sb/mockData/generateMessageItems.js';
22
import type { Meta, StoryObj } from '@storybook/react';
33
import ButtonDesign from '@ui5/webcomponents/dist/types/ButtonDesign.js';
44
import TitleLevel from '@ui5/webcomponents/dist/types/TitleLevel.js';
5+
import WrappingType from '@ui5/webcomponents/dist/types/WrappingType.js';
56
import ValueState from '@ui5/webcomponents-base/dist/types/ValueState.js';
67
import arrowLeftIcon from '@ui5/webcomponents-icons/dist/slim-arrow-left.js';
78
import { useRef, useState } from 'react';
89
import { FlexBoxAlignItems, FlexBoxJustifyContent } from '../../enums/index.js';
910
import { Bar } from '../../webComponents/Bar/index.js';
1011
import { Button } from '../../webComponents/Button/index.js';
1112
import { Dialog } from '../../webComponents/Dialog/index.js';
13+
import { Link } from '../../webComponents/Link/index.js';
1214
import { ResponsivePopover } from '../../webComponents/ResponsivePopover/index.js';
1315
import { Title } from '../../webComponents/Title/index.js';
1416
import { FlexBox } from '../FlexBox/index.js';
@@ -17,8 +19,6 @@ import { MessageItem } from './MessageItem.js';
1719
import type { MessageViewDomRef } from './index.js';
1820
import { MessageView } from './index.js';
1921

20-
// TODO: check docs for outdated info
21-
2222
const meta = {
2323
title: 'User Feedback / MessageView',
2424
component: MessageView,
@@ -75,7 +75,19 @@ const meta = {
7575
>
7676
Informative message
7777
</MessageItem>,
78-
<MessageItem key={7} titleText={'Error Message Type'} type={ValueState.Negative} counter={3} />
78+
<MessageItem key={7} titleText={'Error Message Type'} type={ValueState.Negative} counter={3} />,
79+
<MessageItem
80+
key={8}
81+
titleText={
82+
<Link wrappingType={WrappingType.None}>
83+
Long Error Message Type without children/details including a Link as `titleText` which has
84+
wrappingType="None" applied. - The details view is only available if the `titleText` is not fully visible.
85+
It is NOT recommended to use long titles!
86+
</Link>
87+
}
88+
type={ValueState.Negative}
89+
counter={3}
90+
/>
7991
]
8092
}
8193
} satisfies Meta<typeof MessageView>;

packages/main/src/webComponents/Link/Link.stories.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Meta, StoryObj } from '@storybook/react';
22
import LinkDesign from '@ui5/webcomponents/dist/types/LinkDesign.js';
3+
import WrappingType from '@ui5/webcomponents/dist/types/WrappingType.js';
34
import { Link } from './index.js';
45

56
const meta = {
@@ -10,6 +11,7 @@ const meta = {
1011
},
1112
args: {
1213
design: LinkDesign.Default,
14+
wrappingType: WrappingType.None,
1315
children: 'Link Text'
1416
},
1517
tags: ['package:@ui5/webcomponents']

0 commit comments

Comments
 (0)