Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataViews: Handle grid preview size based on container width #68078

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/dataviews/src/components/dataviews-context/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type DataViewsContextType< Item > = {
getItemId: ( item: Item ) => string;
onClickItem?: ( item: Item ) => void;
isItemClickable: ( item: Item ) => boolean;
containerWidth: number;
};

const DataViewsContext = createContext< DataViewsContextType< any > >( {
Expand All @@ -45,6 +46,7 @@ const DataViewsContext = createContext< DataViewsContextType< any > >( {
openedFilter: null,
getItemId: ( item ) => item.id,
isItemClickable: () => true,
containerWidth: 0,
} );

export default DataViewsContext;
13 changes: 12 additions & 1 deletion packages/dataviews/src/components/dataviews/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { ReactNode } from 'react';
*/
import { __experimentalHStack as HStack } from '@wordpress/components';
import { useMemo, useState } from '@wordpress/element';
import { useResizeObserver } from '@wordpress/compose';

/**
* Internal dependencies
Expand Down Expand Up @@ -73,6 +74,15 @@ export default function DataViews< Item >( {
isItemClickable = defaultIsItemClickable,
header,
}: DataViewsProps< Item > ) {
const [ containerWidth, setContainerWidth ] = useState( 0 );
const containerRef = useResizeObserver(
( resizeObserverEntries: any ) => {
setContainerWidth(
resizeObserverEntries[ 0 ].borderBoxSize[ 0 ].inlineSize
);
},
{ box: 'border-box' }
);
const [ selectionState, setSelectionState ] = useState< string[] >( [] );
const isUncontrolled =
selectionProperty === undefined || onChangeSelection === undefined;
Expand Down Expand Up @@ -117,9 +127,10 @@ export default function DataViews< Item >( {
getItemId,
isItemClickable,
onClickItem,
containerWidth,
} }
>
<div className="dataviews-wrapper">
<div className="dataviews-wrapper" ref={ containerRef }>
<HStack
alignment="top"
justify="space-between"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*/
import { RangeControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useViewportMatch } from '@wordpress/compose';
import { useMemo, useContext } from '@wordpress/element';

/**
Expand All @@ -12,46 +11,45 @@ import { useMemo, useContext } from '@wordpress/element';
import DataViewsContext from '../../components/dataviews-context';
import type { ViewGrid } from '../../types';

const viewportBreaks = {
const viewportBreaks: {
[ key: string ]: { min: number; max: number; default: number };
} = {
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', '>=' );
/**
* Breakpoints were adjusted from media queries breakpoints to account for
* the sidebar width. This was done to match the existing styles we had.
*/
const BREAKPOINTS = {
xhuge: 1520,
huge: 1140,
xlarge: 780,
large: 480,
mobile: 0,
};

if ( isXHuge ) {
return 'xhuge';
}
if ( isHuge ) {
return 'huge';
}
if ( isXlarge ) {
return 'xlarge';
}
if ( isLarge ) {
return 'large';
}
if ( isMobile ) {
return 'mobile';
function useViewPortBreakpoint() {
const containerWidth = useContext( DataViewsContext ).containerWidth;
for ( const [ key, value ] of Object.entries( BREAKPOINTS ) ) {
if ( containerWidth >= value ) {
return key;
}
}
return null;
return 'mobile';
}

export function useUpdatedPreviewSizeOnViewportChange() {
const viewport = useViewPortBreakpoint();
const view = useContext( DataViewsContext ).view as ViewGrid;
const viewport = useViewPortBreakpoint();
return useMemo( () => {
const previewSize = view.layout?.previewSize;
let newPreviewSize;
if ( ! viewport || ! previewSize ) {
if ( ! previewSize ) {
return;
}
const breakValues = viewportBreaks[ viewport ];
Expand All @@ -69,9 +67,8 @@ export default function PreviewSizePicker() {
const viewport = useViewPortBreakpoint();
const context = useContext( DataViewsContext );
const view = context.view as ViewGrid;
const breakValues = viewportBreaks[ viewport || 'mobile' ];
const breakValues = viewportBreaks[ viewport ];
const previewSizeToUse = view.layout?.previewSize || breakValues.default;

const marks = useMemo(
() =>
Array.from(
Expand All @@ -84,11 +81,9 @@ export default function PreviewSizePicker() {
),
[ breakValues ]
);

if ( ! viewport ) {
if ( viewport === 'mobile' ) {
return null;
}

return (
<RangeControl
__nextHasNoMarginBottom
Expand Down
30 changes: 14 additions & 16 deletions packages/dataviews/src/dataviews-layouts/grid/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
grid-template-rows: max-content;
padding: 0 $grid-unit-60 $grid-unit-30;
transition: padding ease-out 0.1s;
container-type: inline-size;
@include reduce-motion("transition");


Expand Down Expand Up @@ -126,21 +127,25 @@
}

.dataviews-view-grid.dataviews-view-grid {
grid-template-columns: repeat(1, minmax(0, 1fr));

@include break-mobile() {
/**
* Breakpoints were adjusted from media queries breakpoints to account for
* the sidebar width. This was done to match the existing styles we had.
*/
@container (max-width: 480px) {
grid-template-columns: repeat(1, minmax(0, 1fr));
padding-left: $grid-unit-30;
padding-right: $grid-unit-30;
}
@container (min-width: 480px) {
grid-template-columns: repeat(2, minmax(0, 1fr));
}

@include break-xlarge() {
@container (min-width: 780px) {
grid-template-columns: repeat(3, minmax(0, 1fr));
}

@include break-huge() {
@container (min-width: 1140px) {
grid-template-columns: repeat(4, minmax(0, 1fr));
}

@include break-xhuge() {
@container (min-width: 1520px) {
grid-template-columns: repeat(5, minmax(0, 1fr));
}
}
Expand All @@ -163,13 +168,6 @@
top: $grid-unit-10;
}

@container (max-width: 430px) {
.dataviews-view-grid {
padding-left: $grid-unit-30;
padding-right: $grid-unit-30;
}
}

.dataviews-view-grid__media--clickable {
cursor: pointer;
}
Loading