diff --git a/.changeset/pretty-seals-flow.md b/.changeset/pretty-seals-flow.md new file mode 100644 index 000000000..b97930df2 --- /dev/null +++ b/.changeset/pretty-seals-flow.md @@ -0,0 +1,5 @@ +--- +"@easypost/easy-ui": minor +--- + +Supports DataGrid loading state diff --git a/documentation/specs/DataGrid.md b/documentation/specs/DataGrid.md index 2e5ebadab..162d6ec7c 100644 --- a/documentation/specs/DataGrid.md +++ b/documentation/specs/DataGrid.md @@ -117,6 +117,12 @@ type DataGridProps = AriaLabelingProps & { /** The current sorted column and direction. */ sortDescriptor?: SortDescriptor; + + /** + * Whether the table is currently loading. + * @default false + */ + isLoading?: boolean; }; type MenuRowAction = { diff --git a/easy-ui-react/src/DataGrid/DataGrid.mdx b/easy-ui-react/src/DataGrid/DataGrid.mdx index 2e2459a65..6bf98c461 100644 --- a/easy-ui-react/src/DataGrid/DataGrid.mdx +++ b/easy-ui-react/src/DataGrid/DataGrid.mdx @@ -83,6 +83,7 @@ const rows = [ columnKeysAllowingSort={["name"]} // "sm", "md" (default), or "lg" size="lg" + isLoading={false} />; ``` @@ -247,6 +248,14 @@ In the example below, to make the status text green or red depending on whether +## Loading State + +`DataGrid` supports rendering loading state through `isLoading` prop. + + + + + ## Properties ### DataGrid diff --git a/easy-ui-react/src/DataGrid/DataGrid.stories.tsx b/easy-ui-react/src/DataGrid/DataGrid.stories.tsx index 17fcdb064..f0ec20ed3 100644 --- a/easy-ui-react/src/DataGrid/DataGrid.stories.tsx +++ b/easy-ui-react/src/DataGrid/DataGrid.stories.tsx @@ -310,6 +310,20 @@ export const EmptyState: Story = { }, }; +export const LoadingState: Story = { + render: Template.bind({}), + args: { + "aria-label": "Example data grid loading state", + isLoading: true, + rows: [], + }, + parameters: { + controls: { + include: ["isLoading"], + }, + }, +}; + function WithSortTemplate(args: Partial) { // https://react-spectrum.adobe.com/react-stately/useAsyncList.html const list = useAsyncList({ diff --git a/easy-ui-react/src/DataGrid/DataGrid.test.tsx b/easy-ui-react/src/DataGrid/DataGrid.test.tsx index 8dc618709..5f5b4bacb 100644 --- a/easy-ui-react/src/DataGrid/DataGrid.test.tsx +++ b/easy-ui-react/src/DataGrid/DataGrid.test.tsx @@ -225,6 +225,17 @@ describe("", () => { screen.getByRole("gridcell", { name: /no data yet/i }), ).toBeInTheDocument(); }); + + it("should render a loading state", () => { + render( + createDataGrid({ + isLoading: true, + }), + ); + expect( + screen.getByRole("status", { name: /loading/i }), + ).toBeInTheDocument(); + }); }); const columns = [ diff --git a/easy-ui-react/src/DataGrid/Table.tsx b/easy-ui-react/src/DataGrid/Table.tsx index 691350680..1ff79f23f 100644 --- a/easy-ui-react/src/DataGrid/Table.tsx +++ b/easy-ui-react/src/DataGrid/Table.tsx @@ -18,6 +18,7 @@ import { DataGridTableContext } from "./context"; import { Column, DataGridProps } from "./types"; import { useEdgeInterceptors } from "./useEdgeInterceptors"; import { useExpandedRow } from "./useExpandedRow"; +import { Spinner } from "../Spinner"; import styles from "./DataGrid.module.scss"; @@ -33,6 +34,7 @@ export function Table(props: TableProps) { selectionMode, size = DEFAULT_SIZE, renderEmptyState = () => "No Data!", + isLoading = false, } = props; const outerContainerRef = useRef(null); @@ -122,25 +124,34 @@ export function Table(props: TableProps) { ))} - {collection.size === 0 && ( + {collection.size === 0 || isLoading ? ( - {renderEmptyState()} + {isLoading ? ( + + Loading.. + + ) : ( + renderEmptyState() + )} + ) : ( + [...collection.body.childNodes].map((row) => ( + + {[...row.childNodes].map((cell) => ( + + ))} + + )) )} - {[...collection.body.childNodes].map((row) => ( - - {[...row.childNodes].map((cell) => ( - - ))} - - ))} {expandedRow && ( diff --git a/easy-ui-react/src/DataGrid/types.d.ts b/easy-ui-react/src/DataGrid/types.d.ts index 1980e293c..4d19c82fd 100644 --- a/easy-ui-react/src/DataGrid/types.d.ts +++ b/easy-ui-react/src/DataGrid/types.d.ts @@ -129,4 +129,10 @@ export type DataGridProps = AriaLabelingProps & { * @default "No Data" */ renderEmptyState?: () => ReactNode; + + /** + * Whether the table is currently loading. + * @default false + */ + isLoading?: boolean; };