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: Support defining field headers/names as React elements. #64642

Merged
merged 2 commits into from
Aug 21, 2024
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
8 changes: 7 additions & 1 deletion packages/dataviews/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@

## Unreleased

- The "move left/move right" controls in the table layout (popup displayed on cliking header) are always visible. ([#64646](https://github.com/WordPress/gutenberg/pull/64646)). Before this, its visibility depending on filters, enableSorting, and enableHiding.
## New features

- Support using a component for field headers or names by providing a `header` property in the field object. The string `label` property (or `id`) is still mandatory. ([#64642](https://github.com/WordPress/gutenberg/pull/64642)).

## Internal

- The "move left/move right" controls in the table layout (popup displayed on cliking header) are always visible. ([#64646](https://github.com/WordPress/gutenberg/pull/64646)). Before this, its visibility depending on filters, enableSorting, and enableHiding.

## 4.1.0 (2024-08-07)

Expand Down
14 changes: 13 additions & 1 deletion packages/dataviews/src/components/dataviews/stories/fixtures.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
import { trash } from '@wordpress/icons';
import { trash, image, Icon, category } from '@wordpress/icons';
import {
Button,
__experimentalText as Text,
Expand Down Expand Up @@ -173,6 +173,12 @@ export const fields = [
{
label: 'Image',
id: 'image',
header: (
<HStack spacing={ 1 } justify="start">
<Icon icon={ image } />
<span>Image</span>
</HStack>
),
render: ( { item } ) => {
return (
<img src={ item.image } alt="" style={ { width: '100%' } } />
Expand Down Expand Up @@ -217,6 +223,12 @@ export const fields = [
{
label: 'Categories',
id: 'categories',
header: (
<HStack spacing={ 1 } justify="start">
<Icon icon={ category } />
<span>Categories</span>
</HStack>
),
elements: [
{ value: 'Space', label: 'Space' },
{ value: 'NASA', label: 'NASA' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useState, useMemo } from '@wordpress/element';
*/
import DataViews from '../index';
import { DEFAULT_VIEW, actions, data, fields } from './fixtures';
import { LAYOUT_GRID, LAYOUT_TABLE } from '../../../constants';
import { LAYOUT_GRID, LAYOUT_LIST, LAYOUT_TABLE } from '../../../constants';
import { filterSortAndPaginate } from '../../../filter-and-sort-data-view';

const meta = {
Expand Down Expand Up @@ -61,5 +61,11 @@ Default.args = {
primaryField: 'title',
},
},
[ LAYOUT_LIST ]: {
layout: {
mediaField: 'image',
primaryField: 'title',
},
},
},
};
2 changes: 1 addition & 1 deletion packages/dataviews/src/dataviews-layouts/grid/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ function GridItem< Item >( {
>
<>
<FlexItem className="dataviews-view-grid__field-name">
{ field.label }
{ field.header }
</FlexItem>
<FlexItem
className="dataviews-view-grid__field-value"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >(
);
const index = view.fields?.indexOf( fieldId ) as number;
if ( !! combinedField ) {
return combinedField.label;
return combinedField.header || combinedField.label;
}
const field = fields.find( ( f ) => f.id === fieldId );
if ( ! field ) {
Expand Down Expand Up @@ -102,7 +102,7 @@ const _HeaderMenu = forwardRef( function HeaderMenu< Item >(
ref={ ref }
variant="tertiary"
>
{ field.label }
{ field.header }
{ view.sort && isSorted && (
<span aria-hidden="true">
{ sortArrows[ view.sort.direction ] }
Expand Down
1 change: 1 addition & 0 deletions packages/dataviews/src/normalize-fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export function normalizeFields< Item >(
return {
...field,
label: field.label || field.id,
header: field.header || field.label || field.id,
getValue,
render,
sort,
Expand Down
9 changes: 9 additions & 0 deletions packages/dataviews/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ export type Field< Item > = {
*/
label?: string;

/**
* The header of the field. Defaults to the label.
* It allows the usage of a React Element to render the field labels.
*/
header?: string | ReactElement;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this a ReactElement and remove the string type? Otherwise, why would you use the header as string if there's already the label field.

Unless you want to enable they being different, which I don't think is the intentionality here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just because in the NormalizedField type we fallback to the label to avoid having to do the fallback everywhere. But in Field it can indeed be just ReactElement

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To enforce the ReactElement type, when we normalize the field, can't we provide a function that returns the field.label if field.header is not present?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To enforce the ReactElement type, when we normalize the field, can't we provide a function that returns the field.label if field.header is not present?

Feels more complex to me, especially since string and React element can both be considered "React Element" I wonder if there's a dedicated type for that.


/**
* A description of the field.
*/
Expand Down Expand Up @@ -151,6 +157,7 @@ export type Field< Item > = {

export type NormalizedField< Item > = Field< Item > & {
label: string;
header: string | ReactElement;
getValue: ( args: { item: Item } ) => any;
render: ComponentType< { item: Item } >;
Edit: ComponentType< DataFormControlProps< Item > >;
Expand Down Expand Up @@ -289,6 +296,8 @@ export interface CombinedField {

label: string;

header?: string | ReactElement;

/**
* The fields to use as columns.
*/
Expand Down
Loading