Add progressive task list animation (https://github.com/woocommerce/woocommerce-admin/pull/7128)
* Hide unexpanded task item content with css. * Add transition animation to expanding TaskItems. * Fix tests.
This commit is contained in:
parent
b24a3d28b7
commit
150c902d36
|
@ -349,6 +349,7 @@ export const TaskList = ( {
|
||||||
? task.onClick
|
? task.onClick
|
||||||
: () => setCurrentTask( task.key )
|
: () => setCurrentTask( task.key )
|
||||||
}
|
}
|
||||||
|
expandable={ expandingItems }
|
||||||
expanded={
|
expanded={
|
||||||
expandingItems &&
|
expandingItems &&
|
||||||
currentTask === task.key
|
currentTask === task.key
|
||||||
|
|
|
@ -85,7 +85,7 @@ describe( 'TaskDashboard and TaskList', () => {
|
||||||
isDismissable: false,
|
isDismissable: false,
|
||||||
type: 'setup',
|
type: 'setup',
|
||||||
action: 'CTA (required)',
|
action: 'CTA (required)',
|
||||||
content: 'This is the require task content',
|
content: 'This is the required task content',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'completed',
|
key: 'completed',
|
||||||
|
@ -108,6 +108,8 @@ describe( 'TaskDashboard and TaskList', () => {
|
||||||
time: '1 minute',
|
time: '1 minute',
|
||||||
isDismissable: true,
|
isDismissable: true,
|
||||||
type: 'extension',
|
type: 'extension',
|
||||||
|
action: 'CTA (extension)',
|
||||||
|
content: 'This is the extension task content',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -663,9 +665,12 @@ describe( 'TaskDashboard and TaskList', () => {
|
||||||
isExtendedTaskListHidden: true,
|
isExtendedTaskListHidden: true,
|
||||||
profileItems: {},
|
profileItems: {},
|
||||||
} ) );
|
} ) );
|
||||||
const { queryByText } = render( <TaskDashboard query={ {} } /> );
|
act( () => {
|
||||||
expect( queryByText( 'This is the optional task content' ) ).toBeNull();
|
const { queryByText } = render( <TaskDashboard query={ {} } /> );
|
||||||
expect( queryByText( 'CTA (optional)' ) ).toBeNull();
|
expect(
|
||||||
|
queryByText( 'This is the optional task content' )
|
||||||
|
).not.toHaveClass( 'woocommerce-task-list__item-content-appear' );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
it( 'setup task list renders expandable items in experiment variant', async () => {
|
it( 'setup task list renders expandable items in experiment variant', async () => {
|
||||||
|
@ -683,21 +688,24 @@ describe( 'TaskDashboard and TaskList', () => {
|
||||||
variationName: 'treatment',
|
variationName: 'treatment',
|
||||||
},
|
},
|
||||||
] );
|
] );
|
||||||
const { container, queryByText } = render(
|
await act( async () => {
|
||||||
<TaskDashboard query={ {} } />
|
const { container, queryByText } = render(
|
||||||
);
|
<TaskDashboard query={ {} } />
|
||||||
|
);
|
||||||
|
|
||||||
// Expect the first incomplete task to be expanded
|
// Expect the first incomplete task to be expanded
|
||||||
expect(
|
expect(
|
||||||
await findByText( container, 'This is the optional task content' )
|
await findByText(
|
||||||
).not.toBeNull();
|
container,
|
||||||
expect(
|
'This is the optional task content'
|
||||||
await findByText( container, 'CTA (optional)' )
|
)
|
||||||
).not.toBeNull();
|
).toHaveClass( 'woocommerce-task-list__item-content-appear' );
|
||||||
|
|
||||||
// Expect the second not to be.
|
// Expect the second not to be.
|
||||||
expect( queryByText( 'This is the required task content' ) ).toBeNull();
|
expect(
|
||||||
expect( queryByText( 'CTA (required)' ) ).toBeNull();
|
queryByText( 'This is the required task content' )
|
||||||
|
).not.toHaveClass( 'woocommerce-task-list__item-content-appear' );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
describe( 'getVisibleTasks', () => {
|
describe( 'getVisibleTasks', () => {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
- Remove the use of Dashicons and replace with @wordpress/icons or gridicons #7020
|
- Remove the use of Dashicons and replace with @wordpress/icons or gridicons #7020
|
||||||
- Add expanded item text and CTA button. #6956
|
- Add expanded item text and CTA button. #6956
|
||||||
- Add inbox note components (InboxNoteCard, InboxNotePlaceholder, and InboxDismissConfirmationModal). #7006
|
- Add inbox note components (InboxNoteCard, InboxNotePlaceholder, and InboxDismissConfirmationModal). #7006
|
||||||
|
- Add transition animation to expanding TaskItems.
|
||||||
|
|
||||||
# 1.2.0
|
# 1.2.0
|
||||||
|
|
||||||
|
|
|
@ -65,13 +65,50 @@ $task-alert-yellow: #f0b849;
|
||||||
}
|
}
|
||||||
|
|
||||||
.woocommerce-task-list__item-content {
|
.woocommerce-task-list__item-content {
|
||||||
|
max-height: 0;
|
||||||
|
opacity: 0;
|
||||||
margin-top: $gap-smallest;
|
margin-top: $gap-smallest;
|
||||||
margin-bottom: $gap-smallest;
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.woocommerce-task-list__item-content-enter {
|
||||||
|
opacity: 0;
|
||||||
|
max-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.woocommerce-task-list__item-content-enter-active {
|
||||||
|
opacity: 1;
|
||||||
|
max-height: 100vh;
|
||||||
|
transition: opacity 500ms, max-height 500ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.woocommerce-task-list__item-content-appear,
|
||||||
|
&.woocommerce-task-list__item-content-appear-active,
|
||||||
|
&.woocommerce-task-list__item-content-appear-done,
|
||||||
|
&.woocommerce-task-list__item-content-enter-done {
|
||||||
|
opacity: 1;
|
||||||
|
max-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.woocommerce-task-list__item-content-exit {
|
||||||
|
opacity: 1;
|
||||||
|
max-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.woocommerce-task-list__item-content-exit-active {
|
||||||
|
opacity: 0;
|
||||||
|
max-height: 0;
|
||||||
|
transition: opacity 500ms, max-height 500ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.woocommerce-task__additional-info {
|
||||||
|
margin-top: $gap-smaller;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.woocommerce-task-list__item-action {
|
.woocommerce-task-list__item-action {
|
||||||
margin-top: $gap-smallest;
|
margin-top: $gap-smaller;
|
||||||
margin-bottom: $gap-smaller;
|
margin-bottom: $gap-smallest;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.woocommerce-task-list__item-after {
|
.woocommerce-task-list__item-after {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import NoticeOutline from 'gridicons/dist/notice-outline';
|
||||||
import { EllipsisMenu } from '@woocommerce/components';
|
import { EllipsisMenu } from '@woocommerce/components';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { sanitize } from 'dompurify';
|
import { sanitize } from 'dompurify';
|
||||||
|
import { CSSTransition } from 'react-transition-group';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
|
@ -38,6 +39,7 @@ type TaskItemProps = {
|
||||||
additionalInfo?: string;
|
additionalInfo?: string;
|
||||||
time?: string;
|
time?: string;
|
||||||
content: string;
|
content: string;
|
||||||
|
expandable?: boolean;
|
||||||
expanded?: boolean;
|
expanded?: boolean;
|
||||||
level?: TaskLevel;
|
level?: TaskLevel;
|
||||||
action: (
|
action: (
|
||||||
|
@ -79,6 +81,7 @@ export const TaskItem: React.FC< TaskItemProps > = ( {
|
||||||
additionalInfo,
|
additionalInfo,
|
||||||
time,
|
time,
|
||||||
content,
|
content,
|
||||||
|
expandable = false,
|
||||||
expanded = false,
|
expanded = false,
|
||||||
level = 3,
|
level = 3,
|
||||||
action,
|
action,
|
||||||
|
@ -110,12 +113,42 @@ export const TaskItem: React.FC< TaskItemProps > = ( {
|
||||||
<span className="woocommerce-task-list__item-title">
|
<span className="woocommerce-task-list__item-title">
|
||||||
{ title }
|
{ title }
|
||||||
</span>
|
</span>
|
||||||
{ expanded && (
|
<CSSTransition
|
||||||
|
appear
|
||||||
|
timeout={ 500 }
|
||||||
|
in={ expanded }
|
||||||
|
classNames="woocommerce-task-list__item-content"
|
||||||
|
>
|
||||||
<div className="woocommerce-task-list__item-content">
|
<div className="woocommerce-task-list__item-content">
|
||||||
{ content }
|
{ content }
|
||||||
|
{ expandable && ! completed && additionalInfo && (
|
||||||
|
<div
|
||||||
|
className="woocommerce-task__additional-info"
|
||||||
|
dangerouslySetInnerHTML={ sanitizeHTML(
|
||||||
|
additionalInfo
|
||||||
|
) }
|
||||||
|
></div>
|
||||||
|
) }
|
||||||
|
{ ! completed && (
|
||||||
|
<Button
|
||||||
|
className="woocommerce-task-list__item-action"
|
||||||
|
isPrimary
|
||||||
|
onClick={ (
|
||||||
|
event:
|
||||||
|
| React.MouseEvent
|
||||||
|
| React.KeyboardEvent
|
||||||
|
) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
action( event, { isExpanded: true } );
|
||||||
|
} }
|
||||||
|
>
|
||||||
|
{ actionLabel || title }
|
||||||
|
</Button>
|
||||||
|
) }
|
||||||
</div>
|
</div>
|
||||||
) }
|
</CSSTransition>
|
||||||
{ additionalInfo && (
|
|
||||||
|
{ ! expandable && ! completed && additionalInfo && (
|
||||||
<div
|
<div
|
||||||
className="woocommerce-task__additional-info"
|
className="woocommerce-task__additional-info"
|
||||||
dangerouslySetInnerHTML={ sanitizeHTML(
|
dangerouslySetInnerHTML={ sanitizeHTML(
|
||||||
|
@ -123,20 +156,6 @@ export const TaskItem: React.FC< TaskItemProps > = ( {
|
||||||
) }
|
) }
|
||||||
></div>
|
></div>
|
||||||
) }
|
) }
|
||||||
{ expanded && ! completed && (
|
|
||||||
<Button
|
|
||||||
className="woocommerce-task-list__item-action"
|
|
||||||
isPrimary
|
|
||||||
onClick={ (
|
|
||||||
event: React.MouseEvent | React.KeyboardEvent
|
|
||||||
) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
action( event, { isExpanded: true } );
|
|
||||||
} }
|
|
||||||
>
|
|
||||||
{ actionLabel || title }
|
|
||||||
</Button>
|
|
||||||
) }
|
|
||||||
{ time && (
|
{ time && (
|
||||||
<div className="woocommerce-task__estimated-time">
|
<div className="woocommerce-task__estimated-time">
|
||||||
{ time }
|
{ time }
|
||||||
|
|
Loading…
Reference in New Issue