Skip to content

Commit

Permalink
DataViews: Use chips for filter summary (#58816)
Browse files Browse the repository at this point in the history
Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org>
Co-authored-by: jameskoster <jameskoster@git.wordpress.org>
Co-authored-by: oandregal <oandregal@git.wordpress.org>
  • Loading branch information
4 people authored Feb 9, 2024
1 parent 810088e commit 4f6e623
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 25 deletions.
133 changes: 108 additions & 25 deletions packages/dataviews/src/filter-summary.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
Expand All @@ -8,9 +13,13 @@ import {
__experimentalHStack as HStack,
FlexItem,
SelectControl,
Tooltip,
Icon,
} from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
import { useRef } from '@wordpress/element';
import { useRef, createInterpolateElement } from '@wordpress/element';
import { closeSmall } from '@wordpress/icons';
import { ENTER, SPACE } from '@wordpress/keycodes';

/**
* Internal dependencies
Expand All @@ -23,27 +32,38 @@ const FilterText = ( { activeElement, filterInView, filter } ) => {
return filter.name;
}

const filterTextWrappers = {
Span1: <span className="dataviews-filter-summary__filter-text-name" />,
Span2: <span className="dataviews-filter-summary__filter-text-value" />,
};

if (
activeElement !== undefined &&
filterInView?.operator === OPERATOR_IN
) {
return sprintf(
/* translators: 1: Filter name. 2: Filter value. e.g.: "Author is Admin". */
__( '%1$s is %2$s' ),
filter.name,
activeElement.label
return createInterpolateElement(
sprintf(
/* translators: 1: Filter name. 2: Filter value. e.g.: "Author is Admin". */
__( '<Span1>%1$s </Span1><Span2>is %2$s</Span2>' ),
filter.name,
activeElement.label
),
filterTextWrappers
);
}

if (
activeElement !== undefined &&
filterInView?.operator === OPERATOR_NOT_IN
) {
return sprintf(
/* translators: 1: Filter name. 2: Filter value. e.g.: "Author is not Admin". */
__( '%1$s is not %2$s' ),
filter.name,
activeElement.label
return createInterpolateElement(
sprintf(
/* translators: 1: Filter name. 2: Filter value. e.g.: "Author is not Admin". */
__( '<Span1>%1$s </Span1><Span2>is not %2$s</Span2>' ),
filter.name,
activeElement.label
),
filterTextWrappers
);
}

Expand Down Expand Up @@ -153,11 +173,14 @@ export default function FilterSummary( {
...commonProps
} ) {
const toggleRef = useRef();
const { filter, view } = commonProps;
const { filter, view, onChangeView } = commonProps;
const filterInView = view.filters.find( ( f ) => f.field === filter.field );
const activeElement = filter.elements.find(
( element ) => element.value === filterInView?.value
);
const isPrimary = filter.isPrimary;
const hasValues = filterInView?.value !== undefined;
const canResetOrRemove = ! isPrimary || hasValues;
return (
<Dropdown
defaultOpen={ openedFilter === filter.field }
Expand All @@ -167,19 +190,79 @@ export default function FilterSummary( {
toggleRef.current?.focus();
} }
renderToggle={ ( { isOpen, onToggle } ) => (
<Button
__experimentalIsFocusable
size="compact"
onClick={ onToggle }
aria-expanded={ isOpen }
ref={ toggleRef }
>
<FilterText
activeElement={ activeElement }
filterInView={ filterInView }
filter={ filter }
/>
</Button>
<div className="dataviews-filter-summary__chip-container">
<Tooltip
text={ sprintf(
/* translators: 1: Filter name. */
__( 'Filter by: %1$s' ),
filter.name.toLowerCase()
) }
placement="top"
>
<div
className={ classnames(
'dataviews-filter-summary__chip',
{
'has-reset': canResetOrRemove,
'has-values': hasValues,
}
) }
role="button"
tabIndex={ 0 }
onClick={ onToggle }
onKeyDown={ ( event ) => {
if (
[ ENTER, SPACE ].includes( event.keyCode )
) {
onToggle();
event.preventDefault();
}
} }
aria-pressed={ isOpen }
aria-expanded={ isOpen }
ref={ toggleRef }
>
<FilterText
activeElement={ activeElement }
filterInView={ filterInView }
filter={ filter }
/>
</div>
</Tooltip>
{ canResetOrRemove && (
<Tooltip
text={ isPrimary ? __( 'Reset' ) : __( 'Remove' ) }
placement="top"
>
<button
className={ classnames(
'dataviews-filter-summary__chip-remove',
{ 'has-values': hasValues }
) }
onClick={ () => {
onChangeView( {
...view,
page: 1,
filters: view.filters.filter(
( _filter ) =>
_filter.field !== filter.field
),
} );
// If the filter is not primary and can be removed, it will be added
// back to the available filters from `Add filter` component.
if ( ! isPrimary ) {
addFilterRef.current?.focus();
} else {
// If is primary, focus the toggle button.
toggleRef.current?.focus();
}
} }
>
<Icon icon={ closeSmall } />
</button>
</Tooltip>
) }
</div>
) }
renderContent={ () => {
return (
Expand Down
89 changes: 89 additions & 0 deletions packages/dataviews/src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -631,3 +631,92 @@
padding: $grid-unit-05;
border-top: 1px solid $gray-200;
}

.dataviews-filter-summary__chip-container {
position: relative;
white-space: pre-wrap;

.dataviews-filter-summary__chip {
border-radius: $grid-unit-20;
border: 1px solid transparent;
cursor: pointer;
padding: 0 $grid-unit-15;
height: $grid-unit-40;
background: $gray-100;
color: $gray-700;
position: relative;
display: flex;
align-items: center;

&.has-reset {
padding-inline-end: $button-size-small + $grid-unit-05;
}

&:hover,
&:focus-visible {
background: $gray-200;
color: $gray-900;
}

&.has-values {
color: var(--wp-admin-theme-color);
background: rgba(var(--wp-admin-theme-color--rgb), 0.04);

&:hover {
background: rgba(var(--wp-admin-theme-color--rgb), 0.08);
}
}

&:focus-visible {
outline: none;
box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);
}

.dataviews-filter-summary__filter-text-name {
font-weight: 500;
}
}

.dataviews-filter-summary__chip-remove {
width: $icon-size;
height: $icon-size;
border-radius: 50%;
border: 0;
padding: 0;
position: absolute;
right: $grid-unit-05;
top: 50%;
transform: translateY(-50%);
display: flex;
align-items: center;
justify-content: center;
background: transparent;
cursor: pointer;

svg {
fill: $gray-700;
}

&:hover,
&:focus {
background: $gray-200;
svg {
fill: $gray-900;
}
}

&.has-values {
svg {
fill: var(--wp-admin-theme-color);
}
&:hover {
background: rgba(var(--wp-admin-theme-color--rgb), 0.08);
}
}

&:focus-visible {
outline: none;
box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color);
}
}
}

1 comment on commit 4f6e623

@github-actions
Copy link

Choose a reason for hiding this comment

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

Flaky tests detected in 4f6e623.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/7843078531
📝 Reported issues:

Please sign in to comment.