@@ -33,8 +39,10 @@ export default class ProductsReport extends Component {
selectedChart={ getSelectedChart( query.chart, charts ) }
/>
);
diff --git a/plugins/woocommerce-admin/client/components/chart/legend.js b/plugins/woocommerce-admin/client/components/chart/legend.js
index 8db8e9248ec..feab9362b93 100644
--- a/plugins/woocommerce-admin/client/components/chart/legend.js
+++ b/plugins/woocommerce-admin/client/components/chart/legend.js
@@ -3,8 +3,9 @@
* External dependencies
*/
import classNames from 'classnames';
-import { Component } from '@wordpress/element';
+import { Component, createRef } from '@wordpress/element';
import PropTypes from 'prop-types';
+import { sprintf } from '@wordpress/i18n';
/**
* WooCommerce dependencies
@@ -14,7 +15,7 @@ import { formatCurrency } from '@woocommerce/currency';
/**
* Internal dependencies
*/
-import './style.scss';
+import './legend.scss';
import { getColor } from './utils';
function getFormatedTotal( total, valueType ) {
@@ -36,65 +37,108 @@ function getFormatedTotal( total, valueType ) {
* A legend specifically designed for the WooCommerce admin charts.
*/
class Legend extends Component {
+ constructor() {
+ super();
+
+ this.listRef = createRef();
+
+ this.state = {
+ isScrollable: false,
+ };
+ }
+
+ componentDidMount() {
+ this.updateListScroll();
+ window.addEventListener( 'resize', this.updateListScroll );
+ }
+
+ componentWillUnmount() {
+ window.removeEventListener( 'resize', this.updateListScroll );
+ }
+
+ updateListScroll = () => {
+ const list = this.listRef.current;
+ const scrolledToEnd = list.scrollHeight - list.scrollTop <= list.offsetHeight;
+ this.setState( {
+ isScrollable: ! scrolledToEnd,
+ } );
+ };
+
render() {
const {
colorScheme,
data,
handleLegendHover,
handleLegendToggle,
+ itemsLabel,
legendDirection,
valueType,
} = this.props;
+ const { isScrollable } = this.state;
const colorParams = {
orderedKeys: data,
colorScheme,
};
const numberOfRowsVisible = data.filter( row => row.visible ).length;
+ const showTotalLabel = legendDirection === 'column' && data.length > 5 && itemsLabel;
return (
-
- { data.map( row => (
- -
-
-
- ) ) }
-
+
+
+ ) ) }
+
+ { showTotalLabel && (
+ { sprintf( itemsLabel, data.length ) }
+ ) }
+
);
}
}
@@ -124,6 +168,11 @@ Legend.propTypes = {
* Display legend items as a `row` or `column` inside a flex-box.
*/
legendDirection: PropTypes.oneOf( [ 'row', 'column' ] ),
+ /**
+ * Label to describe the legend items. It will be displayed in the legend of
+ * comparison charts when there are many.
+ */
+ itemsLabel: PropTypes.string,
/**
* What type of data is to be displayed? Number, Average, String?
*/
diff --git a/plugins/woocommerce-admin/client/components/chart/legend.scss b/plugins/woocommerce-admin/client/components/chart/legend.scss
new file mode 100644
index 00000000000..469c4a2e076
--- /dev/null
+++ b/plugins/woocommerce-admin/client/components/chart/legend.scss
@@ -0,0 +1,212 @@
+/** @format */
+
+.woocommerce-legend {
+ &.has-total {
+ padding-bottom: 50px;
+ position: relative;
+ }
+
+ &.woocommerce-legend__direction-column {
+ border-right: 1px solid $core-grey-light-700;
+
+ .woocommerce-chart__footer & {
+ border-right: none;
+ }
+ }
+}
+
+.woocommerce-legend__list {
+ color: $black;
+ display: flex;
+ height: 100%;
+ margin: 0;
+
+ .woocommerce-legend__direction-column & {
+ flex-direction: column;
+ height: 300px;
+ min-width: 320px;
+ overflow: auto;
+
+ .woocommerce-chart__footer & {
+ border-top: 1px solid $core-grey-light-700;
+ height: 100%;
+ max-height: none;
+ min-height: none;
+ }
+ }
+
+ .has-total.woocommerce-legend__direction-column & {
+ .woocommerce-chart__footer & {
+ height: auto;
+ max-height: 220px;
+ min-height: none;
+ }
+ }
+
+ .woocommerce-legend__direction-row & {
+ flex-direction: row;
+ }
+}
+
+.woocommerce-legend__item {
+ & > button {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ background-color: $white;
+ color: $core-grey-dark-500;
+ display: inline-flex;
+ flex-direction: row;
+ flex-wrap: nowrap;
+ justify-content: space-between;
+ width: 100%;
+ border: none;
+ padding: 0;
+
+ .woocommerce-legend__item-container {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: nowrap;
+ justify-content: space-between;
+ position: relative;
+ padding: 3px 0 3px 24px;
+ cursor: pointer;
+ font-size: 13px;
+ user-select: none;
+ width: 100%;
+
+ &:hover {
+ input {
+ ~ .woocommerce-legend__item-checkmark {
+ background-color: $core-grey-light-200;
+ }
+ }
+ }
+
+ .woocommerce-legend__item-checkmark {
+ border: 1px solid $core-grey-light-900;
+ position: absolute;
+ top: 4px;
+ left: 0;
+ height: 16px;
+ width: 16px;
+ background-color: $white;
+
+ &::after {
+ content: '';
+ position: absolute;
+ display: none;
+ }
+
+ &.woocommerce-legend__item-checkmark-checked {
+ background-color: currentColor;
+ border-color: currentColor;
+
+ &::after {
+ display: block;
+ left: 5px;
+ top: 2px;
+ width: 3px;
+ height: 6px;
+ border: solid $white;
+ border-width: 0 2px 2px 0;
+ transform: rotate(45deg);
+ }
+ }
+ }
+
+ .woocommerce-legend__item-total {
+ font-weight: bold;
+ }
+ }
+
+ &:focus {
+ outline: none;
+
+ .woocommerce-legend__item-container {
+ .woocommerce-legend__item-checkmark {
+ outline: 2px solid $core-grey-light-900;
+ }
+ }
+ }
+
+ &:hover {
+ background-color: $core-grey-light-100;
+ }
+ }
+
+ .woocommerce-legend__direction-column & {
+ margin: 2px 0;
+ padding: 0;
+
+ & > button {
+ height: 32px;
+ padding: 0 17px;
+ }
+
+ &:first-child {
+ margin-top: $gap-small;
+ }
+
+ &:last-child::after {
+ content: '';
+ display: block;
+ height: $gap-small;
+ width: 100%;
+ }
+ }
+
+ .woocommerce-legend__direction-row & {
+ padding: 0;
+ margin: 0;
+
+ & > button {
+ padding: 0 17px;
+
+ .woocommerce-legend__item-container {
+ height: 50px;
+ align-items: center;
+
+ .woocommerce-legend__item-checkmark {
+ top: 17px;
+ }
+
+ .woocommerce-legend__item-title {
+ margin-right: 17px;
+ }
+ }
+ }
+ }
+}
+
+.woocommerce-legend__total {
+ align-items: center;
+ background: $white;
+ border-top: 1px solid $core-grey-light-700;
+ bottom: 0;
+ color: $core-grey-dark-500;
+ display: flex;
+ height: 50px;
+ justify-content: center;
+ left: 0;
+ position: absolute;
+ right: 0;
+ text-transform: uppercase;
+
+ &::before {
+ background: linear-gradient(180deg, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.2));
+ bottom: 100%;
+ content: '';
+ height: 20px;
+ left: 0;
+ opacity: 0;
+ pointer-events: none;
+ position: absolute;
+ right: 0;
+ transition: opacity 0.3s;
+ }
+
+ .is-scrollable &::before {
+ opacity: 1;
+ }
+}
diff --git a/plugins/woocommerce-admin/client/components/chart/style.scss b/plugins/woocommerce-admin/client/components/chart/style.scss
index ad1919bd3fc..2856bb47ca6 100644
--- a/plugins/woocommerce-admin/client/components/chart/style.scss
+++ b/plugins/woocommerce-admin/client/components/chart/style.scss
@@ -61,15 +61,6 @@
.woocommerce-chart__footer {
width: 100%;
-
- .woocommerce-legend {
- &.woocommerce-legend__direction-column {
- height: 100%;
- min-height: none;
- border-right: none;
- margin-bottom: $gap;
- }
- }
}
svg {
@@ -252,146 +243,3 @@
position: absolute;
}
}
-
-.woocommerce-legend {
- color: $black;
- display: flex;
- height: 100%;
- margin: 0;
-
- &.woocommerce-legend__direction-column {
- flex-direction: column;
- border-right: 1px solid $core-grey-light-700;
- height: 300px;
- min-width: 320px;
-
- li {
- margin: 0;
- padding: 0;
-
- button {
- height: 32px;
- padding: 0 17px;
- }
-
- &:first-child {
- margin-top: 17px;
- }
- }
- }
-
- &.woocommerce-legend__direction-row {
- flex-direction: row;
-
- li {
- padding: 0;
- margin: 0;
-
- button {
- padding: 0 17px;
-
- .woocommerce-legend__item-container {
- height: 50px;
- align-items: center;
-
- .woocommerce-legend__item-checkmark {
- top: 17px;
- }
-
- .woocommerce-legend__item-title {
- margin-right: 17px;
- }
- }
- }
- }
- }
-
- li {
- &.woocommerce-legend__item {
- button {
- &:hover {
- background-color: $core-grey-light-100;
- }
- }
- }
-
- button {
- background-color: $white;
- color: $core-grey-dark-500;
- display: inline-flex;
- flex-direction: row;
- flex-wrap: nowrap;
- justify-content: space-between;
- width: 100%;
- border: none;
- padding: 0;
-
- .woocommerce-legend__item-container {
- display: flex;
- flex-direction: row;
- flex-wrap: nowrap;
- justify-content: space-between;
- position: relative;
- padding: 3px 0 3px 24px;
- cursor: pointer;
- font-size: 13px;
- user-select: none;
- width: 100%;
-
- &:hover {
- input {
- ~ .woocommerce-legend__item-checkmark {
- background-color: $core-grey-light-200;
- }
- }
- }
-
- .woocommerce-legend__item-checkmark {
- border: 1px solid $core-grey-light-900;
- position: absolute;
- top: 2px;
- left: 0;
- height: 16px;
- width: 16px;
- background-color: $white;
-
- &::after {
- content: '';
- position: absolute;
- display: none;
- }
-
- &.woocommerce-legend__item-checkmark-checked {
- background-color: currentColor;
- border-color: currentColor;
-
- &::after {
- display: block;
- left: 5px;
- top: 2px;
- width: 3px;
- height: 6px;
- border: solid $white;
- border-width: 0 2px 2px 0;
- transform: rotate(45deg);
- }
- }
- }
-
- .woocommerce-legend__item-total {
- font-weight: bold;
- }
- }
-
- &:focus {
- outline: none;
-
- .woocommerce-legend__item-container {
- .woocommerce-legend__item-checkmark {
- outline: 2px solid $core-grey-light-900;
- }
- }
- }
- }
- }
-}
diff --git a/plugins/woocommerce-admin/client/components/chart/test/legend.js b/plugins/woocommerce-admin/client/components/chart/test/legend.js
index 9be1db292ac..e072fd0dfc6 100644
--- a/plugins/woocommerce-admin/client/components/chart/test/legend.js
+++ b/plugins/woocommerce-admin/client/components/chart/test/legend.js
@@ -3,7 +3,7 @@
*
* @format
*/
-import { shallow } from 'enzyme';
+import { mount } from 'enzyme';
/**
* Internal dependencies
@@ -26,7 +26,7 @@ const data = [
describe( 'Legend', () => {
test( 'should not disable any button if more than one is active', () => {
- const topSellingProducts = shallow( );
+ const topSellingProducts = mount( );
expect( topSellingProducts.find( 'button' ).get( 0 ).props.disabled ).toBeFalsy();
expect( topSellingProducts.find( 'button' ).get( 1 ).props.disabled ).toBeFalsy();
@@ -35,7 +35,7 @@ describe( 'Legend', () => {
test( 'should disable the last active button', () => {
data[ 1 ].visible = false;
- const topSellingProducts = shallow( );
+ const topSellingProducts = mount( );
expect( topSellingProducts.find( 'button' ).get( 0 ).props.disabled ).toBeTruthy();
expect( topSellingProducts.find( 'button' ).get( 1 ).props.disabled ).toBeFalsy();