Skip to content

Commit c338dc1

Browse files
authored
fix(AnalyticalTable): text ellipsis for strings & class for elements for custom Cell (#7951)
1 parent 1b2b050 commit c338dc1

File tree

8 files changed

+170
-44
lines changed

8 files changed

+170
-44
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4382,6 +4382,7 @@ describe('AnalyticalTable', () => {
43824382
.should('have.prop', 'scrollTop', 3000);
43834383
cy.get('[data-component-name="AnalyticalTableBody"]').should('have.prop', 'scrollTop', 3000);
43844384

4385+
cy.wait(100);
43854386
cy.get('[data-component-name="AnalyticalTableContainerWithScrollbar"]').realMouseWheel({ deltaY: 500 });
43864387
cy.get('[data-component-name="AnalyticalTableBody"]').should('have.prop', 'scrollTop', 3500);
43874388
cy.get('[data-component-name="AnalyticalTableVerticalScrollbar"]').should('have.prop', 'scrollTop', 3500);

packages/main/src/components/AnalyticalTable/AnalyticalTable.mdx

Lines changed: 35 additions & 35 deletions
Large diffs are not rendered by default.

packages/main/src/components/AnalyticalTable/AnalyticalTable.module.css

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@
155155
}
156156

157157
.tr {
158+
height: var(--_ui5wcr_AnalyticalTable_RowHeight);
158159
position: absolute;
159160
inset-block-start: 0;
160161
inset-inline-start: 0;
@@ -226,12 +227,12 @@
226227
display: block;
227228
}
228229

229-
.tableText {
230+
/* PUBLIC: When removed or changed, first check if custom inline Cell content is still truncated (Recipes) */
231+
.textEllipsis {
230232
display: inline-block;
231233
font-size: var(--sapFontSize);
232234
max-width: 100%;
233235
box-sizing: border-box;
234-
font-weight: normal;
235236
overflow: hidden;
236237
word-wrap: normal;
237238
white-space: nowrap;
@@ -266,6 +267,12 @@
266267
&[aria-selected='true']:not([data-empty-row-cell]):focus::after {
267268
inset-block-end: 2px;
268269
}
270+
271+
/* Make ellipsis work for text-only content */
272+
&:not(:has(*)) {
273+
display: block;
274+
line-height: var(--_ui5wcr_AnalyticalTable_RowHeight);
275+
}
269276
}
270277

271278
.showVerticalEndBorder .tableCell {

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,3 +663,42 @@ export const KitchenSink: Story = {
663663
return context.viewMode === 'story' ? <AnalyticalTable {...args} /> : <ToggleableTable {...args} />;
664664
},
665665
};
666+
667+
// ===================== Not displayed in sidebar & tags popover =====================
668+
669+
export const EllipsisExamples: Story = {
670+
tags: ['excludeFromSidebar'],
671+
args: {
672+
data: dataLarge.slice(0, 5),
673+
columns: [
674+
{
675+
Header: 'Plain String (Automatic Ellipsis)',
676+
accessor: 'name',
677+
width: 60,
678+
Cell: ({ value }) => value,
679+
},
680+
{
681+
Header: 'With textEllipsis Class',
682+
accessor: 'friend.name',
683+
width: 60,
684+
Cell: ({ value, webComponentsReactProperties }) => (
685+
<div className={webComponentsReactProperties.classes.textEllipsis} title={value}>
686+
{value}
687+
</div>
688+
),
689+
},
690+
{
691+
Header: 'With Text Component',
692+
id: 'description',
693+
width: 60,
694+
Cell: () => (
695+
<Text maxLines={1} title="This is a very long text that demonstrates how the Text component handles ellipsis">
696+
This is a very long text that demonstrates how the Text component handles ellipsis
697+
</Text>
698+
),
699+
},
700+
],
701+
visibleRows: 5,
702+
style: { width: 'min(100%, 300px)' },
703+
},
704+
};

packages/main/src/components/AnalyticalTable/Recipes.mdx

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { TableOfContent } from '@sb/components';
2-
import { Meta } from '@storybook/addon-docs/blocks';
2+
import { Meta, Canvas } from '@storybook/addon-docs/blocks';
33
import { Footer } from '@sb/components';
4-
import { MessageStrip } from '../../webComponents/index';
4+
import { MessageStrip } from '../../webComponents/MessageStrip/index';
5+
import * as ComponentStories from './AnalyticalTable.stories';
56

67
<Meta title="Data Display / AnalyticalTable / Recipes" />
78

@@ -367,4 +368,81 @@ To initially select or expand a row; reorder, filter, group, hide or sort a colu
367368
/>
368369
```
369370

371+
## How to show ellipsis for custom Cells?
372+
373+
**Applicable since v2.16.1**
374+
375+
When using custom `Cell` renderers, text truncation with ellipsis works automatically if you return a plain string. However, when rendering custom content, you need to handle ellipsis styling yourself.
376+
377+
### Automatic Ellipsis (Plain Strings)
378+
379+
If your custom `Cell` renderer returns a plain string, ellipsis is ensured automatically:
380+
381+
```jsx
382+
const columns = [
383+
{
384+
Header: 'Name',
385+
accessor: 'name',
386+
Cell: ({ value }) => value // Plain string - ellipsis works automatically
387+
},
388+
];
389+
```
390+
391+
### Manual Ellipsis (Custom Elements)
392+
393+
When rendering custom elements, you need to apply ellipsis styling:
394+
395+
#### Inline Content
396+
397+
Use the `webComponentsReactProperties.classes.textEllipsis` class for inline content that should truncate with ellipsis:
398+
399+
```jsx
400+
const columns = [
401+
{
402+
Header: 'Name',
403+
accessor: 'name',
404+
Cell: ({ value, webComponentsReactProperties }) => (
405+
<span
406+
className={webComponentsReactProperties.classes.textEllipsis}
407+
title={value} // Show full text on hover
408+
>
409+
{value}
410+
</span>
411+
),
412+
},
413+
];
414+
```
415+
416+
#### For Web Components with Built-in Text Handling
417+
418+
Some Web Components like `Text` and `Label` handle text truncation internally and don't require the `textEllipsis` class:
419+
420+
```jsx
421+
import { Text } from '@ui5/webcomponents-react';
422+
423+
const columns = [
424+
{
425+
Header: 'Description',
426+
accessor: 'description',
427+
Cell: ({ value }) => (
428+
<Text maxLines={1}>{value}</Text> // Text component handles ellipsis internally
429+
),
430+
},
431+
];
432+
```
433+
434+
#### For Other Custom Components
435+
436+
For multi-line content or custom components that don't handle ellipsis, truncation must be ensured by defining the styles yourself.
437+
438+
### Example
439+
440+
<details>
441+
<summary>Show Example</summary>
442+
<Canvas of={ComponentStories.EllipsisExamples} />
443+
</details>
444+
445+
<br />
446+
<br />
447+
370448
<Footer />

packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBody.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ export const VirtualTableBody = (props: VirtualTableBodyProps) => {
199199
transform: `translateY(${virtualRow.start}px)`,
200200
position: 'absolute',
201201
boxSizing: 'border-box',
202-
height: `${updatedHeight}px`,
202+
'--_ui5wcr_AnalyticalTable_RowHeight': `${updatedHeight}px`,
203203
}}
204204
>
205205
{typeof renderRowSubComponent === 'function' && (

packages/main/src/components/AnalyticalTable/defaults/Column/Cell.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const Cell = (props: CellInstance) => {
1616
<span
1717
id={`${webComponentsReactProperties.uniqueId}${column.id}${row.id}`}
1818
title={cellContent}
19-
className={webComponentsReactProperties.classes.tableText}
19+
className={webComponentsReactProperties.classes.textEllipsis}
2020
data-column-id-cell-text={column.id}
2121
// VoiceOver announces blank because of `aria-hidden` although `aria-labelledby` is set on the `gridcell` element - this is a known bug and there's no workaround
2222
aria-hidden="true"

packages/main/src/components/AnalyticalTable/types/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,10 +455,11 @@ export interface AnalyticalTableColumnDefinition {
455455
headerTooltip?: string;
456456
/**
457457
* Custom cell renderer. If set, the table will use this component or render the provided string for every cell,
458-
* passing all necessary information as props, e.g., the cell value as `props.cell.value`.
458+
* passing all necessary information as props, e.g., the cell value as `props.value`.
459459
*
460-
* __Note:__ Using a custom component __can impact performance__!
461-
* If you pass a component, __memoizing it is strongly recommended__, especially for complex components or large datasets.
460+
* __Note:__
461+
* - Using a custom component __can impact performance__! If you pass a component, __memoizing it is strongly recommended__, especially for complex components or large datasets.
462+
* - For custom elements, text truncation needs to be applied manually. [Here](https://ui5.github.io/webcomponents-react/v2/?path=/docs/data-display-analyticaltable-recipes--docs) you can find out more.
462463
*/
463464
Cell?: string | ComponentType<CellInstance>;
464465
/**

0 commit comments

Comments
 (0)