@@ -570,21 +601,14 @@ function DataviewsViewConfigDropdown( {
}
function _DataViewsViewConfig( {
- density,
- setDensity,
defaultLayouts = { list: {}, grid: {}, table: {} },
}: {
- density: number;
- setDensity: React.Dispatch< React.SetStateAction< number > >;
defaultLayouts?: SupportedLayouts;
} ) {
return (
<>
-
+
>
);
}
diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx
index da60ab15ecade..650fcdb5dee85 100644
--- a/packages/dataviews/src/components/dataviews/index.tsx
+++ b/packages/dataviews/src/components/dataviews/index.tsx
@@ -68,7 +68,6 @@ export default function DataViews< Item >( {
header,
}: DataViewsProps< Item > ) {
const [ selectionState, setSelectionState ] = useState< string[] >( [] );
- const [ density, setDensity ] = useState< number >( 0 );
const isUncontrolled =
selectionProperty === undefined || onChangeSelection === undefined;
const selection = isUncontrolled ? selectionState : selectionProperty;
@@ -110,7 +109,6 @@ export default function DataViews< Item >( {
openedFilter,
setOpenedFilter,
getItemId,
- density,
} }
>
@@ -142,8 +140,6 @@ export default function DataViews< Item >( {
>
{ header }
diff --git a/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx b/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx
deleted file mode 100644
index 34ddf6c3fe52f..0000000000000
--- a/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { RangeControl } from '@wordpress/components';
-import { __ } from '@wordpress/i18n';
-import { useViewportMatch } from '@wordpress/compose';
-import { useEffect, useMemo } from '@wordpress/element';
-
-const viewportBreaks = {
- xhuge: { min: 3, max: 6, default: 5 },
- huge: { min: 2, max: 4, default: 4 },
- xlarge: { min: 2, max: 3, default: 3 },
- large: { min: 1, max: 2, default: 2 },
- mobile: { min: 1, max: 2, default: 2 },
-};
-
-function useViewPortBreakpoint() {
- const isXHuge = useViewportMatch( 'xhuge', '>=' );
- const isHuge = useViewportMatch( 'huge', '>=' );
- const isXlarge = useViewportMatch( 'xlarge', '>=' );
- const isLarge = useViewportMatch( 'large', '>=' );
- const isMobile = useViewportMatch( 'mobile', '>=' );
-
- if ( isXHuge ) {
- return 'xhuge';
- }
- if ( isHuge ) {
- return 'huge';
- }
- if ( isXlarge ) {
- return 'xlarge';
- }
- if ( isLarge ) {
- return 'large';
- }
- if ( isMobile ) {
- return 'mobile';
- }
- return null;
-}
-
-export default function DensityPicker( {
- density,
- setDensity,
-}: {
- density: number;
- setDensity: React.Dispatch< React.SetStateAction< number > >;
-} ) {
- const viewport = useViewPortBreakpoint();
- useEffect( () => {
- setDensity( ( _density ) => {
- if ( ! viewport || ! _density ) {
- return 0;
- }
- const breakValues = viewportBreaks[ viewport ];
- if ( _density < breakValues.min ) {
- return breakValues.min;
- }
- if ( _density > breakValues.max ) {
- return breakValues.max;
- }
- return _density;
- } );
- }, [ setDensity, viewport ] );
- const breakValues = viewportBreaks[ viewport || 'mobile' ];
- const densityToUse = density || breakValues.default;
-
- const marks = useMemo(
- () =>
- Array.from(
- { length: breakValues.max - breakValues.min + 1 },
- ( _, i ) => {
- return {
- value: breakValues.min + i,
- };
- }
- ),
- [ breakValues ]
- );
-
- if ( ! viewport ) {
- return null;
- }
-
- return (
- {
- setDensity( breakValues.max + breakValues.min - value );
- } }
- step={ 1 }
- />
- );
-}
diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx
index 230ffe0dc50b5..494bb43e0db01 100644
--- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx
+++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx
@@ -22,8 +22,10 @@ import { __ } from '@wordpress/i18n';
import ItemActions from '../../components/dataviews-item-actions';
import SingleSelectionCheckbox from '../../components/dataviews-selection-checkbox';
import { useHasAPossibleBulkAction } from '../../components/dataviews-bulk-actions';
+import { DensityOptions } from '../../types';
import type { Action, NormalizedField, ViewGridProps } from '../../types';
import type { SetSelection } from '../../private-types';
+import useDensityOptions from './use-density-options';
interface GridItemProps< Item > {
selection: string[];
@@ -172,7 +174,6 @@ export default function ViewGrid< Item >( {
onChangeSelection,
selection,
view,
- density,
}: ViewGridProps< Item > ) {
const mediaField = fields.find(
( field ) => field.id === view.layout?.mediaField
@@ -203,9 +204,22 @@ export default function ViewGrid< Item >( {
{ visibleFields: [], badgeFields: [] }
);
const hasData = !! data?.length;
- const gridStyle = density
- ? { gridTemplateColumns: `repeat(${ density }, minmax(0, 1fr))` }
- : {};
+ // The `DensityOptions.medium` (default) is handled with css. If another density is selected,
+ // we query the viewport to determine the number of columns to display per option.
+ const densityOptions = useDensityOptions();
+ const gridStyle =
+ !! view.density &&
+ [ DensityOptions.comfortable, DensityOptions.compact ].includes(
+ view.density as DensityOptions
+ )
+ ? {
+ gridTemplateColumns: `repeat(${
+ view.density === DensityOptions.compact
+ ? densityOptions.max
+ : densityOptions.min
+ }, minmax(0, 1fr))`,
+ }
+ : {};
return (
<>
{ hasData && (
diff --git a/packages/dataviews/src/dataviews-layouts/grid/use-density-options.ts b/packages/dataviews/src/dataviews-layouts/grid/use-density-options.ts
new file mode 100644
index 0000000000000..6fa7df17fd4bb
--- /dev/null
+++ b/packages/dataviews/src/dataviews-layouts/grid/use-density-options.ts
@@ -0,0 +1,25 @@
+/**
+ * WordPress dependencies
+ */
+import { useViewportMatch } from '@wordpress/compose';
+
+export default function useDensityOptions() {
+ const isXHuge = useViewportMatch( 'xhuge' );
+ const isHuge = useViewportMatch( 'huge' );
+ const isXlarge = useViewportMatch( 'xlarge' );
+ const isLarge = useViewportMatch( 'large' );
+ if ( isXHuge ) {
+ return { min: 3, max: 6 };
+ }
+ if ( isHuge ) {
+ return { min: 2, max: 4 };
+ }
+ if ( isXlarge ) {
+ return { min: 2, max: 3 };
+ }
+ if ( isLarge ) {
+ return { min: 1, max: 2 };
+ }
+ // Default to mobile.
+ return { min: 1, max: 2 };
+}
diff --git a/packages/dataviews/src/dataviews-layouts/index.ts b/packages/dataviews/src/dataviews-layouts/index.ts
index eece17d0f4f10..e832ef3c4aa13 100644
--- a/packages/dataviews/src/dataviews-layouts/index.ts
+++ b/packages/dataviews/src/dataviews-layouts/index.ts
@@ -30,6 +30,7 @@ export const VIEW_LAYOUTS = [
label: __( 'Grid' ),
component: ViewGrid,
icon: category,
+ supportsDensity: true,
},
{
type: LAYOUT_LIST,
diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts
index 0ea0965704d18..c0e164f77499f 100644
--- a/packages/dataviews/src/types.ts
+++ b/packages/dataviews/src/types.ts
@@ -247,6 +247,12 @@ export interface NormalizedFilter {
isPrimary: boolean;
}
+export enum DensityOptions {
+ medium = 0,
+ compact = 1,
+ comfortable = 2,
+}
+
interface ViewBase {
/**
* The layout of the view.
@@ -292,6 +298,12 @@ interface ViewBase {
* The fields to render
*/
fields?: string[];
+
+ /**
+ * The density of the view.
+ */
+ // TODO: maybe move to `layout` object?
+ density?: DensityOptions;
}
export interface CombinedField {
@@ -499,7 +511,6 @@ export interface ViewBaseProps< Item > {
selection: string[];
setOpenedFilter: ( fieldId: string ) => void;
view: View;
- density: number;
}
export interface ViewTableProps< Item > extends ViewBaseProps< Item > {