From 6a2a1dbf2290f1a9c29cff11472106e974db5cc7 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Fri, 19 Jul 2024 13:35:16 +0200 Subject: [PATCH] DataViews: Refactor to prepare exposing the underlying UI pieces (#63694) Co-authored-by: youknowriad Co-authored-by: jorgefilipecosta Co-authored-by: ntsekouras --- packages/base-styles/_z-index.scss | 3 +- .../dataform/index.tsx} | 4 +- .../dataviews-bulk-actions-toolbar/index.tsx} | 58 +- .../dataviews-bulk-actions-toolbar/style.scss | 45 + .../dataviews-bulk-actions/index.tsx} | 54 +- .../dataviews-bulk-actions/style.scss | 7 + .../src/components/dataviews-context/index.ts | 47 + .../dataviews-filters}/add-filter.tsx | 6 +- .../dataviews-filters}/filter-summary.tsx | 28 +- .../dataviews-filters/index.tsx} | 32 +- .../dataviews-filters}/reset-filters.tsx | 2 +- .../dataviews-filters}/search-widget.tsx | 28 +- .../components/dataviews-filters/style.scss | 252 +++++ .../dataviews-item-actions/index.tsx} | 4 +- .../dataviews-item-actions/style.scss | 3 + .../src/components/dataviews-layout/index.tsx | 49 + .../dataviews-pagination/index.tsx} | 28 +- .../dataviews-pagination/style.scss | 26 + .../dataviews-search/index.tsx} | 15 +- .../dataviews-selection-checkbox/index.tsx} | 12 +- .../dataviews-selection-checkbox/style.scss | 14 + .../dataviews-view-config/index.tsx} | 29 +- .../src/components/dataviews/index.tsx | 123 +++ .../src/components/dataviews/style.scss | 97 ++ packages/dataviews/src/dataviews.tsx | 178 ---- packages/dataviews/src/index.ts | 4 +- packages/dataviews/src/layouts/grid/index.tsx | 6 +- .../dataviews/src/layouts/grid/style.scss | 128 +++ packages/dataviews/src/layouts/list/index.tsx | 5 +- .../dataviews/src/layouts/list/style.scss | 189 ++++ .../dataviews/src/layouts/table/index.tsx | 6 +- .../dataviews/src/layouts/table/style.scss | 201 ++++ packages/dataviews/src/style.scss | 962 +----------------- 33 files changed, 1354 insertions(+), 1291 deletions(-) rename packages/dataviews/src/{dataform.tsx => components/dataform/index.tsx} (94%) rename packages/dataviews/src/{bulk-actions-toolbar.tsx => components/dataviews-bulk-actions-toolbar/index.tsx} (82%) create mode 100644 packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss rename packages/dataviews/src/{bulk-actions.tsx => components/dataviews-bulk-actions/index.tsx} (87%) create mode 100644 packages/dataviews/src/components/dataviews-bulk-actions/style.scss create mode 100644 packages/dataviews/src/components/dataviews-context/index.ts rename packages/dataviews/src/{ => components/dataviews-filters}/add-filter.tsx (92%) rename packages/dataviews/src/{ => components/dataviews-filters}/filter-summary.tsx (92%) rename packages/dataviews/src/{filters.tsx => components/dataviews-filters/index.tsx} (75%) rename packages/dataviews/src/{ => components/dataviews-filters}/reset-filters.tsx (94%) rename packages/dataviews/src/{ => components/dataviews-filters}/search-widget.tsx (88%) create mode 100644 packages/dataviews/src/components/dataviews-filters/style.scss rename packages/dataviews/src/{item-actions.tsx => components/dataviews-item-actions/index.tsx} (98%) create mode 100644 packages/dataviews/src/components/dataviews-item-actions/style.scss create mode 100644 packages/dataviews/src/components/dataviews-layout/index.tsx rename packages/dataviews/src/{pagination.tsx => components/dataviews-pagination/index.tsx} (83%) create mode 100644 packages/dataviews/src/components/dataviews-pagination/style.scss rename packages/dataviews/src/{search.tsx => components/dataviews-search/index.tsx} (77%) rename packages/dataviews/src/{single-selection-checkbox.tsx => components/dataviews-selection-checkbox/index.tsx} (80%) create mode 100644 packages/dataviews/src/components/dataviews-selection-checkbox/style.scss rename packages/dataviews/src/{view-actions.tsx => components/dataviews-view-config/index.tsx} (91%) create mode 100644 packages/dataviews/src/components/dataviews/index.tsx create mode 100644 packages/dataviews/src/components/dataviews/style.scss delete mode 100644 packages/dataviews/src/dataviews.tsx create mode 100644 packages/dataviews/src/layouts/grid/style.scss create mode 100644 packages/dataviews/src/layouts/list/style.scss create mode 100644 packages/dataviews/src/layouts/table/style.scss diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index a110c0052b56eb..b8a9088cfd72cc 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -131,6 +131,7 @@ $z-layers: ( ".block-editor-template-part__selection-modal": 1000001, ".block-editor-block-rename-modal": 1000001, ".edit-site-list__rename-modal": 1000001, + ".dataviews-bulk-actions__modal": 1000001, ".dataviews-action-modal": 1000001, ".editor-action-modal": 1000001, ".editor-post-template__swap-template-modal": 1000001, @@ -208,7 +209,7 @@ $z-layers: ( ".dataviews-view-table thead": 1, // Ensure quick actions toolbar appear above pagination - ".dataviews-bulk-actions": 2, + ".dataviews-bulk-actions-toolbar": 2, ); @function z-index( $key ) { diff --git a/packages/dataviews/src/dataform.tsx b/packages/dataviews/src/components/dataform/index.tsx similarity index 94% rename from packages/dataviews/src/dataform.tsx rename to packages/dataviews/src/components/dataform/index.tsx index b81e1c4ae83d37..e61fea075c9b5a 100644 --- a/packages/dataviews/src/dataform.tsx +++ b/packages/dataviews/src/components/dataform/index.tsx @@ -12,8 +12,8 @@ import { useCallback, useMemo } from '@wordpress/element'; /** * Internal dependencies */ -import type { Form, Field, NormalizedField } from './types'; -import { normalizeFields } from './normalize-fields'; +import type { Form, Field, NormalizedField } from '../../types'; +import { normalizeFields } from '../../normalize-fields'; type DataFormProps< Item > = { data: Item; diff --git a/packages/dataviews/src/bulk-actions-toolbar.tsx b/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/index.tsx similarity index 82% rename from packages/dataviews/src/bulk-actions-toolbar.tsx rename to packages/dataviews/src/components/dataviews-bulk-actions-toolbar/index.tsx index c62cd6a5ee9d44..c25328db6a108a 100644 --- a/packages/dataviews/src/bulk-actions-toolbar.tsx +++ b/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/index.tsx @@ -8,7 +8,7 @@ import { __unstableMotion as motion, __unstableAnimatePresence as AnimatePresence, } from '@wordpress/components'; -import { useMemo, useState, useRef } from '@wordpress/element'; +import { useMemo, useState, useRef, useContext } from '@wordpress/element'; import { _n, sprintf, __ } from '@wordpress/i18n'; import { closeSmall } from '@wordpress/icons'; import { useReducedMotion } from '@wordpress/compose'; @@ -17,10 +17,13 @@ import { useRegistry } from '@wordpress/data'; /** * Internal dependencies */ -import { ActionWithModal } from './item-actions'; -import type { Action } from './types'; -import type { ActionTriggerProps } from './item-actions'; -import type { SetSelection } from './private-types'; +import { useSomeItemHasAPossibleBulkAction } from '../dataviews-bulk-actions'; +import DataViewsContext from '../dataviews-context'; +import { ActionWithModal } from '../dataviews-item-actions'; +import { LAYOUT_GRID, LAYOUT_TABLE } from '../../constants'; +import type { Action } from '../../types'; +import type { ActionTriggerProps } from '../dataviews-item-actions'; +import type { SetSelection } from '../../private-types'; interface ActionButtonProps< Item > { action: Action< Item >; @@ -36,14 +39,6 @@ interface ToolbarContentProps< Item > { onChangeSelection: SetSelection; } -interface BulkActionsToolbarProps< Item > { - data: Item[]; - selection: string[]; - actions: Action< Item >[]; - onChangeSelection: SetSelection; - getItemId: ( item: Item ) => string; -} - const SNACKBAR_VARIANTS = { init: { bottom: -48, @@ -136,7 +131,7 @@ function renderToolbarContent< Item >( return ( <> -
+
{ selection.length === 1 ? __( '1 item selected' ) : sprintf( @@ -214,13 +209,14 @@ function ToolbarContent< Item >( { return buttons.current; } -export default function BulkActionsToolbar< Item >( { - data, - selection, - actions = EMPTY_ARRAY, - onChangeSelection, - getItemId, -}: BulkActionsToolbarProps< Item > ) { +function _BulkActionsToolbar() { + const { + data, + selection, + actions = EMPTY_ARRAY, + onChangeSelection, + getItemId, + } = useContext( DataViewsContext ); const isReducedMotion = useReducedMotion(); const selectedItems = useMemo( () => { return data.filter( ( item ) => @@ -258,10 +254,10 @@ export default function BulkActionsToolbar< Item >( { animate="open" exit="exit" variants={ isReducedMotion ? undefined : SNACKBAR_VARIANTS } - className="dataviews-bulk-actions" + className="dataviews-bulk-actions-toolbar" > -
+
( { ); } + +export default function BulkActionsToolbar() { + const { data, actions = [], view } = useContext( DataViewsContext ); + const hasPossibleBulkAction = useSomeItemHasAPossibleBulkAction( + actions, + data + ); + if ( + ! [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) || + ! hasPossibleBulkAction + ) { + return null; + } + + return <_BulkActionsToolbar />; +} diff --git a/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss b/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss new file mode 100644 index 00000000000000..21e6c2ad4d4d64 --- /dev/null +++ b/packages/dataviews/src/components/dataviews-bulk-actions-toolbar/style.scss @@ -0,0 +1,45 @@ +.dataviews-bulk-actions-toolbar { + position: sticky; + display: flex; + flex-direction: column; + align-content: center; + flex-wrap: wrap; + width: fit-content; + margin-left: auto; + margin-right: auto; + bottom: $grid-unit-30; + z-index: z-index(".dataviews-bulk-actions-toolbar"); + + .components-accessible-toolbar { + border-color: $gray-300; + box-shadow: $shadow-popover; + + .components-toolbar-group { + border-color: $gray-200; + + &:last-child { + border: 0; + } + } + } + + .dataviews-bulk-actions-toolbar__selection-count { + display: flex; + align-items: center; + margin: 0 $grid-unit-10 0 $grid-unit-10; + } +} + +.dataviews-bulk-actions-toolbar__wrapper { + display: flex; + flex-grow: 1; + width: 100%; + + .components-toolbar-group { + align-items: center; + } + + .components-button.is-busy { + max-height: $button-size; + } +} diff --git a/packages/dataviews/src/bulk-actions.tsx b/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx similarity index 87% rename from packages/dataviews/src/bulk-actions.tsx rename to packages/dataviews/src/components/dataviews-bulk-actions/index.tsx index ff36d7f7bc2098..2047307bd7e90e 100644 --- a/packages/dataviews/src/bulk-actions.tsx +++ b/packages/dataviews/src/components/dataviews-bulk-actions/index.tsx @@ -7,15 +7,16 @@ import { Modal, } from '@wordpress/components'; import { __, sprintf, _n } from '@wordpress/i18n'; -import { useMemo, useState, useCallback } from '@wordpress/element'; +import { useMemo, useState, useCallback, useContext } from '@wordpress/element'; import { useRegistry } from '@wordpress/data'; /** * Internal dependencies */ -import { unlock } from './lock-unlock'; -import type { Action, ActionModal } from './types'; -import type { SetSelection } from './private-types'; +import DataViewsContext from '../dataviews-context'; +import { LAYOUT_TABLE, LAYOUT_GRID } from '../../constants'; +import { unlock } from '../../lock-unlock'; +import type { Action, ActionModal } from '../../types'; const { DropdownMenuV2: DropdownMenu, @@ -43,14 +44,6 @@ interface ActionsMenuGroupProps< Item > { setActionWithModal: ( action?: ActionModal< Item > ) => void; } -interface BulkActionsProps< Item > { - data: Item[]; - actions: Action< Item >[]; - selection: string[]; - onChangeSelection: SetSelection; - getItemId: ( item: Item ) => string; -} - export function useHasAPossibleBulkAction< Item >( actions: Action< Item >[], item: Item @@ -105,7 +98,7 @@ function ActionWithModal< Item >( { title={ ! hideModalHeader ? label : undefined } __experimentalHideHeader={ !! hideModalHeader } onRequestClose={ onCloseModal } - overlayClassName="dataviews-action-modal" + overlayClassName="dataviews-bulk-actions__modal" > ( { ); } -export default function BulkActions< Item >( { - data, - actions, - selection, - onChangeSelection, - getItemId, -}: BulkActionsProps< Item > ) { +function _BulkActions() { + const { + data, + actions = [], + selection, + onChangeSelection, + getItemId, + } = useContext( DataViewsContext ); const bulkActions = useMemo( () => actions.filter( ( action ) => action.supportsBulk ), [ actions ] ); const [ isMenuOpen, onMenuOpenChange ] = useState( false ); const [ actionWithModal, setActionWithModal ] = useState< - ActionModal< Item > | undefined + ActionModal< any > | undefined >(); const selectableItems = useMemo( () => { return data.filter( ( item ) => { @@ -227,7 +221,7 @@ export default function BulkActions< Item >( { style={ { minWidth: '240px' } } trigger={