Skip to content

Commit 866d518

Browse files
authored
fix(AnalyticalTable): use global UI5 scrollbar styles (#7826)
1 parent 67cdcdd commit 866d518

File tree

5 files changed

+49
-128
lines changed

5 files changed

+49
-128
lines changed

docs/knowledge-base/Styling.mdx

Lines changed: 13 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,63 +11,31 @@ import { MyCustomElement } from '../styling/MyCustomElement';
1111

1212
<TableOfContent />
1313

14-
## Styling UI5 Web Components for React components
15-
16-
You can change the appearance of the Web Components by using [CSS Variables](https://www.w3schools.com/Css/css3_variables.asp).
17-
Per default, we are injecting the Horizon theme parameters as CSS Variables into the `<head>`.
18-
For example, if you want to change the color of all texts that use the `--sapTextColor` variable, you can create an additional `style` tag with the following content:
19-
20-
```html
21-
<style>
22-
* {
23-
--sapTextColor: limegreen;
24-
}
25-
</style>
26-
```
27-
28-
<MessageStrip
29-
hideCloseButton
30-
design={MessageStripDesign.Critical}
31-
children="Changing the value of a CSS Variable will affect theming capabilities, as it will be changed for all themes!"
32-
/>
33-
34-
As a consequence, all HTML Elements in the subtree where this style was applied are now displaying their texts in `limegreen` instead of `#32363a` which would be the default value for Fiori 3.
35-
You can change CSS Variables on any level - in the head, or on every single element by using either CSS classes or element style.
14+
## Styling UI5 Web Components (for React) components
3615

37-
A full list of all supported CSS Variables can be found [here](https://github.com/UI5/webcomponents-react/blob/main/packages/base/src/styling/ThemingParameters.ts)
38-
or in the [theming-base-content](https://github.com/SAP/theming-base-content/tree/master/content/Base/baseLib) repo.
39-
40-
## Scrollbars
16+
UI5 Web Components for React follows the same styling approach as the core [UI5 Web Components](https://ui5.github.io/webcomponents/docs/advanced/styles/).
17+
You can apply CSS variables, use the `::part` pseudo-element selectors, or apply styles directly on selected components (e.g. `Button`, `Title`, `Input`, etc. ) as described in the linked [documentation](https://ui5.github.io/webcomponents/docs/advanced/styles/).
4118

42-
Rendering our `ThemeProvider` will apply the Fiori styles to all scrollbars on the page.
43-
If you want to opt-out of this behavior, you can add the `.ui5-content-native-scrollbars` class to the respective element to prevent the scrollbar styling from being applied.
19+
Components currently only available in the `ui5/webcomponents-react` repo, are not necessarily web components. For these kind of components you can follow the standard styling approach of React.
4420

4521
<MessageStrip
46-
design={MessageStripDesign.Information}
47-
hideCloseButton
48-
children="Due to the limited configuration options for scrollbars, you must apply this class to each scroll-container element individually."
22+
design={MessageStripDesign.Critical}
23+
hideCloseButton
24+
children="While it's easily possible targeting DOM elements and CSS classes of components without a shadow root, modifying internal structures or styles is not officially supported and may break with future updates. Use such changes carefully."
4925
/>
5026

51-
```tsx
52-
<ObjectPage className="ui5-content-native-scrollbars">{children}</ObjectPage>
53-
```
27+
## Scrollbars
28+
29+
`@ui5/webcomponents` components come with globally applied scrollbar styles.
30+
If you want to opt-out of this behavior, you can add the `.ui5-content-native-scrollbars` class to the `body` of the page. You can find out more about this in the [ui5/webcomponents documentation](https://ui5.github.io/webcomponents/docs/advanced/scrollbars-customization/).
5431

5532
## Style your own components
5633

5734
It's quite likely you have to create some custom components when you are building an app.
5835
In order to reuse our central styling approach, you can import the `ThemingParameters` that contain the various CSS variables used in our theming, or use the CSS variables directly.
5936

60-
<MessageStrip
61-
design={MessageStripDesign.Information}
62-
hideCloseButton
63-
children={
64-
<>
65-
You can find all <code>ThemingParameters</code>{' '}
66-
<ui5-link href="./?path=/docs/knowledge-base-public-utils--docs#theming-parameters">here</ui5-link>. If you don't
67-
want to use CSS-in-JS library, you can also just use the corresponding CSS variable.
68-
</>
69-
}
70-
/>
37+
A full list of all supported CSS Variables can be found [here](https://github.com/UI5/webcomponents-react/blob/main/packages/base/src/styling/ThemingParameters.ts)
38+
or in the [theming-base-content](https://github.com/SAP/theming-base-content/tree/master/content/Base/baseLib) repo.
7139

7240
You can then create a custom component by following this recipe:
7341

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

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -381,11 +381,22 @@ describe('AnalyticalTable', () => {
381381
function doubleClickResizer(selector: string, columnName: string, outerWidth: number) {
382382
cy.get(selector)
383383
.realHover()
384-
.should('have.css', 'background-color', cssVarToRgb('--sapContent_DragAndDropActiveColor'))
384+
.should(($el) => {
385+
// the CSS variable is applied too late in React 18.
386+
if (!reactVersion.startsWith('18')) {
387+
const color = getComputedStyle($el[0]).getPropertyValue('background-color');
388+
expect(color).to.equal(cssVarToRgb('--sapContent_DragAndDropActiveColor'));
389+
}
390+
})
385391
.dblclick()
386392
// fallback
387393
.realClick({ clickCount: 2 });
388-
cy.get(`[data-column-id="${columnName}"]`).invoke('outerWidth').should('equal', outerWidth);
394+
395+
cy.get(`[data-column-id="${columnName}"]`)
396+
.invoke('outerWidth')
397+
.should(($width: number) => {
398+
expect(Math.floor($width)).to.equal(outerWidth);
399+
});
389400
}
390401

391402
let resizeColumns = columns.map((el) => {
@@ -413,6 +424,8 @@ describe('AnalyticalTable', () => {
413424
cy.get('[data-component-name="AnalyticalTableResizer"]').eq(0).as('resizer1');
414425
cy.get('[data-component-name="AnalyticalTableResizer"]').eq(1).as('resizer2');
415426

427+
cy.document().its('fonts.status').should('equal', 'loaded');
428+
416429
doubleClickResizer('@resizer2', 'age', 476);
417430
doubleClickResizer('@resizer1', 'name', 476);
418431
// doubled call count because of fallback
@@ -444,6 +457,7 @@ describe('AnalyticalTable', () => {
444457
);
445458

446459
cy.get('[data-component-name="AnalyticalTableBody"]').scrollTo('bottom');
460+
cy.wait(50);
447461
doubleClickResizer('@resizer1', 'name', 93);
448462
cy.get('@resize').should('have.callCount', 10);
449463

@@ -453,8 +467,8 @@ describe('AnalyticalTable', () => {
453467

454468
cy.mount(<AnalyticalTable data={dataFixed} columns={resizeColumns} />);
455469
cy.wait(100);
456-
doubleClickResizer('@resizer2', 'age', 472.75);
457-
doubleClickResizer('@resizer1', 'name', 472.75);
470+
doubleClickResizer('@resizer2', 'age', 472);
471+
doubleClickResizer('@resizer1', 'name', 472);
458472

459473
cy.get('@resize').should('have.callCount', 10);
460474

@@ -3371,7 +3385,7 @@ describe('AnalyticalTable', () => {
33713385
useEffect(() => {
33723386
tableRef.current.scrollTo(520);
33733387
}, []);
3374-
return <AnalyticalTable data={generateMoreData(500)} columns={columns} ref={tableRef} />;
3388+
return <AnalyticalTable data={generateMoreData(300)} columns={columns} ref={tableRef} />;
33753389
};
33763390
cy.mount(<ScrollTo />);
33773391
cy.findByText('Name-12').should('be.visible');
@@ -3382,7 +3396,7 @@ describe('AnalyticalTable', () => {
33823396
useEffect(() => {
33833397
tableRef.current.scrollToItem(12, { align: 'start' });
33843398
}, []);
3385-
return <AnalyticalTable data={generateMoreData(500)} columns={columns} ref={tableRef} />;
3399+
return <AnalyticalTable data={generateMoreData(300)} columns={columns} ref={tableRef} />;
33863400
};
33873401
cy.mount(<ScrollToItem />);
33883402
cy.findByText('Name-12').should('be.visible');
@@ -3395,7 +3409,7 @@ describe('AnalyticalTable', () => {
33953409
}, []);
33963410
return (
33973411
<AnalyticalTable
3398-
data={generateMoreData(500)}
3412+
data={generateMoreData(300)}
33993413
columns={[
34003414
...columns,
34013415
...new Array(100).fill('').map((_, index) => ({ id: `${index}`, Header: () => index })),
@@ -3414,7 +3428,7 @@ describe('AnalyticalTable', () => {
34143428
}, []);
34153429
return (
34163430
<AnalyticalTable
3417-
data={generateMoreData(500)}
3431+
data={generateMoreData(300)}
34183432
columns={new Array(100).fill('').map((_, index) => ({ id: `${index}`, Header: () => index }))}
34193433
ref={tableRef}
34203434
/>
@@ -3870,12 +3884,12 @@ describe('AnalyticalTable', () => {
38703884
cy.get('[data-component-name="AnalyticalTableContainer"]').should(
38713885
'have.css',
38723886
'width',
3873-
withVertScrollbar ? '1293px' : '1306px',
3887+
withVertScrollbar ? '1290px' : '1306px',
38743888
);
38753889
cy.get('[data-component-name="AnalyticalTableBody"]').should(
38763890
'have.css',
38773891
'width',
3878-
withVertScrollbar ? '1293px' : '1306px',
3892+
withVertScrollbar ? '1290px' : '1306px',
38793893
);
38803894

38813895
const _data2 = [
@@ -3942,32 +3956,31 @@ describe('AnalyticalTable', () => {
39423956
cy.get('[data-component-name="AnalyticalTableContainer"]').should(
39433957
'have.css',
39443958
'width',
3945-
withVertScrollbar ? '1293px' : '1306px',
3946-
);
3947-
cy.get('[data-component-name="AnalyticalTableBody"]').should(
3948-
'have.css',
3949-
'width',
3950-
withVertScrollbar ? '1293px' : '1306px',
3959+
withVertScrollbar ? '1290px' : '1306px',
39513960
);
3961+
cy.get('[data-component-name="AnalyticalTableBody"]').should(($el) => {
3962+
const width = Math.round(parseFloat($el.css('width')));
3963+
expect(width).to.equal(withVertScrollbar ? 1290 : 1306);
3964+
});
39523965

39533966
cy.mount(<AnalyticalTable data={data} columns={columns} visibleRows={visibleRows} />);
39543967
cy.get('[data-component-name="AnalyticalTableContainer"]').should(
39553968
'have.css',
39563969
'width',
3957-
withVertScrollbar ? '1293px' : '1306px',
3970+
withVertScrollbar ? '1290px' : '1306px',
39583971
);
39593972
cy.get('[data-component-name="AnalyticalTableBody"]').should(
39603973
'have.css',
39613974
'width',
3962-
withVertScrollbar ? '1293px' : '1306px',
3975+
withVertScrollbar ? '1290px' : '1306px',
39633976
);
39643977

39653978
const _columns3 = [...columns, { id: 'long', Header: 'Long', width: 2000, Cell: 'Long' }];
39663979
cy.mount(<AnalyticalTable data={data} columns={_columns3} visibleRows={visibleRows} />);
39673980
cy.get('[data-component-name="AnalyticalTableContainer"]').should(
39683981
'have.css',
39693982
'width',
3970-
withVertScrollbar ? '1293px' : '1306px',
3983+
withVertScrollbar ? '1290px' : '1306px',
39713984
);
39723985
cy.get('[data-component-name="AnalyticalTableBody"]').should('have.css', 'width', '2240px'); // 4 * 60 (minWidth) + 2000
39733986

@@ -3980,7 +3993,7 @@ describe('AnalyticalTable', () => {
39803993
cy.get('[data-component-name="AnalyticalTableContainer"]').should(
39813994
'have.css',
39823995
'width',
3983-
withVertScrollbar ? '1293px' : '1306px',
3996+
withVertScrollbar ? '1290px' : '1306px',
39843997
);
39853998
cy.get('[data-component-name="AnalyticalTableBody"]').should('have.css', 'width', '1440px'); // 4 * 60 (minWidth) + 1000 (maxWidth) + 200
39863999
});

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

Lines changed: 1 addition & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -148,13 +148,6 @@
148148
overflow-y: auto;
149149
scrollbar-width: none;
150150
box-sizing: border-box;
151-
-ms-overflow-style: none;
152-
153-
&::-webkit-scrollbar {
154-
width: 0 !important;
155-
height: 0 !important;
156-
display: none !important;
157-
}
158151
}
159152

160153
.alternateRowColor {
@@ -600,56 +593,14 @@
600593
background-color: var(--sapList_HeaderBackground);
601594
border-inline-start: 1px solid var(--sapList_BorderColor);
602595
margin-inline-start: -1px;
603-
width: calc(var(--sapScrollBar_Dimension) + 2px);
604596
}
605597
.scrollbar {
598+
box-sizing: border-box;
606599
overflow-y: auto;
607600
border-inline-end: var(--_ui5wcr-AnalyticalTable-OuterBorderInline);
608601
border-block-end: 1px solid var(--sapList_TableFooterBorder);
609602
border-inline-start: 1px solid var(--sapList_BorderColor);
610603
margin-inline-start: -1px;
611-
box-sizing: border-box;
612-
}
613-
614-
.scrollbar:global(.ui5-content-native-scrollbars) {
615-
background-color: var(--sapList_Background);
616-
width: calc(var(--sapScrollBar_Dimension) + 2px);
617-
}
618-
619-
.analyticalTableDelta:global(.ui5-content-native-scrollbars) {
620-
&::-webkit-scrollbar {
621-
background-color: var(--sapScrollBar_TrackColor);
622-
-webkit-border-start: var(--_ui5wcr_Scrollbar_Border);
623-
}
624-
625-
&::-webkit-scrollbar-thumb {
626-
border-radius: var(--_ui5wcr_Scrollbar_BorderRadius);
627-
background-color: var(--sapScrollBar_FaceColor);
628-
629-
&:hover {
630-
background-color: var(--sapScrollBar_FaceColor);
631-
}
632-
633-
&:horizontal {
634-
height: var(--sapScrollBar_Dimension);
635-
}
636-
637-
&:vertical {
638-
width: var(--sapScrollBar_Dimension);
639-
}
640-
}
641-
642-
&::-webkit-scrollbar-corner {
643-
background-color: var(--sapScrollBar_TrackColor);
644-
}
645-
646-
&::-webkit-scrollbar:horizontal {
647-
height: var(--sapScrollBar_Dimension);
648-
}
649-
650-
&::-webkit-scrollbar:vertical {
651-
width: var(--sapScrollBar_Dimension);
652-
}
653604
}
654605

655606
.verticalScroller {

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,6 @@ const AnalyticalTable = forwardRef<AnalyticalTableDomRef, AnalyticalTablePropTyp
190190
useStylesheet(styleData, AnalyticalTable.displayName);
191191
const isInitialized = useRef(false);
192192

193-
const nativeScrollbar = className?.includes('ui5-content-native-scrollbars');
194193
const alwaysShowSubComponent =
195194
subComponentsBehavior === AnalyticalTableSubComponentsBehavior.Visible ||
196195
subComponentsBehavior === AnalyticalTableSubComponentsBehavior.IncludeHeight;
@@ -676,9 +675,6 @@ const AnalyticalTable = forwardRef<AnalyticalTableDomRef, AnalyticalTablePropTyp
676675
classNames.table,
677676
withNavigationHighlight && classNames.hasNavigationIndicator,
678677
showVerticalEndBorder && classNames.showVerticalEndBorder,
679-
nativeScrollbar
680-
? 'ui5-content-native-scrollbars'
681-
: `ui5-content-native-scrollbars ${classNames.analyticalTableDelta}`,
682678
);
683679

684680
const handleOnLoadMore = (e) => {
@@ -881,7 +877,6 @@ const AnalyticalTable = forwardRef<AnalyticalTableDomRef, AnalyticalTablePropTyp
881877
tableRef={tableRef}
882878
ref={verticalScrollBarRef}
883879
scrollContainerRef={scrollContainerRef}
884-
nativeScrollbar={nativeScrollbar}
885880
classNames={classNames}
886881
/>
887882
)}

packages/main/src/components/AnalyticalTable/scrollbars/VerticalScrollbar.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,11 @@ interface VerticalScrollbarProps {
1010
tableRef: MutableRefObject<HTMLDivElement>;
1111
tableBodyHeight: number;
1212
scrollContainerRef: MutableRefObject<HTMLDivElement>;
13-
nativeScrollbar: boolean;
1413
classNames: ClassNames;
1514
}
1615

1716
export const VerticalScrollbar = forwardRef<HTMLDivElement, VerticalScrollbarProps>((props, ref) => {
18-
const { internalRowHeight, tableRef, tableBodyHeight, scrollContainerRef, nativeScrollbar, classNames } = props;
17+
const { internalRowHeight, tableRef, tableBodyHeight, scrollContainerRef, classNames } = props;
1918
const hasHorizontalScrollbar = tableRef?.current?.offsetWidth !== tableRef?.current?.scrollWidth;
2019
const horizontalScrollbarSectionStyles = clsx(hasHorizontalScrollbar && classNames.bottomSection);
2120

@@ -36,12 +35,7 @@ export const VerticalScrollbar = forwardRef<HTMLDivElement, VerticalScrollbarPro
3635
style={{
3736
height: tableRef.current ? `${tableBodyHeight}px` : '0',
3837
}}
39-
className={clsx(
40-
classNames.scrollbar,
41-
nativeScrollbar
42-
? 'ui5-content-native-scrollbars'
43-
: `ui5-content-native-scrollbars ${classNames.analyticalTableDelta}`,
44-
)}
38+
className={clsx(classNames.scrollbar)}
4539
data-component-name="AnalyticalTableVerticalScrollbar"
4640
tabIndex={-1}
4741
>

0 commit comments

Comments
 (0)