diff --git a/packages/main/src/components/AnalyticalTable/AnalyticalTable.mdx b/packages/main/src/components/AnalyticalTable/AnalyticalTable.mdx index 5b385694ec8..266cd658598 100644 --- a/packages/main/src/components/AnalyticalTable/AnalyticalTable.mdx +++ b/packages/main/src/components/AnalyticalTable/AnalyticalTable.mdx @@ -499,7 +499,7 @@ Here you can find an example using a `MultiComboBox` with multiple values as fil
-Show Code +Show static code ```jsx const filterFn = (rows, accessor, filterValue) => { @@ -562,6 +562,10 @@ const TableComponent = () => {
+## Table Without Data + + + ## Kitchen Sink diff --git a/packages/main/src/components/AnalyticalTable/AnalyticalTable.module.css b/packages/main/src/components/AnalyticalTable/AnalyticalTable.module.css index 15a4f913de4..d6e7cd76999 100644 --- a/packages/main/src/components/AnalyticalTable/AnalyticalTable.module.css +++ b/packages/main/src/components/AnalyticalTable/AnalyticalTable.module.css @@ -243,6 +243,14 @@ } .noDataContainer { + box-sizing: border-box; + &:focus { + outline-offset: -3px; + outline: var(--sapContent_FocusColor) solid 0.125rem; + } +} + +.noData { display: flex; justify-content: center; align-items: center; diff --git a/packages/main/src/components/AnalyticalTable/AnalyticalTable.stories.tsx b/packages/main/src/components/AnalyticalTable/AnalyticalTable.stories.tsx index e3a5c712099..2a28fa10838 100644 --- a/packages/main/src/components/AnalyticalTable/AnalyticalTable.stories.tsx +++ b/packages/main/src/components/AnalyticalTable/AnalyticalTable.stories.tsx @@ -4,6 +4,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import '@ui5/webcomponents-icons/dist/delete.js'; import '@ui5/webcomponents-icons/dist/edit.js'; import '@ui5/webcomponents-icons/dist/settings.js'; +import NoDataIllustration from '@ui5/webcomponents-fiori/dist/illustrations/NoData.js'; import { useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react'; import { AnalyticalTablePopinDisplay, @@ -17,10 +18,14 @@ import { TextAlign } from '../../enums/index.js'; import { Button } from '../../webComponents/Button/index.js'; +import { IllustratedMessage } from '../../webComponents/IllustratedMessage/index.js'; import { Label } from '../../webComponents/Label/index.js'; import { MultiComboBox } from '../../webComponents/MultiComboBox/index.js'; import { MultiComboBoxItem } from '../../webComponents/MultiComboBoxItem/index.js'; import { Option } from '../../webComponents/Option/index.js'; +import type { SegmentedButtonPropTypes } from '../../webComponents/SegmentedButton/index.js'; +import { SegmentedButton } from '../../webComponents/SegmentedButton/index.js'; +import { SegmentedButtonItem } from '../../webComponents/SegmentedButtonItem/index.js'; import { Select } from '../../webComponents/Select/index.js'; import { Tag } from '../../webComponents/Tag/index.js'; import { Text } from '../../webComponents/Text/index.js'; @@ -572,6 +577,49 @@ export const CustomFilter: Story = { } }; +export const NoData: Story = { + args: { visibleRows: 5 }, + render(args, context) { + const [selected, setSelected] = useState('noData'); + const handleChange: SegmentedButtonPropTypes['onSelectionChange'] = (e) => { + setSelected(e.detail.selectedItems[0].dataset.key); + }; + + return ( + <> + + + Default NoData Component + + + IllustratedMessage NoData Component + + + With Data + + + {context.viewMode === 'story' ? ( + + } + /> + ) : ( + + } + /> + )} + + ); + } +}; + export const KitchenSink: Story = { args: kitchenSinkArgs, render(args, context) { diff --git a/packages/main/src/components/AnalyticalTable/defaults/LoadingComponent/TablePlaceholder.module.css b/packages/main/src/components/AnalyticalTable/defaults/LoadingComponent/TablePlaceholder.module.css index c64762b8274..b505fc97823 100644 --- a/packages/main/src/components/AnalyticalTable/defaults/LoadingComponent/TablePlaceholder.module.css +++ b/packages/main/src/components/AnalyticalTable/defaults/LoadingComponent/TablePlaceholder.module.css @@ -7,6 +7,10 @@ } } +.container { + background: var(--sapList_Background); +} + .animation { animation-duration: 2s; animation-fill-mode: forwards; diff --git a/packages/main/src/components/AnalyticalTable/defaults/LoadingComponent/TablePlaceholder.tsx b/packages/main/src/components/AnalyticalTable/defaults/LoadingComponent/TablePlaceholder.tsx index 6719d1ca921..93f338ff90a 100644 --- a/packages/main/src/components/AnalyticalTable/defaults/LoadingComponent/TablePlaceholder.tsx +++ b/packages/main/src/components/AnalyticalTable/defaults/LoadingComponent/TablePlaceholder.tsx @@ -1,48 +1,52 @@ -import { ThemingParameters, useStylesheet } from '@ui5/webcomponents-react-base'; +import { useStylesheet } from '@ui5/webcomponents-react-base'; import { clsx } from 'clsx'; import type { CSSProperties, FC } from 'react'; +import type { ColumnType } from '../../types/index.js'; import { resolveCellAlignment } from '../../util/index.js'; -import { classNames, styleData } from './TablePlaceholder.module.css.js'; +import { classNames, content } from './TablePlaceholder.module.css.js'; -const getArrayOfLength = (len) => Array.from(Array(len).keys()); +const getArrayOfLength = (len: number) => Array.from(Array(len).keys()); interface TablePlaceholderPropTypes { - columns: any[]; - rows: number; style: CSSProperties; + columns: ColumnType[]; + rows: number; + pleaseWaitText: string; } export const TablePlaceholder: FC = (props) => { - const { columns, rows = 5, style } = props; + const { columns, rows = 5, style, pleaseWaitText } = props; - useStylesheet(styleData, TablePlaceholder.displayName); + useStylesheet(content, TablePlaceholder.displayName); return ( -
- {getArrayOfLength(rows).map((_, index) => { - return ( -
- {columns.map((col) => { - return ( -
-
-
- ); - })} -
- ); - })} +
+
+ {getArrayOfLength(rows).map((_, index) => { + return ( +
+ {columns.map((col) => { + return ( +
+
+
+ ); + })} +
+ ); + })} +
); }; diff --git a/packages/main/src/components/AnalyticalTable/defaults/NoDataComponent/index.tsx b/packages/main/src/components/AnalyticalTable/defaults/NoDataComponent/index.tsx index d50dfcf4fdc..bb481409313 100644 --- a/packages/main/src/components/AnalyticalTable/defaults/NoDataComponent/index.tsx +++ b/packages/main/src/components/AnalyticalTable/defaults/NoDataComponent/index.tsx @@ -1,6 +1,11 @@ -export const DefaultNoDataComponent = ({ noDataText, className, style }) => { +interface NoDataComponentProps { + noDataText: string; + className: string; +} + +export const DefaultNoDataComponent = ({ noDataText, className }: NoDataComponentProps) => { return ( -
+
{noDataText}
); diff --git a/packages/main/src/components/AnalyticalTable/hooks/useKeyboardNavigation.ts b/packages/main/src/components/AnalyticalTable/hooks/useKeyboardNavigation.ts index 995af9ef182..30c5f8868d1 100644 --- a/packages/main/src/components/AnalyticalTable/hooks/useKeyboardNavigation.ts +++ b/packages/main/src/components/AnalyticalTable/hooks/useKeyboardNavigation.ts @@ -106,7 +106,8 @@ const useGetTableProps = ( Object.prototype.hasOwnProperty.call(dataset, 'subcomponentActiveElement') || // todo: with the new popover API of ui5wc this might not be necessary anymore dataset.componentName === 'ATHeaderPopoverList' || - dataset.componentName === 'ATHeaderPopover' + dataset.componentName === 'ATHeaderPopover' || + dataset.componentName === 'AnalyticalTableNoDataContainer' ) { return; } diff --git a/packages/main/src/components/AnalyticalTable/index.tsx b/packages/main/src/components/AnalyticalTable/index.tsx index 5fc7323ca4b..56ab950921b 100644 --- a/packages/main/src/components/AnalyticalTable/index.tsx +++ b/packages/main/src/components/AnalyticalTable/index.tsx @@ -43,6 +43,7 @@ import { INVALID_TABLE, LIST_NO_DATA, NO_DATA_FILTERED, + PLEASE_WAIT, ROW_COLLAPSED, ROW_EXPANDED, SELECT_ALL, @@ -797,15 +798,25 @@ const AnalyticalTable = forwardRef - )} - {!loading && rows?.length === 0 && ( - + data-component-name="AnalyticalTableNoDataContainer" + role="row" + tabIndex={0} + className={classNames.noDataContainer} + > + {loading ? ( + + ) : ( + + )} +
)} {rows?.length > 0 && tableRef.current && (