Merge pull request woocommerce/woocommerce-admin#2134 from woocommerce/add/dashboard-section-toggle
Dashboard: Section add, remove, move up, and move down
This commit is contained in:
commit
b90f5ecb98
|
@ -0,0 +1,66 @@
|
|||
/** @format */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Icon } from '@wordpress/components';
|
||||
import { Component } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { MenuItem } from '@woocommerce/components';
|
||||
import './style.scss';
|
||||
|
||||
class SectionControls extends Component {
|
||||
constructor( props ) {
|
||||
super( props );
|
||||
this.onMoveUp = this.onMoveUp.bind( this );
|
||||
this.onMoveDown = this.onMoveDown.bind( this );
|
||||
}
|
||||
|
||||
onMoveUp() {
|
||||
const { onMove, onToggle } = this.props;
|
||||
onMove( -1 );
|
||||
// Close the dropdown
|
||||
onToggle();
|
||||
}
|
||||
|
||||
onMoveDown() {
|
||||
const { onMove, onToggle } = this.props;
|
||||
onMove( 1 );
|
||||
// Close the dropdown
|
||||
onToggle();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { onRemove, isFirst, isLast } = this.props;
|
||||
|
||||
if ( ! window.wcAdminFeatures[ 'dashboard/customizable' ] ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="woocommerce-section-controls">
|
||||
{ ! isFirst && (
|
||||
<MenuItem isClickable onInvoke={ this.onMoveUp }>
|
||||
<Icon icon={ 'arrow-up-alt2' } label={ __( 'Move up' ) } />
|
||||
{ __( 'Move up', 'woocommerce-admin' ) }
|
||||
</MenuItem>
|
||||
) }
|
||||
{ ! isLast && (
|
||||
<MenuItem isClickable onInvoke={ this.onMoveDown }>
|
||||
<Icon icon={ 'arrow-down-alt2' } label={ __( 'Move Down' ) } />
|
||||
{ __( 'Move Down', 'woocommerce-admin' ) }
|
||||
</MenuItem>
|
||||
) }
|
||||
<MenuItem isClickable onInvoke={ onRemove }>
|
||||
<Icon icon={ 'trash' } label={ __( 'Remove block' ) } />
|
||||
{ __( 'Remove section', 'woocommerce-admin' ) }
|
||||
</MenuItem>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SectionControls;
|
|
@ -0,0 +1,14 @@
|
|||
/** @format */
|
||||
|
||||
.woocommerce-section-controls {
|
||||
border-top: $border-width solid $core-grey-light-500;
|
||||
|
||||
.dashicon {
|
||||
margin: 0 $gap-smaller 0 0;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.woocommerce-ellipsis-menu__item {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
}
|
|
@ -2,9 +2,11 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { Component, Fragment } from '@wordpress/element';
|
||||
import { applyFilters } from '@wordpress/hooks';
|
||||
import { partial } from 'lodash';
|
||||
import { IconButton, Icon, Dropdown, Button } from '@wordpress/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -16,7 +18,6 @@ import Section from './section';
|
|||
import { ReportFilters, H } from '@woocommerce/components';
|
||||
import StorePerformance from './store-performance';
|
||||
|
||||
// @todo Replace dashboard-charts, leaderboards, and store-performance sections as neccessary with customizable equivalents.
|
||||
export default class CustomizableDashboard extends Component {
|
||||
constructor( props ) {
|
||||
super( props );
|
||||
|
@ -25,20 +26,28 @@ export default class CustomizableDashboard extends Component {
|
|||
{
|
||||
key: 'store-performance',
|
||||
component: StorePerformance,
|
||||
title: __( 'Store Performance', 'woocommerce-admin' ),
|
||||
title: __( 'Performance', 'woocommerce-admin' ),
|
||||
isVisible: true,
|
||||
icon: 'arrow-right-alt',
|
||||
},
|
||||
{
|
||||
key: 'charts',
|
||||
component: DashboardCharts,
|
||||
title: __( 'Charts', 'woocommerce-admin' ),
|
||||
isVisible: true,
|
||||
icon: 'chart-bar',
|
||||
},
|
||||
{
|
||||
key: 'leaderboards',
|
||||
component: Leaderboards,
|
||||
title: __( 'Leaderboards', 'woocommerce-admin' ),
|
||||
isVisible: true,
|
||||
icon: 'editor-ol',
|
||||
},
|
||||
] ),
|
||||
};
|
||||
|
||||
this.onMove = this.onMove.bind( this );
|
||||
}
|
||||
|
||||
onSectionTitleUpdate( updatedKey ) {
|
||||
|
@ -57,15 +66,89 @@ export default class CustomizableDashboard extends Component {
|
|||
};
|
||||
}
|
||||
|
||||
toggleVisibility( key, onToggle ) {
|
||||
return () => {
|
||||
if ( onToggle ) {
|
||||
// Close the dropdown before setting state so an action is not performed on an unmounted component.
|
||||
onToggle();
|
||||
}
|
||||
this.setState( state => {
|
||||
// When toggling visibility, place section at the end of the array.
|
||||
const sections = [ ...state.sections ];
|
||||
const index = sections.findIndex( s => key === s.key );
|
||||
const toggledSection = sections.splice( index, 1 ).shift();
|
||||
toggledSection.isVisible = ! toggledSection.isVisible;
|
||||
sections.push( toggledSection );
|
||||
|
||||
return { sections };
|
||||
} );
|
||||
};
|
||||
}
|
||||
|
||||
onMove( index, change ) {
|
||||
const sections = [ ...this.state.sections ];
|
||||
const movedSection = sections.splice( index, 1 ).shift();
|
||||
sections.splice( index + change, 0, movedSection );
|
||||
|
||||
this.setState( { sections } );
|
||||
}
|
||||
|
||||
renderAddMore() {
|
||||
const { sections } = this.state;
|
||||
const hiddenSections = sections.filter( section => false === section.isVisible );
|
||||
|
||||
if ( 0 === hiddenSections.length ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
position="top center"
|
||||
className="woocommerce-dashboard-section__add-more"
|
||||
renderToggle={ ( { onToggle, isOpen } ) => (
|
||||
<IconButton
|
||||
onClick={ onToggle }
|
||||
icon="plus-alt"
|
||||
title={ __( 'Add more sections', 'woocommerce-admin' ) }
|
||||
aria-expanded={ isOpen }
|
||||
/>
|
||||
) }
|
||||
renderContent={ ( { onToggle } ) => (
|
||||
<Fragment>
|
||||
<H>{ __( 'Dashboard Sections', 'woocommerce-admin' ) }</H>
|
||||
<div className="woocommerce-dashboard-section__add-more-choices">
|
||||
{ hiddenSections.map( section => {
|
||||
return (
|
||||
<Button
|
||||
key={ section.key }
|
||||
onClick={ this.toggleVisibility( section.key, onToggle ) }
|
||||
className="woocommerce-dashboard-section__add-more-btn"
|
||||
title={ sprintf( __( 'Add %s section', 'woocommerce-admin' ), section.title ) }
|
||||
>
|
||||
<Icon icon={ section.icon } size={ 30 } />
|
||||
<span className="woocommerce-dashboard-section__add-more-btn-title">
|
||||
{ section.title }
|
||||
</span>
|
||||
</Button>
|
||||
);
|
||||
} ) }
|
||||
</div>
|
||||
</Fragment>
|
||||
) }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { query, path } = this.props;
|
||||
const { sections } = this.state;
|
||||
const visibleSections = sections.filter( section => section.isVisible );
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<H>{ __( 'Customizable Dashboard', 'woocommerce-admin' ) }</H>
|
||||
<ReportFilters query={ query } path={ path } />
|
||||
{ sections.map( section => {
|
||||
{ visibleSections.map( ( section, index ) => {
|
||||
return (
|
||||
<Section
|
||||
component={ section.component }
|
||||
|
@ -74,9 +157,14 @@ export default class CustomizableDashboard extends Component {
|
|||
path={ path }
|
||||
query={ query }
|
||||
title={ section.title }
|
||||
onMove={ partial( this.onMove, index ) }
|
||||
onRemove={ this.toggleVisibility( section.key ) }
|
||||
isFirst={ 0 === index }
|
||||
isLast={ visibleSections.length === index + 1 }
|
||||
/>
|
||||
);
|
||||
} ) }
|
||||
{ this.renderAddMore() }
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import ChartBlock from './block';
|
|||
import { getChartFromKey, uniqCharts } from './config';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import './style.scss';
|
||||
import SectionControls from 'dashboard/components/section-controls';
|
||||
|
||||
class DashboardCharts extends Component {
|
||||
constructor( props ) {
|
||||
|
@ -74,39 +75,57 @@ class DashboardCharts extends Component {
|
|||
}
|
||||
|
||||
renderMenu() {
|
||||
const { onTitleBlur, onTitleChange, titleInput } = this.props;
|
||||
const {
|
||||
onTitleBlur,
|
||||
onTitleChange,
|
||||
titleInput,
|
||||
onMove,
|
||||
onRemove,
|
||||
isFirst,
|
||||
isLast,
|
||||
} = this.props;
|
||||
const { hiddenChartKeys } = this.state;
|
||||
|
||||
return (
|
||||
<EllipsisMenu
|
||||
label={ __( 'Choose which charts to display and the section name', 'woocommerce-admin' ) }
|
||||
>
|
||||
{ window.wcAdminFeatures[ 'dashboard/customizable' ] && (
|
||||
<div className="woocommerce-ellipsis-menu__item">
|
||||
<TextControl
|
||||
label={ __( 'Section Title', 'woocommerce-admin' ) }
|
||||
onBlur={ onTitleBlur }
|
||||
onChange={ onTitleChange }
|
||||
required
|
||||
value={ titleInput }
|
||||
label={ __( 'Choose which charts to display', 'woocommerce-admin' ) }
|
||||
renderChildren={ ( { onToggle } ) => (
|
||||
<Fragment>
|
||||
{ window.wcAdminFeatures[ 'dashboard/customizable' ] && (
|
||||
<div className="woocommerce-ellipsis-menu__item">
|
||||
<TextControl
|
||||
label={ __( 'Section Title', 'woocommerce-admin' ) }
|
||||
onBlur={ onTitleBlur }
|
||||
onChange={ onTitleChange }
|
||||
required
|
||||
value={ titleInput }
|
||||
/>
|
||||
</div>
|
||||
) }
|
||||
<MenuTitle>{ __( 'Charts', 'woocommerce-admin' ) }</MenuTitle>
|
||||
{ uniqCharts.map( chart => {
|
||||
return (
|
||||
<MenuItem
|
||||
checked={ ! hiddenChartKeys.includes( chart.key ) }
|
||||
isCheckbox
|
||||
isClickable
|
||||
key={ chart.key }
|
||||
onInvoke={ this.toggle( chart.key ) }
|
||||
>
|
||||
{ __( `${ chart.label }`, 'woocommerce-admin' ) }
|
||||
</MenuItem>
|
||||
);
|
||||
} ) }
|
||||
<SectionControls
|
||||
onToggle={ onToggle }
|
||||
onMove={ onMove }
|
||||
onRemove={ onRemove }
|
||||
isFirst={ isFirst }
|
||||
isLast={ isLast }
|
||||
/>
|
||||
</div>
|
||||
</Fragment>
|
||||
) }
|
||||
<MenuTitle>{ __( 'Charts', 'woocommerce-admin' ) }</MenuTitle>
|
||||
{ uniqCharts.map( chart => {
|
||||
return (
|
||||
<MenuItem
|
||||
checked={ ! hiddenChartKeys.includes( chart.key ) }
|
||||
isCheckbox
|
||||
isClickable
|
||||
key={ chart.key }
|
||||
onInvoke={ this.toggle( chart.key ) }
|
||||
>
|
||||
{ __( `${ chart.label }`, 'woocommerce-admin' ) }
|
||||
</MenuItem>
|
||||
);
|
||||
} ) }
|
||||
</EllipsisMenu>
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import { EllipsisMenu, MenuItem, MenuTitle, SectionHeader } from '@woocommerce/c
|
|||
*/
|
||||
import Leaderboard from 'analytics/components/leaderboard';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import SectionControls from 'dashboard/components/section-controls';
|
||||
import './style.scss';
|
||||
|
||||
class Leaderboards extends Component {
|
||||
|
@ -54,7 +55,16 @@ class Leaderboards extends Component {
|
|||
};
|
||||
|
||||
renderMenu() {
|
||||
const { allLeaderboards, onTitleBlur, onTitleChange, titleInput } = this.props;
|
||||
const {
|
||||
allLeaderboards,
|
||||
onTitleBlur,
|
||||
onTitleChange,
|
||||
titleInput,
|
||||
onMove,
|
||||
onRemove,
|
||||
isFirst,
|
||||
isLast,
|
||||
} = this.props;
|
||||
const { hiddenLeaderboardKeys, rowsPerTable } = this.state;
|
||||
|
||||
return (
|
||||
|
@ -63,45 +73,53 @@ class Leaderboards extends Component {
|
|||
'Choose which leaderboards to display and other settings',
|
||||
'woocommerce-admin'
|
||||
) }
|
||||
>
|
||||
<Fragment>
|
||||
{ window.wcAdminFeatures[ 'dashboard/customizable' ] && (
|
||||
<div className="woocommerce-ellipsis-menu__item">
|
||||
<TextControl
|
||||
label={ __( 'Section Title', 'woocommerce-admin' ) }
|
||||
onBlur={ onTitleBlur }
|
||||
onChange={ onTitleChange }
|
||||
required
|
||||
value={ titleInput }
|
||||
/>
|
||||
</div>
|
||||
) }
|
||||
<MenuTitle>{ __( 'Leaderboards', 'woocommerce-admin' ) }</MenuTitle>
|
||||
{ allLeaderboards.map( leaderboard => {
|
||||
return (
|
||||
<MenuItem
|
||||
checked={ ! hiddenLeaderboardKeys.includes( leaderboard.id ) }
|
||||
isCheckbox
|
||||
isClickable
|
||||
key={ leaderboard.id }
|
||||
onInvoke={ this.toggle( leaderboard.id ) }
|
||||
>
|
||||
{ leaderboard.label }
|
||||
</MenuItem>
|
||||
);
|
||||
} ) }
|
||||
<SelectControl
|
||||
className="woocommerce-dashboard__dashboard-leaderboards__select"
|
||||
label={ <MenuTitle>{ __( 'Rows Per Table', 'woocommerce-admin' ) }</MenuTitle> }
|
||||
value={ rowsPerTable }
|
||||
options={ Array.from( { length: 20 }, ( v, key ) => ( {
|
||||
v: key + 1,
|
||||
label: key + 1,
|
||||
} ) ) }
|
||||
onChange={ this.setRowsPerTable }
|
||||
/>
|
||||
</Fragment>
|
||||
</EllipsisMenu>
|
||||
renderChildren={ ( { onToggle } ) => (
|
||||
<Fragment>
|
||||
{ window.wcAdminFeatures[ 'dashboard/customizable' ] && (
|
||||
<div className="woocommerce-ellipsis-menu__item">
|
||||
<TextControl
|
||||
label={ __( 'Section Title', 'woocommerce-admin' ) }
|
||||
onBlur={ onTitleBlur }
|
||||
onChange={ onTitleChange }
|
||||
required
|
||||
value={ titleInput }
|
||||
/>
|
||||
</div>
|
||||
) }
|
||||
<MenuTitle>{ __( 'Leaderboards', 'woocommerce-admin' ) }</MenuTitle>
|
||||
{ allLeaderboards.map( leaderboard => {
|
||||
return (
|
||||
<MenuItem
|
||||
checked={ ! hiddenLeaderboardKeys.includes( leaderboard.id ) }
|
||||
isCheckbox
|
||||
isClickable
|
||||
key={ leaderboard.id }
|
||||
onInvoke={ this.toggle( leaderboard.id ) }
|
||||
>
|
||||
{ leaderboard.label }
|
||||
</MenuItem>
|
||||
);
|
||||
} ) }
|
||||
<SelectControl
|
||||
className="woocommerce-dashboard__dashboard-leaderboards__select"
|
||||
label={ <MenuTitle>{ __( 'Rows Per Table', 'woocommerce-admin' ) }</MenuTitle> }
|
||||
value={ rowsPerTable }
|
||||
options={ Array.from( { length: 20 }, ( v, key ) => ( {
|
||||
v: key + 1,
|
||||
label: key + 1,
|
||||
} ) ) }
|
||||
onChange={ this.setRowsPerTable }
|
||||
/>
|
||||
<SectionControls
|
||||
onToggle={ onToggle }
|
||||
onMove={ onMove }
|
||||
onRemove={ onRemove }
|
||||
isFirst={ isFirst }
|
||||
isLast={ isLast }
|
||||
/>
|
||||
</Fragment>
|
||||
) }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import {
|
|||
SummaryNumber,
|
||||
} from '@woocommerce/components';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import SectionControls from 'dashboard/components/section-controls';
|
||||
import './style.scss';
|
||||
|
||||
class StorePerformance extends Component {
|
||||
|
@ -66,7 +67,16 @@ class StorePerformance extends Component {
|
|||
}
|
||||
|
||||
renderMenu() {
|
||||
const { indicators, onTitleBlur, onTitleChange, titleInput } = this.props;
|
||||
const {
|
||||
indicators,
|
||||
onTitleBlur,
|
||||
onTitleChange,
|
||||
titleInput,
|
||||
onMove,
|
||||
onRemove,
|
||||
isFirst,
|
||||
isLast,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<EllipsisMenu
|
||||
|
@ -74,34 +84,44 @@ class StorePerformance extends Component {
|
|||
'Choose which analytics to display and the section name',
|
||||
'woocommerce-admin'
|
||||
) }
|
||||
>
|
||||
{ window.wcAdminFeatures[ 'dashboard/customizable' ] && (
|
||||
<div className="woocommerce-ellipsis-menu__item">
|
||||
<TextControl
|
||||
label={ __( 'Section Title', 'woocommerce-admin' ) }
|
||||
onBlur={ onTitleBlur }
|
||||
onChange={ onTitleChange }
|
||||
required
|
||||
value={ titleInput }
|
||||
renderChildren={ ( { onToggle } ) => (
|
||||
<Fragment>
|
||||
{ window.wcAdminFeatures[ 'dashboard/customizable' ] && (
|
||||
<div className="woocommerce-ellipsis-menu__item">
|
||||
<TextControl
|
||||
label={ __( 'Section Title', 'woocommerce-admin' ) }
|
||||
onBlur={ onTitleBlur }
|
||||
onChange={ onTitleChange }
|
||||
required
|
||||
value={ titleInput }
|
||||
/>
|
||||
</div>
|
||||
) }
|
||||
<MenuTitle>{ __( 'Display Stats:', 'woocommerce-admin' ) }</MenuTitle>
|
||||
{ indicators.map( ( indicator, i ) => {
|
||||
const checked = ! this.state.hiddenIndicators.includes( indicator.stat );
|
||||
return (
|
||||
<MenuItem
|
||||
checked={ checked }
|
||||
isCheckbox
|
||||
isClickable
|
||||
key={ i }
|
||||
onInvoke={ this.toggle( indicator.stat ) }
|
||||
>
|
||||
{ sprintf( __( 'Show %s', 'woocommerce-admin' ), indicator.label ) }
|
||||
</MenuItem>
|
||||
);
|
||||
} ) }
|
||||
<SectionControls
|
||||
onToggle={ onToggle }
|
||||
onMove={ onMove }
|
||||
onRemove={ onRemove }
|
||||
isFirst={ isFirst }
|
||||
isLast={ isLast }
|
||||
/>
|
||||
</div>
|
||||
</Fragment>
|
||||
) }
|
||||
<MenuTitle>{ __( 'Display Stats:', 'woocommerce-admin' ) }</MenuTitle>
|
||||
{ indicators.map( ( indicator, i ) => {
|
||||
const checked = ! this.state.hiddenIndicators.includes( indicator.stat );
|
||||
return (
|
||||
<MenuItem
|
||||
checked={ checked }
|
||||
isCheckbox
|
||||
isClickable
|
||||
key={ i }
|
||||
onInvoke={ this.toggle( indicator.stat ) }
|
||||
>
|
||||
{ sprintf( __( 'Show %s', 'woocommerce-admin' ), indicator.label ) }
|
||||
</MenuItem>
|
||||
);
|
||||
} ) }
|
||||
</EllipsisMenu>
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,3 +28,35 @@
|
|||
.woocommerce-dashboard__widget-item {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.woocommerce-dashboard-section__add-more {
|
||||
margin: 0 auto;
|
||||
width: 84px;
|
||||
padding: $gap-large;
|
||||
|
||||
.components-popover__content {
|
||||
padding: 0 $gap $gap-smaller;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-dashboard-section__add-more-choices {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.woocommerce-dashboard-section__add-more-btn {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: $gap;
|
||||
margin: $gap-smaller;
|
||||
|
||||
.dashicons-arrow-right-alt {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-dashboard-section__add-more-btn-title {
|
||||
color: $core-grey-dark-300;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ import PropTypes from 'prop-types';
|
|||
*/
|
||||
class EllipsisMenu extends Component {
|
||||
render() {
|
||||
const { children, label } = this.props;
|
||||
if ( ! children ) {
|
||||
const { children, label, renderChildren } = this.props;
|
||||
if ( ! children && ! renderChildren ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,12 @@ class EllipsisMenu extends Component {
|
|||
);
|
||||
};
|
||||
|
||||
const renderContent = () => (
|
||||
<NavigableMenu className="woocommerce-ellipsis-menu__content">{ children }</NavigableMenu>
|
||||
// @todo Make all children rendered by render props so Dropdown args can be passed?
|
||||
const renderContent = renderContentArgs => (
|
||||
<NavigableMenu className="woocommerce-ellipsis-menu__content">
|
||||
{ children && children }
|
||||
{ renderChildren && renderChildren( renderContentArgs ) }
|
||||
</NavigableMenu>
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -59,6 +63,10 @@ EllipsisMenu.propTypes = {
|
|||
* A list of `MenuTitle`/`MenuItem` components
|
||||
*/
|
||||
children: PropTypes.node,
|
||||
/**
|
||||
* A list of `MenuTitle`/`MenuItem` components as a render prop. Arguments from Dropdown passed as function arguments.
|
||||
*/
|
||||
renderChildren: PropTypes.func,
|
||||
};
|
||||
|
||||
export default EllipsisMenu;
|
||||
|
|
Loading…
Reference in New Issue