diff --git a/packages/dataviews/src/components/dataviews-footer/index.tsx b/packages/dataviews/src/components/dataviews-footer/index.tsx index 191e16f47e2c96..c86db502f32131 100644 --- a/packages/dataviews/src/components/dataviews-footer/index.tsx +++ b/packages/dataviews/src/components/dataviews-footer/index.tsx @@ -41,6 +41,7 @@ export default function DataViewsFooter() { expanded={ false } justify="end" className="dataviews-footer" + style={ view.layout?.styles?.__default__ } > { hasBulkActions && } diff --git a/packages/dataviews/src/components/dataviews/index.tsx b/packages/dataviews/src/components/dataviews/index.tsx index 9d5870174f9db7..4ceca30b186f4a 100644 --- a/packages/dataviews/src/components/dataviews/index.tsx +++ b/packages/dataviews/src/components/dataviews/index.tsx @@ -7,7 +7,13 @@ import type { ReactNode, ComponentProps, ReactElement } from 'react'; * WordPress dependencies */ import { __experimentalHStack as HStack } from '@wordpress/components'; -import { useEffect, useMemo, useRef, useState } from '@wordpress/element'; +import { + useContext, + useEffect, + useMemo, + useRef, + useState, +} from '@wordpress/element'; import { useResizeObserver, throttle } from '@wordpress/compose'; /** @@ -88,6 +94,8 @@ function DefaultUI( { search = true, searchLabel = undefined, }: DefaultUIProps ) { + const { view } = useContext( DataViewsContext ); + return ( <> ( { ); } +function getColumnStyles( view: ViewTableType, columnId: string ) { + const stylesById = view.layout?.styles ?? {}; + const defaultStyles = stylesById.__default__ ?? {}; + const columnStyles = stylesById[ columnId ] ?? {}; + const { align, ...mergedStyles } = { + ...defaultStyles, + ...columnStyles, + }; + return { + ...mergedStyles, + textAlign: align, + }; +} + function TableRow< Item >( { hasBulkActions, item, @@ -194,7 +208,10 @@ function TableRow< Item >( { } } > { hasBulkActions && ( - +
( { ) } { hasPrimaryColumn && ( - + ( { ) } { columns.map( ( column: string ) => { - // Explicit picks the supported styles. - const { width, maxWidth, minWidth, align } = - view.layout?.styles?.[ column ] ?? {}; - + const columnStyles = getColumnStyles( view, column ); return ( - + ); @@ -261,6 +268,7 @@ function TableRow< Item >( { isActionsColumnSticky, } ) } onClick={ ( e ) => e.stopPropagation() } + style={ getColumnStyles( view, '__actions__' ) } > @@ -380,6 +388,10 @@ function ViewTable< Item >( { ( { ) } { hasPrimaryColumn && ( - + { titleField && ( ( { ) } { columns.map( ( column, index ) => { - // Explicit picks the supported styles. - const { width, maxWidth, minWidth, align } = - view.layout?.styles?.[ column ] ?? {}; return ( ( { ! isHorizontalScrollEnd, } ) } + style={ getColumnStyles( view, '__actions__' ) } > { __( 'Actions' ) } diff --git a/packages/dataviews/src/stories/dataviews.story.tsx b/packages/dataviews/src/stories/dataviews.story.tsx index 43f91166840bab..015a4dfb231be1 100644 --- a/packages/dataviews/src/stories/dataviews.story.tsx +++ b/packages/dataviews/src/stories/dataviews.story.tsx @@ -363,6 +363,13 @@ export const WithCard = () => { titleField: 'title', descriptionField: 'description', mediaField: 'image', + layout: { + styles: { + __default__: { + paddingInline: '100px', + }, + }, + }, } ); const { data: shownData, paginationInfo } = useMemo( () => { return filterSortAndPaginate( data, view, fields ); diff --git a/packages/dataviews/src/types/dataviews.ts b/packages/dataviews/src/types/dataviews.ts index bb2836cc097331..33f0cef96a3b13 100644 --- a/packages/dataviews/src/types/dataviews.ts +++ b/packages/dataviews/src/types/dataviews.ts @@ -188,27 +188,18 @@ interface ViewBase { infiniteScrollEnabled?: boolean; } -export interface ColumnStyle { - /** - * The width of the field column. - */ - width?: string | number; - - /** - * The minimum width of the field column. - */ - maxWidth?: string | number; - - /** - * The maximum width of the field column. - */ - minWidth?: string | number; - - /** - * The alignment of the field column, defaults to left. - */ - align?: 'start' | 'center' | 'end'; -} +export type ColumnStyle = + // Allow any valid inline CSS style for td/th + Omit< React.CSSProperties, 'textAlign' > & { + /** + * Logical alignment; mapped to CSS textAlign where applicable. + */ + align?: 'start' | 'center' | 'end'; + /** + * Optional textAlign passthrough if ever needed for headers. + */ + textAlign?: React.CSSProperties[ 'textAlign' ]; + }; export type Density = 'compact' | 'balanced' | 'comfortable'; @@ -235,6 +226,13 @@ export interface ViewTable extends ViewBase { export interface ViewList extends ViewBase { type: 'list'; + + layout?: { + /** + * The styles for the list. + */ + styles?: Record< string, ColumnStyle >; + }; } export interface ViewGrid extends ViewBase { @@ -250,6 +248,11 @@ export interface ViewGrid extends ViewBase { * The preview size of the grid. */ previewSize?: number; + + /** + * The styles for the list. + */ + styles?: Record< string, ColumnStyle >; }; } @@ -266,6 +269,11 @@ export interface ViewPickerGrid extends ViewBase { * The preview size of the grid. */ previewSize?: number; + + /** + * The styles for the list. + */ + styles?: Record< string, ColumnStyle >; }; }