* Add `hidden` legendPosition to `Chart`.

Sometimes, for example, when there is a single data set, there is no need for rendering the legend. It may even introduce more confusion than value. It seems interactive, but there is nothing you can do with it.

Fixes: https://github.com/woocommerce/google-listings-and-ads/issues/618

* Add `@storybook/addon-knobs` to devDependencies.

It was used but not explicitely stated.

* Add a changelog entry.

* Add tests for legendPosition in Chart component

Co-authored-by: Lourens Schep <lourensschep@gmail.com>
This commit is contained in:
Tomek Wytrębowicz 2021-07-27 16:14:54 +02:00 committed by GitHub
parent 17c1b38781
commit afd6693718
6 changed files with 124 additions and 19 deletions

View File

@ -1,6 +1,7 @@
# Unreleased
- Fix a bug in the deprecated callback handlers of Form component. #7356
- Add `hidden` legend position to `Chart`. #7378
# 8.0.0

View File

@ -25,6 +25,7 @@
"src/**/*.scss"
],
"dependencies": {
"@storybook/addon-knobs": "^6.3.0",
"@woocommerce/csv-export": "file:../csv-export",
"@woocommerce/currency": "file:../currency",
"@woocommerce/data": "file:../data",

View File

@ -91,7 +91,7 @@ Name | Type | Default | Description
`interval` | One of: 'hour', 'day', 'week', 'month', 'quarter', 'year' | `'day'` | Interval specification (hourly, daily, weekly etc)
`intervalData` | Object | `null` | Information about the currently selected interval, and set of allowed intervals for the chart. See `getIntervalsForQuery`
`isRequesting` | Boolean | `false` | Render a chart placeholder to signify an in-flight data request
`legendPosition` | One of: 'bottom', 'side', 'top' | `null` | Position the legend must be displayed in. If it's not defined, it's calculated depending on the viewport width and the mode
`legendPosition` | One of: 'bottom', 'side', 'top', 'hidden' | `null` | Position the legend must be displayed in. If it's not defined, it's calculated depending on the viewport width and the mode
`legendTotals` | Object | `null` | Values to overwrite the legend totals. If not defined, the sum of all line values will be used
`screenReaderFormat` | One of type: string, func | `'%B %-d, %Y'` | A datetime formatting string or overriding function to format the screen reader labels
`showHeaderControls` | Boolean | `true` | Wether header UI controls must be displayed

View File

@ -334,18 +334,19 @@ class Chart extends Component {
const chartDirection = legendPosition === 'side' ? 'row' : 'column';
const chartHeight = this.getChartHeight();
const legend = isRequesting ? null : (
<D3Legend
colorScheme={ d3InterpolateViridis }
data={ orderedKeys }
handleLegendHover={ this.handleLegendHover }
handleLegendToggle={ this.handleLegendToggle }
interactive={ interactiveLegend }
legendDirection={ legendDirection }
legendValueFormat={ tooltipValueFormat }
totalLabel={ sprintf( itemsLabel, orderedKeys.length ) }
/>
);
const legend =
legendPosition !== 'hidden' && isRequesting ? null : (
<D3Legend
colorScheme={ d3InterpolateViridis }
data={ orderedKeys }
handleLegendHover={ this.handleLegendHover }
handleLegendToggle={ this.handleLegendToggle }
interactive={ interactiveLegend }
legendDirection={ legendDirection }
legendValueFormat={ tooltipValueFormat }
totalLabel={ sprintf( itemsLabel, orderedKeys.length ) }
/>
);
const margin = {
bottom: 50,
left: 80,
@ -566,7 +567,7 @@ Chart.propTypes = {
* Position the legend must be displayed in. If it's not defined, it's calculated
* depending on the viewport width and the mode.
*/
legendPosition: PropTypes.oneOf( [ 'bottom', 'side', 'top' ] ),
legendPosition: PropTypes.oneOf( [ 'bottom', 'side', 'top', 'hidden' ] ),
/**
* Values to overwrite the legend totals. If not defined, the sum of all line values will be used.
*/

View File

@ -1,7 +1,12 @@
/**
* External dependencies
*/
import { Chart } from '@woocommerce/components';
import { select } from '@storybook/addon-knobs';
/**
* Internal dependencies
*/
import Chart from '../';
const data = [
{
@ -66,8 +71,18 @@ const data = [
},
];
export default () => (
<div>
<Chart data={ data } title="Example Chart" layout="item-comparison" />
</div>
export default {
title: 'WooCommerce Admin/components/Chart',
component: Chart,
};
export const Default = () => (
<Chart
data={ data }
legendPosition={ select(
'Legend Position',
[ undefined, 'bottom', 'side', 'top', 'hidden' ],
undefined
) }
/>
);

View File

@ -0,0 +1,87 @@
/**
* @jest-environment jsdom
*/
/**
* External dependencies
*/
import { render, within } from '@testing-library/react';
import { createElement } from '@wordpress/element';
/**
* Internal dependencies
*/
import Chart from '../';
jest.mock( '../d3chart', () => ( {
D3Legend: jest.fn().mockReturnValue( '[D3Legend]' ),
} ) );
const data = [
{
date: '2018-05-30T00:00:00',
Hoodie: {
label: 'Hoodie',
value: 21599,
},
Sunglasses: {
label: 'Sunglasses',
value: 38537,
},
Cap: {
label: 'Cap',
value: 106010,
},
},
{
date: '2018-05-31T00:00:00',
Hoodie: {
label: 'Hoodie',
value: 14205,
},
Sunglasses: {
label: 'Sunglasses',
value: 24721,
},
Cap: {
label: 'Cap',
value: 70131,
},
},
];
describe( 'Chart', () => {
test( '<Chart legendPosition="hidden" /> should not render any legend', () => {
const { queryByText } = render(
<Chart data={ data } legendPosition="hidden" />
);
expect( queryByText( '[D3Legend]' ) ).not.toBeInTheDocument();
} );
test( '<Chart legendPosition="bottom" /> should render the legend at the bottom', () => {
const { container } = render(
<Chart data={ data } legendPosition="bottom" />
);
const footer = container.querySelector( '.woocommerce-chart__footer' );
expect(
within( footer ).queryByText( '[D3Legend]' )
).toBeInTheDocument();
} );
test( '<Chart legendPosition="side" /> should render the legend at the side', () => {
const { container } = render(
<Chart data={ data } legendPosition="side" />
);
const body = container.querySelector( '.woocommerce-chart__body' );
expect(
within( body ).queryByText( '[D3Legend]' )
).toBeInTheDocument();
} );
test( '<Chart legendPosition="top" /> should render the legend at the top', () => {
const { container } = render(
<Chart data={ data } legendPosition="top" />
);
const top = container.querySelector( '.woocommerce-chart__header' );
expect( within( top ).queryByText( '[D3Legend]' ) ).toBeInTheDocument();
} );
} );