Skip to content

Commit fe0ada1

Browse files
committed
DataViews: Add density option to table layout
1 parent 944e6b8 commit fe0ada1

11 files changed

Lines changed: 154 additions & 60 deletions

File tree

‎packages/dataviews/src/components/dataviews-context/index.ts‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ type DataViewsContextType< Item > = {
2828
getItemId: ( item: Item ) => string;
2929
onClickItem: ( item: Item ) => void;
3030
isItemClickable: ( item: Item ) => boolean;
31-
density: number;
3231
};
3332

3433
const DataViewsContext = createContext< DataViewsContextType< any > >( {
@@ -47,7 +46,6 @@ const DataViewsContext = createContext< DataViewsContextType< any > >( {
4746
getItemId: ( item ) => item.id,
4847
onClickItem: () => {},
4948
isItemClickable: () => false,
50-
density: 0,
5149
} );
5250

5351
export default DataViewsContext;

‎packages/dataviews/src/components/dataviews-layout/index.tsx‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ export default function DataViewsLayout() {
2727
selection,
2828
onChangeSelection,
2929
setOpenedFilter,
30-
density,
3130
onClickItem,
3231
isItemClickable,
3332
} = useContext( DataViewsContext );
@@ -49,7 +48,6 @@ export default function DataViewsLayout() {
4948
onClickItem={ onClickItem }
5049
isItemClickable={ isItemClickable }
5150
view={ view }
52-
density={ density }
5351
/>
5452
);
5553
}

‎packages/dataviews/src/components/dataviews-view-config/index.tsx‎

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import { useInstanceId } from '@wordpress/compose';
3535
*/
3636
import {
3737
SORTING_DIRECTIONS,
38-
LAYOUT_GRID,
3938
LAYOUT_TABLE,
4039
sortIcons,
4140
sortLabels,
@@ -49,7 +48,6 @@ import {
4948
import type { SupportedLayouts, View, Field } from '../../types';
5049
import DataViewsContext from '../dataviews-context';
5150
import { unlock } from '../../lock-unlock';
52-
import DensityPicker from '../../dataviews-layouts/grid/density-picker';
5351

5452
const { Menu } = unlock( componentsPrivateApis );
5553

@@ -512,19 +510,15 @@ function SettingsSection( {
512510
);
513511
}
514512

515-
function DataviewsViewConfigDropdown( {
516-
density,
517-
setDensity,
518-
}: {
519-
density: number;
520-
setDensity: React.Dispatch< React.SetStateAction< number > >;
521-
} ) {
513+
function DataviewsViewConfigDropdown() {
522514
const { view } = useContext( DataViewsContext );
523515
const popoverId = useInstanceId(
524516
_DataViewsViewConfig,
525517
'dataviews-view-config-dropdown'
526518
);
527-
519+
const usedLayout = VIEW_LAYOUTS.find(
520+
( layout ) => layout.type === view.type
521+
);
528522
return (
529523
<Dropdown
530524
popoverProps={ {
@@ -551,11 +545,8 @@ function DataviewsViewConfigDropdown( {
551545
<SortFieldControl />
552546
<SortDirectionControl />
553547
</HStack>
554-
{ view.type === LAYOUT_GRID && (
555-
<DensityPicker
556-
density={ density }
557-
setDensity={ setDensity }
558-
/>
548+
{ !! usedLayout?.viewConfigOptions && (
549+
<usedLayout.viewConfigOptions />
559550
) }
560551
<ItemsPerPageControl />
561552
</SettingsSection>
@@ -570,21 +561,14 @@ function DataviewsViewConfigDropdown( {
570561
}
571562

572563
function _DataViewsViewConfig( {
573-
density,
574-
setDensity,
575564
defaultLayouts = { list: {}, grid: {}, table: {} },
576565
}: {
577-
density: number;
578-
setDensity: React.Dispatch< React.SetStateAction< number > >;
579566
defaultLayouts?: SupportedLayouts;
580567
} ) {
581568
return (
582569
<>
583570
<ViewTypeMenu defaultLayouts={ defaultLayouts } />
584-
<DataviewsViewConfigDropdown
585-
density={ density }
586-
setDensity={ setDensity }
587-
/>
571+
<DataviewsViewConfigDropdown />
588572
</>
589573
);
590574
}

‎packages/dataviews/src/components/dataviews/index.tsx‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ export default function DataViews< Item >( {
7575
header,
7676
}: DataViewsProps< Item > ) {
7777
const [ selectionState, setSelectionState ] = useState< string[] >( [] );
78-
const [ density, setDensity ] = useState< number >( 0 );
7978
const isUncontrolled =
8079
selectionProperty === undefined || onChangeSelection === undefined;
8180
const selection = isUncontrolled ? selectionState : selectionProperty;
@@ -119,7 +118,6 @@ export default function DataViews< Item >( {
119118
getItemId,
120119
isItemClickable,
121120
onClickItem,
122-
density,
123121
} }
124122
>
125123
<div className="dataviews-wrapper">
@@ -151,8 +149,6 @@ export default function DataViews< Item >( {
151149
>
152150
<DataViewsViewConfig
153151
defaultLayouts={ defaultLayouts }
154-
density={ density }
155-
setDensity={ setDensity }
156152
/>
157153
{ header }
158154
</HStack>

‎packages/dataviews/src/dataviews-layouts/grid/index.tsx‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { useHasAPossibleBulkAction } from '../../components/dataviews-bulk-actio
2525
import type { Action, NormalizedField, ViewGridProps } from '../../types';
2626
import type { SetSelection } from '../../private-types';
2727
import getClickableItemProps from '../utils/get-clickable-item-props';
28+
import { useChangeGridColumnsOnViewportChange } from './preview-size-picker';
2829

2930
interface GridItemProps< Item > {
3031
selection: string[];
@@ -192,8 +193,8 @@ export default function ViewGrid< Item >( {
192193
isItemClickable,
193194
selection,
194195
view,
195-
density,
196196
}: ViewGridProps< Item > ) {
197+
useChangeGridColumnsOnViewportChange();
197198
const mediaField = fields.find(
198199
( field ) => field.id === view.layout?.mediaField
199200
);
@@ -223,8 +224,10 @@ export default function ViewGrid< Item >( {
223224
{ visibleFields: [], badgeFields: [] }
224225
);
225226
const hasData = !! data?.length;
226-
const gridStyle = density
227-
? { gridTemplateColumns: `repeat(${ density }, minmax(0, 1fr))` }
227+
const gridStyle = view.layout?.gridColumns
228+
? {
229+
gridTemplateColumns: `repeat(${ view.layout.gridColumns }, minmax(0, 1fr))`,
230+
}
228231
: {};
229232
return (
230233
<>

packages/dataviews/src/dataviews-layouts/grid/density-picker.tsx renamed to packages/dataviews/src/dataviews-layouts/grid/preview-size-picker.tsx

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
import { RangeControl } from '@wordpress/components';
55
import { __ } from '@wordpress/i18n';
66
import { useViewportMatch } from '@wordpress/compose';
7-
import { useEffect, useMemo } from '@wordpress/element';
7+
import { useEffect, useMemo, useContext } from '@wordpress/element';
8+
9+
/**
10+
* Internal dependencies
11+
*/
12+
import DataViewsContext from '../../components/dataviews-context';
13+
import type { ViewGrid } from '../../types';
814

915
const viewportBreaks = {
1016
xhuge: { min: 3, max: 6, default: 5 },
@@ -39,31 +45,41 @@ function useViewPortBreakpoint() {
3945
return null;
4046
}
4147

42-
export default function DensityPicker( {
43-
density,
44-
setDensity,
45-
}: {
46-
density: number;
47-
setDensity: React.Dispatch< React.SetStateAction< number > >;
48-
} ) {
48+
export function useChangeGridColumnsOnViewportChange() {
4949
const viewport = useViewPortBreakpoint();
50+
const context = useContext( DataViewsContext );
51+
const view = context.view as ViewGrid;
5052
useEffect( () => {
51-
setDensity( ( _density ) => {
52-
if ( ! viewport || ! _density ) {
53-
return 0;
54-
}
55-
const breakValues = viewportBreaks[ viewport ];
56-
if ( _density < breakValues.min ) {
57-
return breakValues.min;
58-
}
59-
if ( _density > breakValues.max ) {
60-
return breakValues.max;
61-
}
62-
return _density;
63-
} );
64-
}, [ setDensity, viewport ] );
53+
const gridColumns = view.layout?.gridColumns;
54+
let newGridColumns;
55+
if ( ! viewport || ! gridColumns ) {
56+
return;
57+
}
58+
const breakValues = viewportBreaks[ viewport ];
59+
if ( gridColumns < breakValues.min ) {
60+
newGridColumns = breakValues.min;
61+
}
62+
if ( gridColumns > breakValues.max ) {
63+
newGridColumns = breakValues.max;
64+
}
65+
if ( newGridColumns ) {
66+
context.onChangeView( {
67+
...view,
68+
layout: {
69+
...view.layout,
70+
gridColumns: newGridColumns,
71+
},
72+
} );
73+
}
74+
}, [ viewport, view, context ] );
75+
}
76+
77+
export default function DensityPicker() {
78+
const viewport = useViewPortBreakpoint();
79+
const context = useContext( DataViewsContext );
80+
const view = context.view as ViewGrid;
6581
const breakValues = viewportBreaks[ viewport || 'mobile' ];
66-
const densityToUse = density || breakValues.default;
82+
const densityToUse = view.layout?.gridColumns || breakValues.default;
6783

6884
const marks = useMemo(
6985
() =>
@@ -94,7 +110,13 @@ export default function DensityPicker( {
94110
max={ breakValues.max }
95111
withInputField={ false }
96112
onChange={ ( value = 0 ) => {
97-
setDensity( breakValues.max + breakValues.min - value );
113+
context.onChangeView( {
114+
...view,
115+
layout: {
116+
...view.layout,
117+
gridColumns: breakValues.max + breakValues.min - value,
118+
},
119+
} );
98120
} }
99121
step={ 1 }
100122
/>

‎packages/dataviews/src/dataviews-layouts/index.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,23 @@ import ViewGrid from './grid';
1717
import ViewList from './list';
1818
import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../constants';
1919
import type { View, Field } from '../types';
20+
import PreviewSizePicker from './grid/preview-size-picker';
21+
import DensityPicker from './table/density-picker';
2022

2123
export const VIEW_LAYOUTS = [
2224
{
2325
type: LAYOUT_TABLE,
2426
label: __( 'Table' ),
2527
component: ViewTable,
2628
icon: blockTable,
29+
viewConfigOptions: DensityPicker,
2730
},
2831
{
2932
type: LAYOUT_GRID,
3033
label: __( 'Grid' ),
3134
component: ViewGrid,
3235
icon: category,
36+
viewConfigOptions: PreviewSizePicker,
3337
},
3438
{
3539
type: LAYOUT_LIST,
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* WordPress dependencies
3+
*/
4+
import {
5+
__experimentalToggleGroupControl as ToggleGroupControl,
6+
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
7+
} from '@wordpress/components';
8+
import { __, _x } from '@wordpress/i18n';
9+
import { useContext } from '@wordpress/element';
10+
11+
/**
12+
* Internal dependencies
13+
*/
14+
import DataViewsContext from '../../components/dataviews-context';
15+
import type { ViewTable, Density } from '../../types';
16+
17+
export default function DensityPicker() {
18+
const context = useContext( DataViewsContext );
19+
const view = context.view as ViewTable;
20+
return (
21+
<ToggleGroupControl
22+
__nextHasNoMarginBottom
23+
size="__unstable-large"
24+
label={ __( 'Density' ) }
25+
value={ view.layout?.density || 'balanced' }
26+
onChange={ ( value ) => {
27+
context.onChangeView( {
28+
...view,
29+
layout: {
30+
...view.layout,
31+
density: value as Density,
32+
},
33+
} );
34+
} }
35+
isBlock
36+
>
37+
<ToggleGroupControlOption
38+
key="comfortable"
39+
value="comfortable"
40+
label={ _x(
41+
'Comfortable',
42+
'Density option for DataView layout'
43+
) }
44+
/>
45+
<ToggleGroupControlOption
46+
key="balanced"
47+
value="balanced"
48+
label={ _x( 'Balanced', 'Density option for DataView layout' ) }
49+
/>
50+
<ToggleGroupControlOption
51+
key="compact"
52+
value="compact"
53+
label={ _x( 'Compact', 'Density option for DataView layout' ) }
54+
/>
55+
</ToggleGroupControl>
56+
);
57+
}

‎packages/dataviews/src/dataviews-layouts/table/index.tsx‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,13 @@ function ViewTable< Item >( {
328328
return (
329329
<>
330330
<table
331-
className="dataviews-view-table"
331+
className={ clsx( 'dataviews-view-table', {
332+
[ `has-${ view.layout?.density }-density` ]:
333+
view.layout?.density &&
334+
[ 'compact', 'comfortable' ].includes(
335+
view.layout.density
336+
),
337+
} ) }
332338
aria-busy={ isLoading }
333339
aria-describedby={ tableNoticeId }
334340
>

‎packages/dataviews/src/dataviews-layouts/table/style.scss‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,21 @@
169169
opacity: 1;
170170
}
171171
}
172+
173+
// Density style overrides.
174+
&.has-compact-density {
175+
td,
176+
th {
177+
padding: $grid-unit-05;
178+
}
179+
}
180+
181+
&.has-comfortable-density {
182+
td,
183+
th {
184+
padding: $grid-unit-20;
185+
}
186+
}
172187
}
173188

174189
/* stylelint-disable-next-line scss/at-rule-no-unknown -- '@container' not globally permitted */

0 commit comments

Comments
 (0)