Merge pull request woocommerce/woocommerce-admin#1332 from woocommerce/fix/summary-number-close-on-mobile
SummaryNumbers: close on click for mobile
This commit is contained in:
commit
a52fab85de
|
@ -42,33 +42,35 @@ export class ReportSummary extends Component {
|
|||
const secondaryTotals = totals.secondary || {};
|
||||
const { compare } = getDateParamsFromQuery( query );
|
||||
|
||||
const summaryNumbers = charts.map( chart => {
|
||||
const { key, label, type } = chart;
|
||||
const delta = calculateDelta( primaryTotals[ key ], secondaryTotals[ key ] );
|
||||
const href = getNewPath( { chart: key } );
|
||||
const prevValue = formatValue( type, secondaryTotals[ key ] );
|
||||
const isSelected = selectedChart.key === key;
|
||||
const value = formatValue( type, primaryTotals[ key ] );
|
||||
const renderSummaryNumbers = ( { onToggle } ) =>
|
||||
charts.map( chart => {
|
||||
const { key, label, type } = chart;
|
||||
const delta = calculateDelta( primaryTotals[ key ], secondaryTotals[ key ] );
|
||||
const href = getNewPath( { chart: key } );
|
||||
const prevValue = formatValue( type, secondaryTotals[ key ] );
|
||||
const isSelected = selectedChart.key === key;
|
||||
const value = formatValue( type, primaryTotals[ key ] );
|
||||
|
||||
return (
|
||||
<SummaryNumber
|
||||
key={ key }
|
||||
delta={ delta }
|
||||
href={ href }
|
||||
label={ label }
|
||||
prevLabel={
|
||||
'previous_period' === compare
|
||||
? __( 'Previous Period:', 'wc-admin' )
|
||||
: __( 'Previous Year:', 'wc-admin' )
|
||||
}
|
||||
prevValue={ prevValue }
|
||||
selected={ isSelected }
|
||||
value={ value }
|
||||
/>
|
||||
);
|
||||
} );
|
||||
return (
|
||||
<SummaryNumber
|
||||
key={ key }
|
||||
delta={ delta }
|
||||
href={ href }
|
||||
label={ label }
|
||||
prevLabel={
|
||||
'previous_period' === compare
|
||||
? __( 'Previous Period:', 'wc-admin' )
|
||||
: __( 'Previous Year:', 'wc-admin' )
|
||||
}
|
||||
prevValue={ prevValue }
|
||||
selected={ isSelected }
|
||||
value={ value }
|
||||
onLinkClickCallback={ onToggle }
|
||||
/>
|
||||
);
|
||||
} );
|
||||
|
||||
return <SummaryList>{ summaryNumbers }</SummaryList>;
|
||||
return <SummaryList>{ renderSummaryNumbers }</SummaryList>;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -112,37 +112,39 @@ class StorePerformance extends Component {
|
|||
: __( 'Previous Year:', 'wc-admin' );
|
||||
return (
|
||||
<SummaryList>
|
||||
{ userIndicators.map( ( indicator, i ) => {
|
||||
const primaryItem = find( primaryData.data, data => data.stat === indicator.stat );
|
||||
const secondaryItem = find( secondaryData.data, data => data.stat === indicator.stat );
|
||||
{ () =>
|
||||
userIndicators.map( ( indicator, i ) => {
|
||||
const primaryItem = find( primaryData.data, data => data.stat === indicator.stat );
|
||||
const secondaryItem = find( secondaryData.data, data => data.stat === indicator.stat );
|
||||
|
||||
if ( ! primaryItem || ! secondaryItem ) {
|
||||
return null;
|
||||
}
|
||||
if ( ! primaryItem || ! secondaryItem ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const href =
|
||||
( primaryItem._links &&
|
||||
primaryItem._links.report[ 0 ] &&
|
||||
primaryItem._links.report[ 0 ].href ) ||
|
||||
'';
|
||||
const reportUrl =
|
||||
( href && getNewPath( persistedQuery, href, { chart: primaryItem.chart } ) ) || '';
|
||||
const delta = calculateDelta( primaryItem.value, secondaryItem.value );
|
||||
const primaryValue = formatValue( primaryItem.format, primaryItem.value );
|
||||
const secondaryValue = formatValue( secondaryItem.format, secondaryItem.value );
|
||||
const href =
|
||||
( primaryItem._links &&
|
||||
primaryItem._links.report[ 0 ] &&
|
||||
primaryItem._links.report[ 0 ].href ) ||
|
||||
'';
|
||||
const reportUrl =
|
||||
( href && getNewPath( persistedQuery, href, { chart: primaryItem.chart } ) ) || '';
|
||||
const delta = calculateDelta( primaryItem.value, secondaryItem.value );
|
||||
const primaryValue = formatValue( primaryItem.format, primaryItem.value );
|
||||
const secondaryValue = formatValue( secondaryItem.format, secondaryItem.value );
|
||||
|
||||
return (
|
||||
<SummaryNumber
|
||||
key={ i }
|
||||
href={ reportUrl }
|
||||
label={ indicator.label }
|
||||
value={ primaryValue }
|
||||
prevLabel={ prevLabel }
|
||||
prevValue={ secondaryValue }
|
||||
delta={ delta }
|
||||
/>
|
||||
);
|
||||
} ) }
|
||||
return (
|
||||
<SummaryNumber
|
||||
key={ i }
|
||||
href={ reportUrl }
|
||||
label={ indicator.label }
|
||||
value={ primaryValue }
|
||||
prevLabel={ prevLabel }
|
||||
prevValue={ secondaryValue }
|
||||
delta={ delta }
|
||||
/>
|
||||
);
|
||||
} )
|
||||
}
|
||||
</SummaryList>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,13 +3,16 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import classnames from 'classnames';
|
||||
import { Children, cloneElement } from '@wordpress/element';
|
||||
import { Dropdown, NavigableMenu } from '@wordpress/components';
|
||||
import { Dropdown } from '@wordpress/components';
|
||||
import PropTypes from 'prop-types';
|
||||
import { uniqueId } from 'lodash';
|
||||
import { withViewportMatch } from '@wordpress/viewport';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import Menu from './menu';
|
||||
|
||||
/**
|
||||
* A container element for a list of SummaryNumbers. This component handles detecting & switching to
|
||||
* the mobile format on smaller screens.
|
||||
|
@ -17,45 +20,27 @@ import { withViewportMatch } from '@wordpress/viewport';
|
|||
* @return { object } -
|
||||
*/
|
||||
const SummaryList = ( { children, isDropdownBreakpoint, label } ) => {
|
||||
if ( ! label ) {
|
||||
label = __( 'Performance Indicators', 'wc-admin' );
|
||||
}
|
||||
|
||||
const items = children( {} );
|
||||
// We default to "one" because we can't have empty children.
|
||||
const itemCount = Children.count( children ) || 1;
|
||||
const hasItemsClass = itemCount < 10 ? `has-${ itemCount }-items` : 'has-10-items';
|
||||
const classes = classnames( 'woocommerce-summary', {
|
||||
[ hasItemsClass ]: ! isDropdownBreakpoint,
|
||||
} );
|
||||
|
||||
const instanceId = uniqueId( 'woocommerce-summary-helptext-' );
|
||||
const menu = (
|
||||
<NavigableMenu
|
||||
aria-label={ label }
|
||||
aria-describedby={ instanceId }
|
||||
orientation={ isDropdownBreakpoint ? 'vertical' : 'horizontal' }
|
||||
stopNavigationEvents
|
||||
>
|
||||
<p id={ instanceId } className="screen-reader-text">
|
||||
{ __(
|
||||
'List of data points available for filtering. Use arrow keys to cycle through ' +
|
||||
'the list. Click a data point for a detailed report.',
|
||||
'wc-admin'
|
||||
) }
|
||||
</p>
|
||||
<ul className={ classes }>{ children }</ul>
|
||||
</NavigableMenu>
|
||||
const itemCount = Children.count( items ) || 1;
|
||||
const orientation = isDropdownBreakpoint ? 'vertical' : 'horizontal';
|
||||
const summaryMenu = (
|
||||
<Menu
|
||||
label={ label }
|
||||
orientation={ orientation }
|
||||
itemCount={ itemCount }
|
||||
items={ items }
|
||||
/>
|
||||
);
|
||||
|
||||
// On large screens, or if there are not multiple SummaryNumbers, we'll display the plain list.
|
||||
if ( ! isDropdownBreakpoint || itemCount < 2 ) {
|
||||
return menu;
|
||||
return summaryMenu;
|
||||
}
|
||||
|
||||
const items = Children.toArray( children );
|
||||
const selected = items.find( item => !! item.props.selected );
|
||||
if ( ! selected ) {
|
||||
return menu;
|
||||
return summaryMenu;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -64,22 +49,33 @@ const SummaryList = ( { children, isDropdownBreakpoint, label } ) => {
|
|||
position="bottom"
|
||||
headerTitle={ label }
|
||||
renderToggle={ ( { isOpen, onToggle } ) => cloneElement( selected, { onToggle, isOpen } ) }
|
||||
renderContent={ () => menu }
|
||||
renderContent={ renderContentArgs => (
|
||||
<Menu
|
||||
label={ label }
|
||||
orientation={ orientation }
|
||||
itemCount={ itemCount }
|
||||
items={ children( renderContentArgs ) }
|
||||
/>
|
||||
) }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
SummaryList.propTypes = {
|
||||
/**
|
||||
* A list of `<SummaryNumber />`s
|
||||
* A function returning a list of `<SummaryNumber />`s
|
||||
*/
|
||||
children: PropTypes.node.isRequired,
|
||||
children: PropTypes.func.isRequired,
|
||||
/**
|
||||
* An optional label of this group, read to screen reader users. Defaults to "Performance Indicators".
|
||||
* An optional label of this group, read to screen reader users.
|
||||
*/
|
||||
label: PropTypes.string,
|
||||
};
|
||||
|
||||
SummaryList.defaultProps = {
|
||||
label: __( 'Performance Indicators', 'wc-admin' ),
|
||||
};
|
||||
|
||||
export default withViewportMatch( {
|
||||
isDropdownBreakpoint: '< large',
|
||||
} )( SummaryList );
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/** @format */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { NavigableMenu } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import classnames from 'classnames';
|
||||
import { uniqueId } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getHasItemsClass } from './utils';
|
||||
|
||||
const Menu = ( { label, orientation, itemCount, items } ) => {
|
||||
const instanceId = uniqueId( 'woocommerce-summary-helptext-' );
|
||||
const hasItemsClass = getHasItemsClass( itemCount );
|
||||
const classes = classnames( 'woocommerce-summary', {
|
||||
[ hasItemsClass ]: orientation === 'horizontal',
|
||||
} );
|
||||
|
||||
return (
|
||||
<NavigableMenu
|
||||
aria-label={ label }
|
||||
aria-describedby={ instanceId }
|
||||
orientation={ orientation }
|
||||
stopNavigationEvents
|
||||
>
|
||||
<p id={ instanceId } className="screen-reader-text">
|
||||
{ __(
|
||||
'List of data points available for filtering. Use arrow keys to cycle through ' +
|
||||
'the list. Click a data point for a detailed report.',
|
||||
'wc-admin'
|
||||
) }
|
||||
</p>
|
||||
<ul className={ classes }>
|
||||
{ items }
|
||||
</ul>
|
||||
</NavigableMenu>
|
||||
);
|
||||
};
|
||||
|
||||
Menu.propTypes = {
|
||||
/**
|
||||
* An optional label of this group, read to screen reader users.
|
||||
*/
|
||||
label: PropTypes.string,
|
||||
/**
|
||||
* Item layout orientation.
|
||||
*/
|
||||
orientation: PropTypes.oneOf( [ 'vertical', 'horizontal' ] ).isRequired,
|
||||
/**
|
||||
* A list of `<SummaryNumber />`s.
|
||||
*/
|
||||
items: PropTypes.node.isRequired,
|
||||
/**
|
||||
* Number of items.
|
||||
*/
|
||||
itemCount: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
export default Menu;
|
|
@ -6,7 +6,7 @@ import { __, sprintf } from '@wordpress/i18n';
|
|||
import { Button } from '@wordpress/components';
|
||||
import classnames from 'classnames';
|
||||
import Gridicon from 'gridicons';
|
||||
import { isNil } from 'lodash';
|
||||
import { isNil, noop } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
|
@ -30,6 +30,7 @@ const SummaryNumber = ( {
|
|||
reverseTrend,
|
||||
selected,
|
||||
value,
|
||||
onLinkClickCallback,
|
||||
} ) => {
|
||||
const liClasses = classnames( 'woocommerce-summary__item-container', {
|
||||
'is-dropdown-button': onToggle,
|
||||
|
@ -59,13 +60,15 @@ const SummaryNumber = ( {
|
|||
};
|
||||
|
||||
if ( onToggle || href ) {
|
||||
Container = onToggle ? Button : Link;
|
||||
if ( ! onToggle ) {
|
||||
containerProps.href = href;
|
||||
containerProps.role = 'menuitem';
|
||||
} else {
|
||||
const isButton = !! onToggle;
|
||||
Container = isButton ? Button : Link;
|
||||
if ( isButton ) {
|
||||
containerProps.onClick = onToggle;
|
||||
containerProps[ 'aria-expanded' ] = isOpen;
|
||||
} else {
|
||||
containerProps.href = href;
|
||||
containerProps.role = 'menuitem';
|
||||
containerProps.onClick = onLinkClickCallback;
|
||||
}
|
||||
} else {
|
||||
Container = 'div';
|
||||
|
@ -150,6 +153,10 @@ SummaryNumber.propTypes = {
|
|||
* A string or number value to display - a string is allowed so we can accept currency formatting.
|
||||
*/
|
||||
value: PropTypes.oneOfType( [ PropTypes.number, PropTypes.string ] ),
|
||||
/**
|
||||
* A function to be called after a SummaryNumber, rendered as a link, is clicked.
|
||||
*/
|
||||
onLinkClickCallback: PropTypes.func,
|
||||
};
|
||||
|
||||
SummaryNumber.defaultProps = {
|
||||
|
@ -158,6 +165,7 @@ SummaryNumber.defaultProps = {
|
|||
prevLabel: __( 'Previous Period:', 'wc-admin' ),
|
||||
reverseTrend: false,
|
||||
selected: false,
|
||||
onLinkClickCallback: noop,
|
||||
};
|
||||
|
||||
export default SummaryNumber;
|
||||
|
|
|
@ -8,6 +8,11 @@ import { range } from 'lodash';
|
|||
import PropTypes from 'prop-types';
|
||||
import { withViewportMatch } from '@wordpress/viewport';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getHasItemsClass } from './utils';
|
||||
|
||||
/**
|
||||
* `SummaryListPlaceholder` behaves like `SummaryList` but displays placeholder summary items instead of data.
|
||||
* This can be used while loading data.
|
||||
|
@ -17,7 +22,7 @@ class SummaryListPlaceholder extends Component {
|
|||
const { isDropdownBreakpoint } = this.props;
|
||||
const numberOfItems = isDropdownBreakpoint ? 1 : this.props.numberOfItems;
|
||||
|
||||
const hasItemsClass = numberOfItems < 10 ? `has-${ numberOfItems }-items` : 'has-10-items';
|
||||
const hasItemsClass = getHasItemsClass( numberOfItems );
|
||||
const classes = classnames( 'woocommerce-summary', {
|
||||
[ hasItemsClass ]: ! isDropdownBreakpoint,
|
||||
'is-placeholder': true,
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* Get a class name depending on item count.
|
||||
*
|
||||
* @param {number} count - Item count.
|
||||
* @returns {string} - class name.
|
||||
*/
|
||||
export function getHasItemsClass( count ) {
|
||||
return count < 10 ? `has-${ count }-items` : 'has-10-items';
|
||||
}
|
Loading…
Reference in New Issue