Try: Replace Accordion with Panel component (https://github.com/woocommerce/woocommerce-admin/pull/5970)
* Use Panel for Activity Panels * Update styling for panels in activity panels * Remove Accordion component * Add collapsible param to activity panel tests * Fix errant comma * Add bottom border to panel header toggle and remove disbled button styling * Update empty activity card styles * Add border between activity cards
This commit is contained in:
parent
f1d649a657
commit
0b3f4d8e92
|
@ -2,8 +2,14 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { useSelect } from '@wordpress/data';
|
||||
import { Fragment } from '@wordpress/element';
|
||||
import { Accordion, AccordionPanel } from '@woocommerce/components';
|
||||
import { Badge } from '@woocommerce/components';
|
||||
import {
|
||||
Button,
|
||||
Panel,
|
||||
PanelBody,
|
||||
PanelRow,
|
||||
__experimentalText as Text,
|
||||
} from '@wordpress/components';
|
||||
import { getSetting } from '@woocommerce/wc-admin-settings';
|
||||
|
||||
/**
|
||||
|
@ -48,32 +54,48 @@ export const ActivityPanel = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<Accordion>
|
||||
<Fragment>
|
||||
{ panels.map( ( panelData ) => {
|
||||
const {
|
||||
className,
|
||||
count,
|
||||
id,
|
||||
initialOpen,
|
||||
panel,
|
||||
title,
|
||||
collapsible,
|
||||
} = panelData;
|
||||
return (
|
||||
<AccordionPanel
|
||||
key={ id }
|
||||
className={ className }
|
||||
count={ count }
|
||||
initialOpen={ initialOpen }
|
||||
title={ title }
|
||||
collapsible={ collapsible }
|
||||
>
|
||||
{ panel }
|
||||
</AccordionPanel>
|
||||
);
|
||||
} ) }
|
||||
</Fragment>
|
||||
</Accordion>
|
||||
<Panel className="woocommerce-activity-panel">
|
||||
{ panels.map( ( panelData ) => {
|
||||
const {
|
||||
className,
|
||||
count,
|
||||
id,
|
||||
initialOpen,
|
||||
panel,
|
||||
title,
|
||||
collapsible,
|
||||
} = panelData;
|
||||
return collapsible ? (
|
||||
<PanelBody
|
||||
title={ [
|
||||
<Text key={ title } variant="title.small">
|
||||
{ title }
|
||||
</Text>,
|
||||
count !== null && <Badge count={ count } />,
|
||||
] }
|
||||
key={ id }
|
||||
className={ className }
|
||||
initialOpen={ initialOpen }
|
||||
collapsible={ collapsible }
|
||||
disabled={ ! collapsible }
|
||||
>
|
||||
<PanelRow>{ panel }</PanelRow>
|
||||
</PanelBody>
|
||||
) : (
|
||||
<div className="components-panel__body">
|
||||
<h2 className="components-panel__body-title">
|
||||
<Button
|
||||
className="components-panel__body-toggle"
|
||||
aria-expanded={ false }
|
||||
disabled={ true }
|
||||
>
|
||||
<Text variant="title.small">{ title }</Text>
|
||||
{ count !== null && <Badge count={ count } /> }
|
||||
</Button>
|
||||
</h2>
|
||||
</div>
|
||||
);
|
||||
} ) }
|
||||
</Panel>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
.woocommerce-accordion-card {
|
||||
.woocommerce-empty-activity-card {
|
||||
background: unset;
|
||||
text-align: center;
|
||||
padding: ( $fallback-gutter / 2 ) $gutter 0;
|
||||
h4 {
|
||||
color: $gray-900;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-activity-panel {
|
||||
.woocommerce-order-empty__success-icon {
|
||||
font-size: 36px;
|
||||
}
|
||||
|
|
|
@ -1,67 +1,70 @@
|
|||
@mixin accordion-header {
|
||||
.woocommerce-accordion-header {
|
||||
order: 1;
|
||||
text-align: left;
|
||||
.woocommerce-accordion-title {
|
||||
margin-right: $gap;
|
||||
}
|
||||
}
|
||||
}
|
||||
.woocommerce-accordion-card {
|
||||
.components-card__header,
|
||||
.components-panel__body-title .components-button {
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
color: $gray-900;
|
||||
&:focus {
|
||||
box-shadow: unset;
|
||||
outline: unset;
|
||||
.woocommerce-activity-panel {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
|
||||
.components-panel__body {
|
||||
background: #fff;
|
||||
border: 1px solid $gray-200;
|
||||
|
||||
&.is-opened {
|
||||
margin-bottom: $gap-large;
|
||||
|
||||
.components-panel__body-toggle {
|
||||
border-bottom: 1px solid $gray-200;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.components-card__header {
|
||||
height: 60px;
|
||||
@include accordion-header();
|
||||
&.components-panel > .components-panel__body:last-child {
|
||||
border-bottom: 1px solid $gray-200;
|
||||
}
|
||||
|
||||
.components-panel__body-title {
|
||||
margin: 0;
|
||||
padding: $gap-small 0;
|
||||
height: 60px;
|
||||
.components-button {
|
||||
.components-panel__row {
|
||||
margin: 0 -#{$gap} -#{$gap} -#{$gap};
|
||||
> div {
|
||||
width: 100%;
|
||||
padding-left: 24px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@include accordion-header();
|
||||
|
||||
.woocommerce-accordion-header {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
& > span {
|
||||
order: 2;
|
||||
width: 50%;
|
||||
text-align: right;
|
||||
.components-panel__arrow {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.components-panel__body-toggle {
|
||||
border-radius: 0;
|
||||
|
||||
&:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-activity-panel {
|
||||
margin-bottom: $gap-large;
|
||||
}
|
||||
|
||||
.components-panel__body-title p {
|
||||
margin-right: $gap;
|
||||
}
|
||||
|
||||
.woocommerce-activity-card {
|
||||
padding: $gap-largest/2 $gutter $gutter;
|
||||
|
||||
&:not(:last-of-type) {
|
||||
border-bottom: 1px solid $gray-200;
|
||||
}
|
||||
|
||||
&__header {
|
||||
margin-bottom: $gap-small;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-empty-activity-card {
|
||||
margin: 0;
|
||||
background: unset;
|
||||
text-align: center;
|
||||
padding: $gap-large $gutter $gap-smallest;
|
||||
|
||||
h4 {
|
||||
color: $gray-900;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-layout__activity-panel-outbound-link {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
@ -110,6 +113,7 @@
|
|||
|
||||
.woocommerce-layout__activity-panel-empty {
|
||||
border-top: 1px solid $gray-200;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.woocommerce-activity-card__button {
|
||||
|
@ -120,9 +124,3 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.components-panel__body-title {
|
||||
.woocommerce-accordion-card .is-opened & {
|
||||
border-bottom: 1px solid $gray-200;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ jest.mock( '../panels', () => {
|
|||
count: 10000,
|
||||
initialOpen: true,
|
||||
panel: <span>Custom panel 1</span>,
|
||||
collapsible: true,
|
||||
},
|
||||
{
|
||||
id: 'custom-panel-2',
|
||||
|
@ -25,6 +26,7 @@ jest.mock( '../panels', () => {
|
|||
count: 20000,
|
||||
initialOpen: false,
|
||||
panel: <span>Custom panel 2</span>,
|
||||
collapsible: true,
|
||||
},
|
||||
] ),
|
||||
};
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# Unreleased
|
||||
|
||||
- Change styling of `<ProductImage />`.
|
||||
- Add new `<Accordion>` component.
|
||||
- Remove the `showCount` prop from `<SearchListItem>`. Count will always be displayed if any of those props is not undefined/null: `countLabel` and `item.count`.
|
||||
- Fix alignment of `<SearchListItem>` count bubble in newest versions of `@wordpress/components`.
|
||||
- `<SearchListControl>` no longer has different styles when it's used inside a panel. Those styles are available now with the `isCompact` prop.
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
# Accordion
|
||||
|
||||
This is an accordion that renders the children inside. It will toggle the panel's content when the title is clicked.
|
||||
|
||||
## Usage
|
||||
|
||||
```jsx
|
||||
<Accordion>
|
||||
<AccordionPanel
|
||||
className="class-name"
|
||||
count={ 15 }
|
||||
title="Panel 1"
|
||||
initialOpen={ true }
|
||||
>
|
||||
<span>Panel 1 content</span>
|
||||
</AccordionPanel>
|
||||
<AccordionPanel
|
||||
className="class-name"
|
||||
count={ 20 }
|
||||
title="Panel 2"
|
||||
initialOpen={ false }
|
||||
>
|
||||
<span>Panel 2 content</span>
|
||||
</AccordionPanel>
|
||||
</Accordion>
|
||||
```
|
||||
|
||||
### Props
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| ----------- | ------ | ------- | ----------------------- |
|
||||
| `className` | String | `null` | Additional CSS classes. |
|
||||
|
||||
# AccordionPanel
|
||||
|
||||
A component designed for use inside of the `Accordion` component.
|
||||
`AccordionPanel` is used to give the panel content an accessible wrapper.
|
||||
|
||||
## Usage
|
||||
|
||||
```jsx
|
||||
<AccordionPanel
|
||||
className="class-name"
|
||||
count={ 15 }
|
||||
title="Panel 1"
|
||||
initialOpen={ true }
|
||||
>
|
||||
<span>Panel 1 content</span>
|
||||
</AccordionPanel>
|
||||
```
|
||||
|
||||
### Props
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| ------------- | ------- | ------- | ------------------------------------------------------------------------------------ |
|
||||
| `className` | Array | `null` | A list of objects with data to set the panels. |
|
||||
| `count` | Number | `null` | Number of unread elements in the panel that will be shown next to the panel's title. |
|
||||
| `initialOpen` | Boolean | `true` | Whether or not the panel will start open. |
|
||||
| `title` | String | `null` | The panel title. |
|
|
@ -1,31 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Panel } from '@wordpress/components';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
|
||||
/**
|
||||
* Use `Accordion` to display an accordion that renders the children inside.
|
||||
*
|
||||
* @param {Object} props
|
||||
* @param {string} props.children
|
||||
* @param {string} props.className
|
||||
* @return {Object} -
|
||||
*/
|
||||
const Accordion = ( { className, children } ) => {
|
||||
return (
|
||||
<Panel className={ classnames( className, 'woocommerce-accordion' ) }>
|
||||
{ children }
|
||||
</Panel>
|
||||
);
|
||||
};
|
||||
|
||||
Accordion.propTypes = {
|
||||
/**
|
||||
* Additional CSS classes.
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Accordion;
|
|
@ -1,111 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Card, CardHeader, PanelBody, PanelRow } from '@wordpress/components';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { useState, useEffect } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Badge } from '../badge';
|
||||
|
||||
/**
|
||||
* `AccordionPanel` is used to give the panel content an accessible wrapper.
|
||||
*
|
||||
* @param {Object} props
|
||||
* @param {string} props.className
|
||||
* @param {string} props.count
|
||||
* @param {string} props.children
|
||||
* @param {string} props.title
|
||||
* @param {string} props.initialOpen
|
||||
* @param {boolean} props.collapsible
|
||||
* @return {Object} -
|
||||
*/
|
||||
const AccordionPanel = ( {
|
||||
className,
|
||||
count,
|
||||
title,
|
||||
initialOpen,
|
||||
collapsible,
|
||||
children,
|
||||
} ) => {
|
||||
const [ isPanelOpen, setIsPanelOpen ] = useState( null );
|
||||
|
||||
useEffect( () => {
|
||||
if ( ! collapsible && isPanelOpen ) {
|
||||
setIsPanelOpen( ! isPanelOpen );
|
||||
}
|
||||
}, [ collapsible ] );
|
||||
|
||||
const getTitleAndCount = ( titleText, countUnread ) => {
|
||||
return (
|
||||
<span className="woocommerce-accordion-header">
|
||||
<span className="woocommerce-accordion-title">
|
||||
{ titleText }
|
||||
</span>
|
||||
{ countUnread !== null && <Badge count={ countUnread } /> }
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const opened = isPanelOpen === null ? initialOpen : isPanelOpen;
|
||||
|
||||
const onToggle = () => {
|
||||
setIsPanelOpen( ! opened );
|
||||
};
|
||||
|
||||
return (
|
||||
<Card
|
||||
size="large"
|
||||
className={ classnames( className, 'woocommerce-accordion-card', {
|
||||
'is-panel-opened': opened,
|
||||
} ) }
|
||||
>
|
||||
{ collapsible ? (
|
||||
<PanelBody
|
||||
title={ getTitleAndCount( title, count ) }
|
||||
initialOpen={ opened }
|
||||
onToggle={ onToggle }
|
||||
>
|
||||
<PanelRow> { children } </PanelRow>
|
||||
</PanelBody>
|
||||
) : (
|
||||
<CardHeader size="medium">
|
||||
{ getTitleAndCount( title, count ) }
|
||||
</CardHeader>
|
||||
) }
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
AccordionPanel.propTypes = {
|
||||
/**
|
||||
* Additional CSS classes.
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
/**
|
||||
* Number of unread elements in the panel that will be shown next to the panel's title.
|
||||
*/
|
||||
count: PropTypes.number,
|
||||
/**
|
||||
* The panel title.
|
||||
*/
|
||||
title: PropTypes.string,
|
||||
/**
|
||||
* Whether or not the panel will start open.
|
||||
*/
|
||||
initialOpen: PropTypes.bool,
|
||||
/**
|
||||
* Whether or not the panel can be collapsed or not.
|
||||
*/
|
||||
collapsible: PropTypes.bool,
|
||||
};
|
||||
|
||||
AccordionPanel.defaultProps = {
|
||||
initialOpen: true,
|
||||
collapsible: true,
|
||||
};
|
||||
|
||||
export default AccordionPanel;
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Accordion, AccordionPanel } from '@woocommerce/components';
|
||||
|
||||
export const Basic = () => (
|
||||
<Accordion>
|
||||
<AccordionPanel
|
||||
className="class-name"
|
||||
count={ 15 }
|
||||
title="Panel 1"
|
||||
initialOpen={ true }
|
||||
>
|
||||
<span>Panel 1 content</span>
|
||||
</AccordionPanel>
|
||||
<AccordionPanel
|
||||
className="class-name"
|
||||
count={ 20 }
|
||||
title="Panel 2"
|
||||
initialOpen={ false }
|
||||
>
|
||||
<span>Panel 2 content</span>
|
||||
</AccordionPanel>
|
||||
</Accordion>
|
||||
);
|
||||
|
||||
export default {
|
||||
title: 'WooCommerce Admin/components/Accordion',
|
||||
component: Accordion,
|
||||
};
|
|
@ -1,26 +0,0 @@
|
|||
.woocommerce-accordion {
|
||||
&-badge {
|
||||
background-color: $gray-100;
|
||||
border-radius: 20px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 27px;
|
||||
align-items: center;
|
||||
width: 32px;
|
||||
height: 28px;
|
||||
margin-left: $gap;
|
||||
}
|
||||
&-card {
|
||||
&.is-panel-opened {
|
||||
&:not(:first-child) {
|
||||
margin-top: 20px;
|
||||
}
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { render, screen } from '@testing-library/react';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import Accordion from '../';
|
||||
import AccordionPanel from '../panel';
|
||||
|
||||
const panels = (
|
||||
<>
|
||||
<AccordionPanel
|
||||
className="panel-1"
|
||||
count={ 10000 }
|
||||
title="panel-1"
|
||||
initialOpen={ true }
|
||||
>
|
||||
<span>Custom panel 1</span>
|
||||
</AccordionPanel>
|
||||
<AccordionPanel
|
||||
className="panel-2"
|
||||
count={ 20000 }
|
||||
title="panel-2"
|
||||
initialOpen={ false }
|
||||
>
|
||||
<span>Custom panel 1</span>
|
||||
</AccordionPanel>
|
||||
</>
|
||||
);
|
||||
|
||||
describe( 'Accordion', () => {
|
||||
it( 'should render a panel with two rows', () => {
|
||||
render( <Accordion> { panels } </Accordion> );
|
||||
expect( screen.getByText( 'panel-1' ) ).not.toBeNull();
|
||||
expect( screen.getByText( 'panel-2' ) ).not.toBeNull();
|
||||
} );
|
||||
|
||||
it( 'should render one visible panel and one hidden panel', () => {
|
||||
render( <Accordion> { panels } </Accordion> );
|
||||
expect( screen.queryByText( 'Custom panel 1' ) ).toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByText( 'Custom panel 2' )
|
||||
).not.toBeInTheDocument();
|
||||
} );
|
||||
|
||||
it( 'should render the count of unread items', () => {
|
||||
render( <Accordion> { panels } </Accordion> );
|
||||
expect( screen.queryByText( '10000' ) ).toBeInTheDocument();
|
||||
expect( screen.queryByText( '20000' ) ).toBeInTheDocument();
|
||||
} );
|
||||
|
||||
it( 'should only render title if collapsible is false', () => {
|
||||
render(
|
||||
<Accordion>
|
||||
{ ' ' }
|
||||
<AccordionPanel
|
||||
title="empty title"
|
||||
initialOpen={ false }
|
||||
collapsible={ false }
|
||||
>
|
||||
<span>Custom panel 1</span>
|
||||
</AccordionPanel>
|
||||
</Accordion>
|
||||
);
|
||||
expect( screen.queryByText( 'empty title' ) ).toBeInTheDocument();
|
||||
expect( screen.queryByRole( 'button' ) ).toBeNull();
|
||||
expect( screen.queryByText( 'Custom panel 1' ) ).toBeNull();
|
||||
} );
|
||||
} );
|
|
@ -4,8 +4,6 @@
|
|||
import 'react-dates/initialize';
|
||||
// The above: Turn on react-dates classes/styles, see https://github.com/airbnb/react-dates#initialize
|
||||
|
||||
export { default as Accordion } from './accordion';
|
||||
export { default as AccordionPanel } from './accordion/panel';
|
||||
export { default as AdvancedFilters } from './advanced-filters';
|
||||
export { default as AnimationSlider } from './animation-slider';
|
||||
export { default as Chart } from './chart';
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
/**
|
||||
* Internal Dependencies
|
||||
*/
|
||||
@import 'accordion/style.scss';
|
||||
@import 'animation-slider/style.scss';
|
||||
@import 'calendar/style.scss';
|
||||
@import 'card/style.scss';
|
||||
@import 'chart/style.scss';
|
||||
|
|
Loading…
Reference in New Issue