diff --git a/packages/dataviews/CHANGELOG.md b/packages/dataviews/CHANGELOG.md index 957b6d0b5e0f1e..f44b9f77e6b52b 100644 --- a/packages/dataviews/CHANGELOG.md +++ b/packages/dataviews/CHANGELOG.md @@ -5,6 +5,7 @@ ### Enhancements - Simplify field normalization and types. [#73387](https://github.com/WordPress/gutenberg/pull/73387) +- DataViews and DataViewsPicker: add padding prop to control outer padding. [#72989](https://github.com/WordPress/gutenberg/pull/72989) - DataViews table layout: make checkboxes permanently visible when bulk actions are available. [#73245](https://github.com/WordPress/gutenberg/pull/73245) - DataViews: Make sticky elements (table headers, footer, actions column) inherit background colors from parent container. This allows DataViews instances to seamlessly adapt to containers with custom background colors. [#73240](https://github.com/WordPress/gutenberg/pull/73240) - DataViews table layout: only apply hover styles when bulk actions are available. [#73248](https://github.com/WordPress/gutenberg/pull/73248) diff --git a/packages/dataviews/src/components/dataviews-footer/style.scss b/packages/dataviews/src/components/dataviews-footer/style.scss index 9f22c42c2d6163..c64e83de2f4a82 100644 --- a/packages/dataviews/src/components/dataviews-footer/style.scss +++ b/packages/dataviews/src/components/dataviews-footer/style.scss @@ -7,7 +7,10 @@ bottom: 0; left: 0; background-color: inherit; - padding: $grid-unit-15 $grid-unit-60; + padding-block-start: $grid-unit-15; + padding-block-end: var(--wp-dataviews-padding-block-end, #{$grid-unit-15}); + padding-inline-start: var(--wp-dataviews-padding-inline-start, #{$grid-unit-60}); + padding-inline-end: var(--wp-dataviews-padding-inline-end, #{$grid-unit-60}); border-top: $border-width solid $gray-100; flex-shrink: 0; @@ -20,7 +23,10 @@ @container (max-width: 430px) { .dataviews-footer { - padding: $grid-unit-15 $grid-unit-30; + padding-block-start: $grid-unit-15; + padding-block-end: var(--wp-dataviews-padding-block-end, #{$grid-unit-15}); + padding-inline-start: var(--wp-dataviews-padding-inline-start, #{$grid-unit-30}); + padding-inline-end: var(--wp-dataviews-padding-inline-end, #{$grid-unit-30}); } } diff --git a/packages/dataviews/src/components/dataviews-picker/get-padding-by-size.ts b/packages/dataviews/src/components/dataviews-picker/get-padding-by-size.ts new file mode 100644 index 00000000000000..79949f1a57c45c --- /dev/null +++ b/packages/dataviews/src/components/dataviews-picker/get-padding-by-size.ts @@ -0,0 +1,112 @@ +/** + * Internal dependencies + */ +import type { + PaddingSize, + PaddingOptions, + DimensionVariant, +} from '../../types/private'; + +/** + * Maps padding size tokens to CSS values. + * Aligned with the Card component's spacing scale (space function with 4px base): + * - x-small: space(2) = 8px + * - small: space(4) = 16px + * - medium: space(6) = 24px + * - large: space(8) = 32px + * - x-large: space(12) = 48px + */ +const paddingValuesBySize: Record< PaddingSize, string > = { + 'x-small': '8px', + small: '16px', + medium: '24px', + large: '32px', + 'x-large': '48px', + none: '0', +}; + +/** + * Gets the CSS value for a single padding size token. + * + * @param size The padding size token. + * @return The CSS value for the padding size. + */ +function getSinglePaddingValue( size: PaddingSize ): string { + return paddingValuesBySize[ size ]; +} + +/** + * Converts padding options into CSS custom property style values. + * Returns an object with the appropriate CSS custom properties set. + * When padding is undefined, returns an empty object to allow SCSS + * defaults and container queries to apply. + * + * @param padding The padding option (single size or directional variants), or undefined to use SCSS defaults + * @return An object with CSS custom property values, or empty object to use SCSS defaults + */ +export function getPaddingBySizeStyles( + padding: PaddingOptions | undefined +): Record< string, string > { + const styles: Record< string, string > = {}; + + // Handle string-based sizes (single value applied to all directional variants) + if ( typeof padding === 'string' ) { + const value = getSinglePaddingValue( padding ); + styles[ '--wp-dataviews-padding-block-start' ] = value; + styles[ '--wp-dataviews-padding-block-end' ] = value; + styles[ '--wp-dataviews-padding-inline-start' ] = value; + styles[ '--wp-dataviews-padding-inline-end' ] = value; + return styles; + } + + // If no padding specified, return empty object to use SCSS defaults + if ( ! padding ) { + return styles; + } + + // Handle object with directional variants + const { block, blockStart, blockEnd, inline, inlineStart, inlineEnd } = + padding as DimensionVariant< PaddingSize >; + + if ( block !== undefined ) { + const value = getSinglePaddingValue( block ); + if ( blockStart === undefined ) { + styles[ '--wp-dataviews-padding-block-start' ] = value; + } + if ( blockEnd === undefined ) { + styles[ '--wp-dataviews-padding-block-end' ] = value; + } + } + + if ( blockStart !== undefined ) { + styles[ '--wp-dataviews-padding-block-start' ] = + getSinglePaddingValue( blockStart ); + } + + if ( blockEnd !== undefined ) { + styles[ '--wp-dataviews-padding-block-end' ] = + getSinglePaddingValue( blockEnd ); + } + + if ( inline !== undefined ) { + const value = getSinglePaddingValue( inline ); + if ( inlineStart === undefined ) { + styles[ '--wp-dataviews-padding-inline-start' ] = value; + } + if ( inlineEnd === undefined ) { + styles[ '--wp-dataviews-padding-inline-end' ] = value; + } + } + + if ( inlineStart !== undefined ) { + styles[ '--wp-dataviews-padding-inline-start' ] = + getSinglePaddingValue( inlineStart ); + } + + if ( inlineEnd !== undefined ) { + styles[ '--wp-dataviews-padding-inline-end' ] = + getSinglePaddingValue( inlineEnd ); + } + + return styles; +} diff --git a/packages/dataviews/src/components/dataviews-picker/index.tsx b/packages/dataviews/src/components/dataviews-picker/index.tsx index a97bb40825978f..88db5747d2c75d 100644 --- a/packages/dataviews/src/components/dataviews-picker/index.tsx +++ b/packages/dataviews/src/components/dataviews-picker/index.tsx @@ -31,7 +31,8 @@ import DataViewsViewConfig, { } from '../dataviews-view-config'; import normalizeFields from '../../field-types/utils/normalize-fields'; import type { ActionButton, Field, View, SupportedLayouts } from '../../types'; -import type { SelectionOrUpdater } from '../../types/private'; +import type { SelectionOrUpdater, PaddingOptions } from '../../types/private'; +import { getPaddingBySizeStyles } from './get-padding-by-size'; type ItemWithId = { id: string }; const isItemClickable = () => false; @@ -63,6 +64,11 @@ type DataViewsPickerProps< Item > = { }; itemListLabel?: string; empty?: ReactNode; + /** + * Determines the amount of padding within the component. + * When not provided, the default SCSS padding values are used. + */ + padding?: PaddingOptions; } & ( Item extends ItemWithId ? { getItemId?: ( item: Item ) => string } : { getItemId: ( item: Item ) => string } ); @@ -128,6 +134,7 @@ function DataViewsPicker< Item >( { config = { perPageSizes: [ 10, 20, 50, 100 ] }, itemListLabel, empty, + padding, }: DataViewsPickerProps< Item > ) { const { infiniteScrollHandler } = paginationInfo; const containerRef = useRef< HTMLDivElement | null >( null ); @@ -209,6 +216,11 @@ function DataViewsPicker< Item >( { [ defaultLayoutsProperty ] ); + const paddingStyles = useMemo( + () => getPaddingBySizeStyles( padding ), + [ padding ] + ); + if ( ! defaultLayouts[ view.type ] ) { return null; } @@ -242,7 +254,11 @@ function DataViewsPicker< Item >( { hasInfiniteScrollHandler: !! infiniteScrollHandler, } } > -
+
{ children ?? ( ) } diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index 07cda5d91bd9b7..2c39c340d52540 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -32,7 +32,8 @@ import DataViewsViewConfig, { } from '../dataviews-view-config'; import normalizeFields from '../../field-types/utils/normalize-fields'; import type { Action, Field, View, SupportedLayouts } from '../../types'; -import type { SelectionOrUpdater } from '../../types/private'; +import type { SelectionOrUpdater, PaddingOptions } from '../../types/private'; +import { getPaddingBySizeStyles } from '../dataviews-picker/get-padding-by-size'; type ItemWithId = { id: string }; type DataViewsProps< Item > = { @@ -66,6 +67,11 @@ type DataViewsProps< Item > = { perPageSizes: number[]; }; empty?: ReactNode; + /** + * Determines the amount of padding within the component. + * When not provided, the default SCSS padding values are used. + */ + padding?: PaddingOptions; } & ( Item extends ItemWithId ? { getItemId?: ( item: Item ) => string } : { getItemId: ( item: Item ) => string } ); @@ -142,6 +148,7 @@ function DataViews< Item >( { children, config = { perPageSizes: [ 10, 20, 50, 100 ] }, empty, + padding, }: DataViewsProps< Item > ) { const { infiniteScrollHandler } = paginationInfo; const containerRef = useRef< HTMLDivElement | null >( null ); @@ -236,6 +243,11 @@ function DataViews< Item >( { [ defaultLayoutsProperty ] ); + const paddingStyles = useMemo( + () => getPaddingBySizeStyles( padding ), + [ padding ] + ); + if ( ! defaultLayouts[ view.type ] ) { return null; } @@ -271,7 +283,11 @@ function DataViews< Item >( { hasInfiniteScrollHandler: !! infiniteScrollHandler, } } > -
+
{ children ?? ( []; selection?: string[]; + padding?: PaddingOptions; } const DataViewsPickerContent = ( { @@ -72,8 +95,10 @@ const DataViewsPickerContent = ( { infiniteScrollEnabled, actions: customActions, selection: customSelection, + padding: customPadding, }: PickerContentProps ) => { const [ view, setView ] = useState< View >( { + type: LAYOUT_PICKER_GRID, fields: [], titleField: 'title', mediaField: 'image', @@ -81,7 +106,6 @@ const DataViewsPickerContent = ( { page: 1, perPage: 10, filters: [], - type: LAYOUT_PICKER_GRID, groupBy: isGrouped ? { field: 'type', direction: 'asc' } : undefined, infiniteScrollEnabled, } ); @@ -93,10 +117,8 @@ const DataViewsPickerContent = ( { useEffect( () => { setView( ( prevView ) => ( { ...prevView, - groupBy: - isGrouped && ! infiniteScrollEnabled - ? { field: 'type', direction: 'asc' } - : undefined, + groupByField: + isGrouped && ! infiniteScrollEnabled ? 'type' : undefined, infiniteScrollEnabled, } ) ); }, [ isGrouped, infiniteScrollEnabled ] ); @@ -141,14 +163,14 @@ const DataViewsPickerContent = ( { setView, data: shownData, getItemId: ( item ) => item.id.toString(), - totalDataLength: data.length, + totalDataLength: shownData.length, } ); return ( <> { infiniteScrollEnabled && ( + ) }