diff --git a/packages/dataviews/src/components/dataviews-context/index.ts b/packages/dataviews/src/components/dataviews-context/index.ts
index 87acade73bc819..19f6b4178b7b55 100644
--- a/packages/dataviews/src/components/dataviews-context/index.ts
+++ b/packages/dataviews/src/components/dataviews-context/index.ts
@@ -28,7 +28,6 @@ type DataViewsContextType< Item > = {
getItemId: ( item: Item ) => string;
onClickItem: ( item: Item ) => void;
isItemClickable: ( item: Item ) => boolean;
- density: number;
};
const DataViewsContext = createContext< DataViewsContextType< any > >( {
@@ -47,7 +46,6 @@ const DataViewsContext = createContext< DataViewsContextType< any > >( {
getItemId: ( item ) => item.id,
onClickItem: () => {},
isItemClickable: () => false,
- density: 0,
} );
export default DataViewsContext;
diff --git a/packages/dataviews/src/components/dataviews-layout/index.tsx b/packages/dataviews/src/components/dataviews-layout/index.tsx
index 4ef0125b1f64b5..ebc251eae36a7a 100644
--- a/packages/dataviews/src/components/dataviews-layout/index.tsx
+++ b/packages/dataviews/src/components/dataviews-layout/index.tsx
@@ -27,7 +27,6 @@ export default function DataViewsLayout() {
selection,
onChangeSelection,
setOpenedFilter,
- density,
onClickItem,
isItemClickable,
} = useContext( DataViewsContext );
@@ -49,7 +48,6 @@ export default function DataViewsLayout() {
onClickItem={ onClickItem }
isItemClickable={ isItemClickable }
view={ view }
- density={ density }
/>
);
}
diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx
index c8b26c51275891..f13670f27cdab7 100644
--- a/packages/dataviews/src/components/dataviews-view-config/index.tsx
+++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx
@@ -35,7 +35,6 @@ import { useInstanceId } from '@wordpress/compose';
*/
import {
SORTING_DIRECTIONS,
- LAYOUT_GRID,
LAYOUT_TABLE,
sortIcons,
sortLabels,
@@ -49,7 +48,6 @@ import {
import type { SupportedLayouts, View, Field } from '../../types';
import DataViewsContext from '../dataviews-context';
import { unlock } from '../../lock-unlock';
-import DensityPicker from '../../dataviews-layouts/grid/density-picker';
const { Menu } = unlock( componentsPrivateApis );
@@ -512,19 +510,15 @@ function SettingsSection( {
);
}
-function DataviewsViewConfigDropdown( {
- density,
- setDensity,
-}: {
- density: number;
- setDensity: React.Dispatch< React.SetStateAction< number > >;
-} ) {
+function DataviewsViewConfigDropdown() {
const { view } = useContext( DataViewsContext );
const popoverId = useInstanceId(
_DataViewsViewConfig,
'dataviews-view-config-dropdown'
);
-
+ const activeLayout = VIEW_LAYOUTS.find(
+ ( layout ) => layout.type === view.type
+ );
return (
- { view.type === LAYOUT_GRID && (
-
+ { !! activeLayout?.viewConfigOptions && (
+
) }
@@ -570,21 +561,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 3e8224e61bc5d5..ee6073f40bf3d8 100644
--- a/packages/dataviews/src/components/dataviews/index.tsx
+++ b/packages/dataviews/src/components/dataviews/index.tsx
@@ -75,7 +75,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;
@@ -119,7 +118,6 @@ export default function DataViews< Item >( {
getItemId,
isItemClickable,
onClickItem,
- density,
} }
>
@@ -151,8 +149,6 @@ export default function DataViews< Item >( {
>
{ header }
diff --git a/packages/dataviews/src/dataviews-layouts/grid/index.tsx b/packages/dataviews/src/dataviews-layouts/grid/index.tsx
index e218172b7900aa..2a09fb68efab82 100644
--- a/packages/dataviews/src/dataviews-layouts/grid/index.tsx
+++ b/packages/dataviews/src/dataviews-layouts/grid/index.tsx
@@ -25,6 +25,7 @@ import { useHasAPossibleBulkAction } from '../../components/dataviews-bulk-actio
import type { Action, NormalizedField, ViewGridProps } from '../../types';
import type { SetSelection } from '../../private-types';
import getClickableItemProps from '../utils/get-clickable-item-props';
+import { useUpdatedPreviewSizeOnViewportChange } from './preview-size-picker';
interface GridItemProps< Item > {
selection: string[];
@@ -192,7 +193,6 @@ export default function ViewGrid< Item >( {
isItemClickable,
selection,
view,
- density,
}: ViewGridProps< Item > ) {
const mediaField = fields.find(
( field ) => field.id === view.layout?.mediaField
@@ -223,8 +223,12 @@ export default function ViewGrid< Item >( {
{ visibleFields: [], badgeFields: [] }
);
const hasData = !! data?.length;
- const gridStyle = density
- ? { gridTemplateColumns: `repeat(${ density }, minmax(0, 1fr))` }
+ const updatedPreviewSize = useUpdatedPreviewSizeOnViewportChange();
+ const usedPreviewSize = updatedPreviewSize || view.layout?.previewSize;
+ const gridStyle = usedPreviewSize
+ ? {
+ gridTemplateColumns: `repeat(${ usedPreviewSize }, minmax(0, 1fr))`,
+ }
: {};
return (
<>
diff --git a/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx b/packages/dataviews/src/dataviews-layouts/grid/preview-size-picker.tsx
similarity index 56%
rename from packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx
rename to packages/dataviews/src/dataviews-layouts/grid/preview-size-picker.tsx
index 34ddf6c3fe52f3..b48c6422bd6b37 100644
--- a/packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx
+++ b/packages/dataviews/src/dataviews-layouts/grid/preview-size-picker.tsx
@@ -4,7 +4,13 @@
import { RangeControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useViewportMatch } from '@wordpress/compose';
-import { useEffect, useMemo } from '@wordpress/element';
+import { useMemo, useContext } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import DataViewsContext from '../../components/dataviews-context';
+import type { ViewGrid } from '../../types';
const viewportBreaks = {
xhuge: { min: 3, max: 6, default: 5 },
@@ -39,31 +45,32 @@ function useViewPortBreakpoint() {
return null;
}
-export default function DensityPicker( {
- density,
- setDensity,
-}: {
- density: number;
- setDensity: React.Dispatch< React.SetStateAction< number > >;
-} ) {
+export function useUpdatedPreviewSizeOnViewportChange() {
+ const viewport = useViewPortBreakpoint();
+ const view = useContext( DataViewsContext ).view as ViewGrid;
+ return useMemo( () => {
+ const previewSize = view.layout?.previewSize;
+ let newPreviewSize;
+ if ( ! viewport || ! previewSize ) {
+ return;
+ }
+ const breakValues = viewportBreaks[ viewport ];
+ if ( previewSize < breakValues.min ) {
+ newPreviewSize = breakValues.min;
+ }
+ if ( previewSize > breakValues.max ) {
+ newPreviewSize = breakValues.max;
+ }
+ return newPreviewSize;
+ }, [ viewport, view ] );
+}
+
+export default function PreviewSizePicker() {
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 context = useContext( DataViewsContext );
+ const view = context.view as ViewGrid;
const breakValues = viewportBreaks[ viewport || 'mobile' ];
- const densityToUse = density || breakValues.default;
+ const previewSizeToUse = view.layout?.previewSize || breakValues.default;
const marks = useMemo(
() =>
@@ -88,13 +95,19 @@ export default function DensityPicker( {
__next40pxDefaultSize
showTooltip={ false }
label={ __( 'Preview size' ) }
- value={ breakValues.max + breakValues.min - densityToUse }
+ value={ breakValues.max + breakValues.min - previewSizeToUse }
marks={ marks }
min={ breakValues.min }
max={ breakValues.max }
withInputField={ false }
onChange={ ( value = 0 ) => {
- setDensity( breakValues.max + breakValues.min - value );
+ context.onChangeView( {
+ ...view,
+ layout: {
+ ...view.layout,
+ previewSize: breakValues.max + breakValues.min - value,
+ },
+ } );
} }
step={ 1 }
/>
diff --git a/packages/dataviews/src/dataviews-layouts/index.ts b/packages/dataviews/src/dataviews-layouts/index.ts
index eece17d0f4f10c..7abdd1eb459328 100644
--- a/packages/dataviews/src/dataviews-layouts/index.ts
+++ b/packages/dataviews/src/dataviews-layouts/index.ts
@@ -17,6 +17,8 @@ import ViewGrid from './grid';
import ViewList from './list';
import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../constants';
import type { View, Field } from '../types';
+import PreviewSizePicker from './grid/preview-size-picker';
+import DensityPicker from './table/density-picker';
export const VIEW_LAYOUTS = [
{
@@ -24,12 +26,14 @@ export const VIEW_LAYOUTS = [
label: __( 'Table' ),
component: ViewTable,
icon: blockTable,
+ viewConfigOptions: DensityPicker,
},
{
type: LAYOUT_GRID,
label: __( 'Grid' ),
component: ViewGrid,
icon: category,
+ viewConfigOptions: PreviewSizePicker,
},
{
type: LAYOUT_LIST,
diff --git a/packages/dataviews/src/dataviews-layouts/table/density-picker.tsx b/packages/dataviews/src/dataviews-layouts/table/density-picker.tsx
new file mode 100644
index 00000000000000..6d3d31aeb7345e
--- /dev/null
+++ b/packages/dataviews/src/dataviews-layouts/table/density-picker.tsx
@@ -0,0 +1,57 @@
+/**
+ * WordPress dependencies
+ */
+import {
+ __experimentalToggleGroupControl as ToggleGroupControl,
+ __experimentalToggleGroupControlOption as ToggleGroupControlOption,
+} from '@wordpress/components';
+import { __, _x } from '@wordpress/i18n';
+import { useContext } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import DataViewsContext from '../../components/dataviews-context';
+import type { ViewTable, Density } from '../../types';
+
+export default function DensityPicker() {
+ const context = useContext( DataViewsContext );
+ const view = context.view as ViewTable;
+ return (
+
{
+ context.onChangeView( {
+ ...view,
+ layout: {
+ ...view.layout,
+ density: value as Density,
+ },
+ } );
+ } }
+ isBlock
+ >
+
+
+
+
+ );
+}
diff --git a/packages/dataviews/src/dataviews-layouts/table/index.tsx b/packages/dataviews/src/dataviews-layouts/table/index.tsx
index db76d24b53bfa3..7f93a4c14a7ddc 100644
--- a/packages/dataviews/src/dataviews-layouts/table/index.tsx
+++ b/packages/dataviews/src/dataviews-layouts/table/index.tsx
@@ -332,7 +332,13 @@ function ViewTable< Item >( {
return (
<>
diff --git a/packages/dataviews/src/dataviews-layouts/table/style.scss b/packages/dataviews/src/dataviews-layouts/table/style.scss
index ea2c614e4339df..3bbb045c73a9d9 100644
--- a/packages/dataviews/src/dataviews-layouts/table/style.scss
+++ b/packages/dataviews/src/dataviews-layouts/table/style.scss
@@ -169,6 +169,38 @@
opacity: 1;
}
}
+
+ // Density style overrides.
+ &.has-compact-density {
+ thead {
+ th {
+ &:has(.dataviews-view-table-header-button):not(:first-child) {
+ padding-left: 0;
+ }
+ }
+ }
+ td,
+ th {
+ padding: $grid-unit-05 $grid-unit-10;
+ }
+ }
+
+ &.has-comfortable-density {
+ td,
+ th {
+ padding: $grid-unit-20 $grid-unit-15;
+ }
+ }
+
+ &.has-compact-density,
+ &.has-comfortable-density {
+ td,
+ th {
+ &.dataviews-view-table__checkbox-column {
+ padding-right: 0;
+ }
+ }
+ }
}
/* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */
diff --git a/packages/dataviews/src/types.ts b/packages/dataviews/src/types.ts
index 8c4276f2541ecc..861dc53404f914 100644
--- a/packages/dataviews/src/types.ts
+++ b/packages/dataviews/src/types.ts
@@ -329,6 +329,8 @@ export interface ColumnStyle {
minWidth?: string | number;
}
+export type Density = 'compact' | 'balanced' | 'comfortable';
+
export interface ViewTable extends ViewBase {
type: 'table';
@@ -347,6 +349,11 @@ export interface ViewTable extends ViewBase {
* The styles for the columns.
*/
styles?: Record< string, ColumnStyle >;
+
+ /**
+ * The density of the view.
+ */
+ density?: Density;
};
}
@@ -389,6 +396,11 @@ export interface ViewGrid extends ViewBase {
* The fields to use as badge fields.
*/
badgeFields?: string[];
+
+ /**
+ * The preview size of the grid.
+ */
+ previewSize?: number;
};
}
@@ -501,7 +513,6 @@ export interface ViewBaseProps< Item > {
onClickItem: ( item: Item ) => void;
isItemClickable: ( item: Item ) => boolean;
view: View;
- density: number;
}
export interface ViewTableProps< Item > extends ViewBaseProps< Item > {
diff --git a/packages/edit-site/src/components/page-templates/style.scss b/packages/edit-site/src/components/page-templates/style.scss
index 6a753921f6f40a..4432cf6bec4923 100644
--- a/packages/edit-site/src/components/page-templates/style.scss
+++ b/packages/edit-site/src/components/page-templates/style.scss
@@ -60,6 +60,7 @@
.dataviews-view-table & {
margin-bottom: $grid-unit-10;
+ display: block;
}
}
diff --git a/packages/fields/src/fields/featured-image/style.scss b/packages/fields/src/fields/featured-image/style.scss
index 46d37960199ead..918f69172f3023 100644
--- a/packages/fields/src/fields/featured-image/style.scss
+++ b/packages/fields/src/fields/featured-image/style.scss
@@ -83,13 +83,10 @@ fieldset.fields-controls__featured-image {
}
.dataviews-view-table__cell-content-wrapper {
- .fields-controls__featured-image-image {
- width: 32px;
- height: 32px;
- }
-
+ .fields-controls__featured-image-image,
.fields-controls__featured-image-placeholder {
width: 32px;
height: 32px;
+ display: block;
}
}