From 27575e4568b972eeb018f89fe2f7585eabc3e101 Mon Sep 17 00:00:00 2001 From: Lukas Harbarth <lukas.harbarth@sap.com> Date: Thu, 22 Aug 2024 09:20:44 +0200 Subject: [PATCH 1/2] fix(AnalyticalTable): ensure loading indicator displays correctly across all browsers --- .../AnalyticalTable.module.css | 14 +- .../src/components/AnalyticalTable/index.tsx | 279 +++++++++--------- 2 files changed, 146 insertions(+), 147 deletions(-) diff --git a/packages/main/src/components/AnalyticalTable/AnalyticalTable.module.css b/packages/main/src/components/AnalyticalTable/AnalyticalTable.module.css index 12e2251bd58..7f48b1ff244 100644 --- a/packages/main/src/components/AnalyticalTable/AnalyticalTable.module.css +++ b/packages/main/src/components/AnalyticalTable/AnalyticalTable.module.css @@ -41,13 +41,17 @@ position: relative; } +.busyIndicator { + position: absolute; + z-index: 1; + inset: 0; + height: 100%; +} + .overlay { position: absolute; z-index: 1; - top: 0; - bottom: 0; - left: 0; - right: 0; + inset: 0; background: var(--sapGroup_ContentBackground); opacity: 0.8; @@ -158,7 +162,7 @@ color: var(--sapList_TextColor); border-block-end: 1px solid var(--sapList_BorderColor); /* needed for vertical virtualization*/ - margin-bottom: -1px; + margin-block-end: -1px; box-sizing: border-box; display: flex; diff --git a/packages/main/src/components/AnalyticalTable/index.tsx b/packages/main/src/components/AnalyticalTable/index.tsx index bddd5056894..4d7e9fbd101 100644 --- a/packages/main/src/components/AnalyticalTable/index.tsx +++ b/packages/main/src/components/AnalyticalTable/index.tsx @@ -46,7 +46,6 @@ import { SELECT_PRESS_SPACE, UNSELECT_PRESS_SPACE } from '../../i18n/i18n-defaults.js'; -import { addCustomCSSWithScoping } from '../../internal/addCustomCSSWithScoping.js'; import { BusyIndicator } from '../../webComponents/BusyIndicator/index.js'; import { Text } from '../../webComponents/Text/index.js'; import { FlexBox } from '../FlexBox/index.js'; @@ -95,19 +94,6 @@ const measureElement = (el: HTMLElement) => { return el.offsetHeight; }; -//todo: add feature request for parts or even a fix if this turns out to be a bug -addCustomCSSWithScoping( - 'ui5-busy-indicator', - ` -:host([data-component-name="AnalyticalTableBusyIndicator"]) .ui5-busy-indicator-root { - display: initial; -} -:host([data-component-name="AnalyticalTableBusyIndicator"]) .ui5-busy-indicator-busy-area:focus { -border-radius: 0; -} -` -); - /** * The `AnalyticalTable` provides a set of convenient functions for responsive table design, including virtualization of rows and columns, infinite scrolling and customizable columns that will, unless otherwise defined, distribute the available space equally among themselves. * It also provides several possibilities for working with the data, including sorting, filtering, grouping and aggregation. @@ -717,143 +703,152 @@ const AnalyticalTable = forwardRef<AnalyticalTableDomRef, AnalyticalTablePropTyp </TitleBar> )} {extension && <div ref={extensionRef}>{extension}</div>} - <BusyIndicator active={loading} delay={loadingDelay} data-component-name="AnalyticalTableBusyIndicator"> - <FlexBox - className={classNames.tableContainerWithScrollBar} - data-component-name="AnalyticalTableContainerWithScrollbar" - > - {showOverlay && ( - <> - <span id={invalidTableTextId} className={classNames.hiddenA11yText} aria-hidden> - {invalidTableA11yText} - </span> - <div - tabIndex={0} - aria-labelledby={`${titleBarId} ${invalidTableTextId}`} - role="region" - data-component-name="AnalyticalTableOverlay" - className={classNames.overlay} - /> - </> - )} - <div - aria-labelledby={titleBarId} - {...getTableProps()} - tabIndex={showOverlay ? -1 : 0} - role="grid" - aria-rowcount={rows.length} - aria-colcount={visibleColumns.length} - data-per-page={internalVisibleRowCount} - data-component-name="AnalyticalTableContainer" - ref={tableRef} - className={tableClasses} + <FlexBox + className={classNames.tableContainerWithScrollBar} + data-component-name="AnalyticalTableContainerWithScrollbar" + > + {loading && ( + <BusyIndicator + className={classNames.busyIndicator} + active={true} + delay={loadingDelay} + data-component-name="AnalyticalTableBusyIndicator" > - <div className={classNames.tableHeaderBackgroundElement} /> - <div className={classNames.tableBodyBackgroundElement} /> - {headerGroups.map((headerGroup) => { - let headerProps: Record<string, unknown> = {}; - if (headerGroup.getHeaderGroupProps) { - headerProps = headerGroup.getHeaderGroupProps(); - } - return ( - tableRef.current && ( - <ColumnHeaderContainer - ref={headerRef} - key={headerProps.key as string} - resizeInfo={tableState.columnResizing} - headerProps={headerProps} - headerGroup={headerGroup} - onSort={onSort} - onGroupByChanged={onGroupByChanged} - isRtl={isRtl} - columnVirtualizer={columnVirtualizer} - uniqueId={uniqueId} - showVerticalEndBorder={showVerticalEndBorder} - /> - ) - ); - })} - {loading && rows?.length === 0 && ( - <TablePlaceholder columns={visibleColumns} rows={minRows} style={noDataStyles} /> - )} - {!loading && rows?.length === 0 && ( - <NoDataComponent - noDataText={noDataTextLocal} - className={classNames.noDataContainer} - style={noDataStyles} - /> - )} - {rows?.length > 0 && tableRef.current && ( - <VirtualTableBodyContainer - rowCollapsedFlag={tableState.rowCollapsed} - dispatch={dispatch} - tableBodyHeight={tableBodyHeight} - totalColumnsWidth={columnVirtualizer.getTotalSize()} - parentRef={parentRef} - classes={classNames} - infiniteScroll={infiniteScroll} - infiniteScrollThreshold={infiniteScrollThreshold} - onLoadMore={handleOnLoadMore} - internalRowHeight={internalRowHeight} - popInRowHeight={popInRowHeight} - rows={rows} - handleExternalScroll={handleBodyScroll} - visibleRows={internalVisibleRowCount} - > - <VirtualTableBody - scrollContainerRef={scrollContainerRef} - classes={classNames} - prepareRow={prepareRow} - rows={rows} - scrollToRef={scrollToRef} - isTreeTable={isTreeTable} - internalRowHeight={internalRowHeight} - popInRowHeight={popInRowHeight} - alternateRowColor={alternateRowColor} - visibleColumns={visibleColumns} - renderRowSubComponent={renderRowSubComponent} - alwaysShowSubComponent={alwaysShowSubComponent} - markNavigatedRow={markNavigatedRow} + {/*todo: This is necessary; otherwise, the focus behavior and overlay color will not be applied. */} + <span /> + </BusyIndicator> + )} + {showOverlay && ( + <> + <span id={invalidTableTextId} className={classNames.hiddenA11yText} aria-hidden> + {invalidTableA11yText} + </span> + <div + tabIndex={0} + aria-labelledby={`${titleBarId} ${invalidTableTextId}`} + role="region" + data-component-name="AnalyticalTableOverlay" + className={classNames.overlay} + /> + </> + )} + <div + aria-labelledby={titleBarId} + {...getTableProps()} + tabIndex={showOverlay ? -1 : 0} + role="grid" + aria-rowcount={rows.length} + aria-colcount={visibleColumns.length} + data-per-page={internalVisibleRowCount} + data-component-name="AnalyticalTableContainer" + ref={tableRef} + className={tableClasses} + > + <div className={classNames.tableHeaderBackgroundElement} /> + <div className={classNames.tableBodyBackgroundElement} /> + {headerGroups.map((headerGroup) => { + let headerProps: Record<string, unknown> = {}; + if (headerGroup.getHeaderGroupProps) { + headerProps = headerGroup.getHeaderGroupProps(); + } + return ( + tableRef.current && ( + <ColumnHeaderContainer + ref={headerRef} + key={headerProps.key as string} + resizeInfo={tableState.columnResizing} + headerProps={headerProps} + headerGroup={headerGroup} + onSort={onSort} + onGroupByChanged={onGroupByChanged} isRtl={isRtl} - subComponentsHeight={tableState.subComponentsHeight} - dispatch={dispatch} columnVirtualizer={columnVirtualizer} - manualGroupBy={reactTableOptions?.manualGroupBy as boolean | undefined} - subRowsKey={subRowsKey} - subComponentsBehavior={subComponentsBehavior} - triggerScroll={tableState.triggerScroll} - rowVirtualizer={rowVirtualizer} + uniqueId={uniqueId} + showVerticalEndBorder={showVerticalEndBorder} /> - </VirtualTableBodyContainer> - )} - </div> - {(additionalEmptyRowsCount || tableState.isScrollable === undefined || tableState.isScrollable) && ( - <VerticalScrollbar + ) + ); + })} + {loading && rows?.length === 0 && ( + <TablePlaceholder columns={visibleColumns} rows={minRows} style={noDataStyles} /> + )} + {!loading && rows?.length === 0 && ( + <NoDataComponent + noDataText={noDataTextLocal} + className={classNames.noDataContainer} + style={noDataStyles} + /> + )} + {rows?.length > 0 && tableRef.current && ( + <VirtualTableBodyContainer + rowCollapsedFlag={tableState.rowCollapsed} + dispatch={dispatch} tableBodyHeight={tableBodyHeight} - internalRowHeight={internalHeaderRowHeight} - tableRef={tableRef} - handleVerticalScrollBarScroll={handleVerticalScrollBarScroll} - ref={verticalScrollBarRef} - scrollContainerRef={scrollContainerRef} + totalColumnsWidth={columnVirtualizer.getTotalSize()} parentRef={parentRef} - nativeScrollbar={className?.includes('ui5-content-native-scrollbars')} - /> + classes={classNames} + infiniteScroll={infiniteScroll} + infiniteScrollThreshold={infiniteScrollThreshold} + onLoadMore={handleOnLoadMore} + internalRowHeight={internalRowHeight} + popInRowHeight={popInRowHeight} + rows={rows} + handleExternalScroll={handleBodyScroll} + visibleRows={internalVisibleRowCount} + > + <VirtualTableBody + scrollContainerRef={scrollContainerRef} + classes={classNames} + prepareRow={prepareRow} + rows={rows} + scrollToRef={scrollToRef} + isTreeTable={isTreeTable} + internalRowHeight={internalRowHeight} + popInRowHeight={popInRowHeight} + alternateRowColor={alternateRowColor} + visibleColumns={visibleColumns} + renderRowSubComponent={renderRowSubComponent} + alwaysShowSubComponent={alwaysShowSubComponent} + markNavigatedRow={markNavigatedRow} + isRtl={isRtl} + subComponentsHeight={tableState.subComponentsHeight} + dispatch={dispatch} + columnVirtualizer={columnVirtualizer} + manualGroupBy={reactTableOptions?.manualGroupBy as boolean | undefined} + subRowsKey={subRowsKey} + subComponentsBehavior={subComponentsBehavior} + triggerScroll={tableState.triggerScroll} + rowVirtualizer={rowVirtualizer} + /> + </VirtualTableBodyContainer> )} - </FlexBox> - {visibleRowCountMode === AnalyticalTableVisibleRowCountMode.Interactive && ( - <VerticalResizer - popInRowHeight={popInRowHeight} - hasPopInColumns={tableState?.popInColumns?.length > 0} - analyticalTableRef={analyticalTableRef} - dispatch={dispatch} - extensionsHeight={extensionsHeight} - internalRowHeight={internalRowHeight} - rowsLength={rows.length} - visibleRows={internalVisibleRowCount} - handleOnLoadMore={handleOnLoadMore} + </div> + {(additionalEmptyRowsCount || tableState.isScrollable === undefined || tableState.isScrollable) && ( + <VerticalScrollbar + tableBodyHeight={tableBodyHeight} + internalRowHeight={internalHeaderRowHeight} + tableRef={tableRef} + handleVerticalScrollBarScroll={handleVerticalScrollBarScroll} + ref={verticalScrollBarRef} + scrollContainerRef={scrollContainerRef} + parentRef={parentRef} + nativeScrollbar={className?.includes('ui5-content-native-scrollbars')} /> )} - </BusyIndicator> + </FlexBox> + {visibleRowCountMode === AnalyticalTableVisibleRowCountMode.Interactive && ( + <VerticalResizer + popInRowHeight={popInRowHeight} + hasPopInColumns={tableState?.popInColumns?.length > 0} + analyticalTableRef={analyticalTableRef} + dispatch={dispatch} + extensionsHeight={extensionsHeight} + internalRowHeight={internalRowHeight} + rowsLength={rows.length} + visibleRows={internalVisibleRowCount} + handleOnLoadMore={handleOnLoadMore} + /> + )} </div> <Text aria-hidden="true" From 5b6b60e1e0ec7f5381578a03dc532ae1e58bd826 Mon Sep 17 00:00:00 2001 From: Lukas Harbarth <lukas.harbarth@sap.com> Date: Thu, 22 Aug 2024 09:44:07 +0200 Subject: [PATCH 2/2] link feature request --- packages/main/src/components/AnalyticalTable/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/main/src/components/AnalyticalTable/index.tsx b/packages/main/src/components/AnalyticalTable/index.tsx index 4d7e9fbd101..21ca02d9af1 100644 --- a/packages/main/src/components/AnalyticalTable/index.tsx +++ b/packages/main/src/components/AnalyticalTable/index.tsx @@ -714,7 +714,7 @@ const AnalyticalTable = forwardRef<AnalyticalTableDomRef, AnalyticalTablePropTyp delay={loadingDelay} data-component-name="AnalyticalTableBusyIndicator" > - {/*todo: This is necessary; otherwise, the focus behavior and overlay color will not be applied. */} + {/*todo: This is necessary; otherwise, the overlay bg color will not be applied. https://github.com/SAP/ui5-webcomponents/issues/9723 */} <span /> </BusyIndicator> )}