From d6e306fa2b58a454c879f911187e17076ce06ea3 Mon Sep 17 00:00:00 2001 From: Matt Gallo Date: Fri, 23 Feb 2024 14:06:29 -0500 Subject: [PATCH] feat(Datagrid): add option to specify an initial sortable column (#4423) * feat(Datagrid): apply initial column sort functionality * fix: return if not using sortable table --- .../components/Datagrid/Datagrid.docs-page.js | 36 +++++++++++++++++++ .../components/Datagrid/Datagrid.stories.js | 8 ++++- .../Datagrid/Datagrid/DatagridHeaderRow.js | 2 ++ .../Datagrid/useInitialColumnSort.js | 29 +++++++++++++++ .../components/Datagrid/useSortableColumns.js | 31 ++++++++-------- 5 files changed, 90 insertions(+), 16 deletions(-) create mode 100644 packages/ibm-products/src/components/Datagrid/useInitialColumnSort.js diff --git a/packages/ibm-products/src/components/Datagrid/Datagrid.docs-page.js b/packages/ibm-products/src/components/Datagrid/Datagrid.docs-page.js index 5862d08c01..62cec9d189 100644 --- a/packages/ibm-products/src/components/Datagrid/Datagrid.docs-page.js +++ b/packages/ibm-products/src/components/Datagrid/Datagrid.docs-page.js @@ -436,6 +436,42 @@ const datagridState = useDatagrid( useSortableColumns ); +return ; + `, + }, + }, + { + description: `Columns can also be initially sorted by providing a \`sortableColumn\` object to the \`initialState\`. The structure of + the \`sortableColumn\` property is as follows: +\` +{ + id: string, // column id + order: string, // ASC | DESC +} +\` + +See example below: `, + source: { + code: ` +const [data] = useState(makeData(10)); +const columns = React.useMemo(() => getColumns(data), []); +const datagridState = useDatagrid( + { + columns, + data, + ascendingSortableLabelText: 'none', + descendingSortableLabelText: 'ascending', + defaultSortableLabelText: 'descending', + initialState: { + sortableColumn: { + id: 'firstName', // column id + order: 'ASC' // sorting order + } + } + }, + useSortableColumns +); + return ; `, }, diff --git a/packages/ibm-products/src/components/Datagrid/Datagrid.stories.js b/packages/ibm-products/src/components/Datagrid/Datagrid.stories.js index 3ce037d330..a1cf3f7c81 100644 --- a/packages/ibm-products/src/components/Datagrid/Datagrid.stories.js +++ b/packages/ibm-products/src/components/Datagrid/Datagrid.stories.js @@ -354,11 +354,17 @@ export const SortableColumns = () => { ascendingSortableLabelText: 'ascending', descendingSortableLabelText: 'descending', defaultSortableLabelText: 'none', + initialState: { + sortableColumn: { + id: 'firstName', + order: 'ASC', + }, + }, }, useSortableColumns ); - return ; + return ; }; export const ActionsDropdown = () => { diff --git a/packages/ibm-products/src/components/Datagrid/Datagrid/DatagridHeaderRow.js b/packages/ibm-products/src/components/Datagrid/Datagrid/DatagridHeaderRow.js index 66df32d7f5..55e284029e 100644 --- a/packages/ibm-products/src/components/Datagrid/Datagrid/DatagridHeaderRow.js +++ b/packages/ibm-products/src/components/Datagrid/Datagrid/DatagridHeaderRow.js @@ -18,6 +18,7 @@ import { } from './addons/stateReducer'; import { getNodeTextContent } from '../../../global/js/utils/getNodeTextContent'; import { DatagridSlug } from './addons/Slug/DatagridSlug'; +import { useInitialColumnSort } from '../useInitialColumnSort'; const blockClass = `${pkg.prefix}--datagrid`; @@ -100,6 +101,7 @@ const ResizeHeader = ({ const HeaderRow = (datagridState, headRef, headerGroup) => { const { resizerAriaLabel, isTableSortable, rows, isFetching } = datagridState; + useInitialColumnSort(datagridState); // Used to measure the height of the table and uses that value // to display a vertical line to indicate the column you are resizing useEffect(() => { diff --git a/packages/ibm-products/src/components/Datagrid/useInitialColumnSort.js b/packages/ibm-products/src/components/Datagrid/useInitialColumnSort.js new file mode 100644 index 0000000000..f57e43fcb6 --- /dev/null +++ b/packages/ibm-products/src/components/Datagrid/useInitialColumnSort.js @@ -0,0 +1,29 @@ +/** + * Copyright IBM Corp. 2024, 2024 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { useEffect, useState } from 'react'; +import { getNewSortOrder } from './useSortableColumns'; + +export const useInitialColumnSort = (instance) => { + const [hasInitialSort, setHasInitialSort] = useState(false); + useEffect(() => { + const { initialState, headers, onSort, isTableSortable } = instance; + const { sortableColumn } = initialState; + const foundSortedCol = headers.some((h) => h.isSorted); + if (foundSortedCol || hasInitialSort || !isTableSortable) { + return; + } + + if (sortableColumn) { + const { id: columnId, order } = sortableColumn; + const { newSortDesc, newOrder } = getNewSortOrder(order); + onSort?.(columnId, newOrder); + instance.toggleSortBy(columnId, newSortDesc, false); + setHasInitialSort(true); + } + }, [instance, hasInitialSort]); +}; diff --git a/packages/ibm-products/src/components/Datagrid/useSortableColumns.js b/packages/ibm-products/src/components/Datagrid/useSortableColumns.js index 2b5b3136fb..55cac510ca 100644 --- a/packages/ibm-products/src/components/Datagrid/useSortableColumns.js +++ b/packages/ibm-products/src/components/Datagrid/useSortableColumns.js @@ -21,6 +21,22 @@ const ordering = { NONE: 'NONE', }; +export const getNewSortOrder = (sortOrder) => { + const order = { + newSortDesc: undefined, + newOrder: ordering.NONE, + }; + if (sortOrder === false || sortOrder === ordering.DESC) { + order.newOrder = ordering.DESC; + order.newSortDesc = true; + } + if (sortOrder === undefined || sortOrder === ordering.ASC) { + order.newOrder = ordering.ASC; + order.newSortDesc = false; + } + return order; +}; + const getAriaSortValue = ( col, { @@ -160,21 +176,6 @@ const useSortableColumns = (hooks) => { Object.assign(instance, { manualSortBy: !!onSort, isTableSortable: true }); }; - const getNewSortOrder = (sortOrder) => { - const order = { - newSortDesc: undefined, - newOrder: ordering.NONE, - }; - if (sortOrder === false) { - order.newOrder = ordering.DESC; - order.newSortDesc = true; - } - if (sortOrder === undefined) { - order.newOrder = ordering.ASC; - order.newSortDesc = false; - } - return order; - }; hooks.visibleColumns.push(sortableVisibleColumns); hooks.useInstance.push(sortInstanceProps); };