Skip to content

Commit

Permalink
Add shake leave confirmation
Browse files Browse the repository at this point in the history
  • Loading branch information
sophschneider committed Jan 19, 2024
1 parent 2755dc5 commit 6eb350e
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 45 deletions.
56 changes: 33 additions & 23 deletions polaris-react/playground/DetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,14 @@ export function DetailsPage() {
),
[],
);
const toggleIsLoading = useCallback(
() => setIsLoading((isLoading) => !isLoading),
[],
);
const toggleIsLoading = useCallback(() => {
if (isDirty) {
const event = new CustomEvent('onLeaveDirtyState');
window.dispatchEvent(event);
return;
}
setIsLoading((isLoading) => !isLoading);
}, [isDirty]);
const toggleModalActive = useCallback(
() => setModalActive((modalActive) => !modalActive),
[],
Expand Down Expand Up @@ -222,7 +226,7 @@ export function DetailsPage() {
icon: HomeIcon,
onClick: () => {
toggleIsLoading();
setNavItemActive('home');
!isDirty && setNavItemActive('home');
},
matches: navItemActive === 'home',
url: '#',
Expand All @@ -232,7 +236,7 @@ export function DetailsPage() {
icon: OrderIcon,
onClick: () => {
toggleIsLoading();
setNavItemActive('orders');
!isDirty && setNavItemActive('orders');
},
matches: navItemActive === 'orders',
url: '#',
Expand All @@ -241,7 +245,7 @@ export function DetailsPage() {
label: 'All orders',
onClick: () => {
toggleIsLoading();
setNavItemActive('all-orders');
!isDirty && setNavItemActive('all-orders');
},
matches: navItemActive.includes('orders'),
url: '#',
Expand All @@ -251,7 +255,7 @@ export function DetailsPage() {
label: 'Drafts',
onClick: () => {
toggleIsLoading();
setNavItemActive('drafts');
!isDirty && setNavItemActive('drafts');
},
matches: navItemActive === 'drafts',
},
Expand All @@ -260,7 +264,7 @@ export function DetailsPage() {
label: 'Abandoned checkouts',
onClick: () => {
toggleIsLoading();
setNavItemActive('abandoned');
!isDirty && setNavItemActive('abandoned');
},
matches: navItemActive === 'abandoned',
},
Expand All @@ -271,16 +275,17 @@ export function DetailsPage() {
icon: ProductIcon,
onClick: () => {
toggleIsLoading();
setNavItemActive('products');
!isDirty && setNavItemActive('products');
},
matches: navItemActive === 'products',
url: '#',
subNavigationItems: [
{
label: 'All products',
onClick: () => {
console.log(isDirty);
toggleIsLoading();
setNavItemActive('all-products');
!isDirty && setNavItemActive('all-products');
},
matches: navItemActive.includes('products'),
url: '#',
Expand All @@ -290,7 +295,7 @@ export function DetailsPage() {
label: 'Inventory',
onClick: () => {
toggleIsLoading();
setNavItemActive('inventory');
!isDirty && setNavItemActive('inventory');
},
matches: navItemActive === 'inventory',
},
Expand All @@ -299,7 +304,7 @@ export function DetailsPage() {
label: 'Transfers',
onClick: () => {
toggleIsLoading();
setNavItemActive('transfers');
!isDirty && setNavItemActive('transfers');
},
matches: navItemActive === 'transfers',
},
Expand All @@ -310,7 +315,7 @@ export function DetailsPage() {
icon: PersonIcon,
onClick: () => {
toggleIsLoading();
setNavItemActive('customers');
!isDirty && setNavItemActive('customers');
},
matches: navItemActive === 'customers',
url: '#',
Expand All @@ -320,7 +325,7 @@ export function DetailsPage() {
icon: ChartVerticalIcon,
onClick: () => {
toggleIsLoading();
setNavItemActive('analytics');
!isDirty && setNavItemActive('analytics');
},
matches: navItemActive === 'analytics',
url: '#',
Expand All @@ -330,7 +335,7 @@ export function DetailsPage() {
icon: TargetIcon,
onClick: () => {
toggleIsLoading();
setNavItemActive('marketing');
!isDirty && setNavItemActive('marketing');
},
matches: navItemActive === 'marketing',
url: '#',
Expand All @@ -340,7 +345,7 @@ export function DetailsPage() {
icon: DiscountIcon,
onClick: () => {
toggleIsLoading();
setNavItemActive('discounts');
!isDirty && setNavItemActive('discounts');
},
matches: navItemActive === 'discounts',
url: '#',
Expand All @@ -350,7 +355,7 @@ export function DetailsPage() {
icon: AppsIcon,
onClick: () => {
toggleIsLoading();
setNavItemActive('apps');
!isDirty && setNavItemActive('apps');
},
matches: navItemActive === 'apps',
url: '#',
Expand All @@ -374,7 +379,7 @@ export function DetailsPage() {
icon: posIcon,
onClick: () => {
toggleIsLoading();
setNavItemActive('pos');
!isDirty && setNavItemActive('pos');
},
matches: navItemActive === 'pos',
url: '#',
Expand All @@ -383,7 +388,7 @@ export function DetailsPage() {
label: 'Overview',
onClick: () => {
toggleIsLoading();
setNavItemActive('pos');
!isDirty && setNavItemActive('pos');
},
matches: navItemActive.includes('pos'),
url: '#',
Expand All @@ -393,7 +398,7 @@ export function DetailsPage() {
label: 'Staff',
onClick: () => {
toggleIsLoading();
setNavItemActive('pos');
!isDirty && setNavItemActive('pos');
},
matches: navItemActive === 'pos',
},
Expand All @@ -402,7 +407,7 @@ export function DetailsPage() {
label: 'Locations',
onClick: () => {
toggleIsLoading();
setNavItemActive('pos');
!isDirty && setNavItemActive('pos');
},
matches: navItemActive === 'pos',
external: true,
Expand Down Expand Up @@ -550,7 +555,12 @@ export function DetailsPage() {
const actualPageMarkup = (
<Page
fullWidth
backAction={{content: 'Products', url: '/products/31'}}
backAction={{
onAction: () => {
toggleIsLoading();
!isDirty && setNavItemActive('home');
},
}}
title={title}
titleMetadata={<Badge tone="success">Success badge</Badge>}
primaryAction={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
.ContextualSaveBar {
/* stylelint-disable -- polaris: Used to apply dark theme to action buttons */
--p-color-bg-surface: var(--p-color-bg-surface-inverse);
--p-color-bg-surface-hover: var(--p-color-bg-fill-inverse-hover);
--p-color-bg-surface-secondary-active: var(--p-color-bg-fill-inverse-active);
/* stylelint-enable */
position: relative;
display: flex;
height: 36px;
background-color: var(--p-color-bg-surface-inverse);
Expand All @@ -21,6 +21,32 @@
background-origin: border-box;
background-clip: padding-box, border-box;

// stylelint-disable -- prototype
&::before {
content: '';
position: absolute;
top: -1px;
left: -1px;
right: -1px;
bottom: -1px;
pointer-events: none;
opacity: 0;
transition: opacity 0.6s var(--p-motion-ease-out);

border-radius: var(--p-border-radius-300);
border: solid var(--p-border-width-025) transparent;
background-origin: border-box;
background-clip: padding-box, border-box;
background-color: var(--p-color-bg-fill-success-active);

background-image: linear-gradient(
var(--p-color-bg-fill-success-active),
var(--p-color-bg-fill-success-active)
),
linear-gradient(to bottom, rgba(255, 255, 255, 0.12), transparent);
}
// stylelint-enable

.LogoContainer {
border-right: none;
}
Expand Down Expand Up @@ -60,6 +86,7 @@
margin: 0 auto;
padding: var(--p-space-100);
padding-left: var(--p-space-200);
z-index: 1;
}

.fullWidth {
Expand Down Expand Up @@ -108,11 +135,11 @@
& [class*='Polaris-Button--variantTertiary'],
& [class*='Button-variantTertiary'] {
--pc-button-bg: rgba(255, 255, 255, 0.1);
--pc-button-bg_hover: var(--p-color-bg-fill-inverse-hover);
--pc-button-bg_active: var(--p-color-bg-fill-inverse-active);
--pc-button-bg_hover: rgba(255, 255, 255, 0.15);
--pc-button-bg_active: rgba(255, 255, 255, 0.25);
--pc-button-bg_disabled: var(--pc-button-bg);
--pc-button-color: var(--p-color-text-inverse);
--pc-button-color_disabled: var(--p-color-text-secondary);
--pc-button-color_disabled: rgba(255, 255, 255, 0.15);
}
/* stylelint-enable */
}
Expand All @@ -129,3 +156,43 @@
width: $layout-width-nav-base;
}
}

// stylelint-disable -- prototype
.GreenBar {
animation: shake 0.7s var(--p-motion-ease-in-out);

.ContextualSaveBar {
&::before {
opacity: 1;
transition: opacity 0.4s var(--p-motion-ease-in-out);
}
}
}

@keyframes shake {
0% {
transform: translateX(0);
}
16% {
transform: translateX(6px);
}
32% {
transform: translateX(-6px);
}
48% {
transform: translateX(6px);
}
64% {
transform: translateX(-6px);
}
80% {
transform: translateX(6px);
}
96% {
transform: translateX(0px);
}
100% {
transform: translateX(0px);
}
}
// stylelint-enable
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useCallback} from 'react';
import React, {useCallback, useRef} from 'react';
import {AlertBubbleIcon} from '@shopify/polaris-icons';

import {Button} from '../../../Button';
Expand All @@ -9,6 +9,8 @@ import type {ContextualSaveBarProps} from '../../../../utilities/frame';
import {useI18n} from '../../../../utilities/i18n';
import {useToggle} from '../../../../utilities/use-toggle';
import {InlineStack} from '../../../InlineStack';
import {useEventListener} from '../../../../utilities/use-event-listener';
import {debounce} from '../../../../utilities/debounce';

import {DiscardConfirmationModal} from './components';
import styles from './ContextualSaveBar.module.scss';
Expand All @@ -21,6 +23,25 @@ export function ContextualSaveBar({
secondaryMenu,
}: ContextualSaveBarProps) {
const i18n = useI18n();
const barRef = useRef<HTMLDivElement>(null);

const handleLeaveConfirmation = debounce(
() => {
barRef.current?.classList.add(styles.GreenBar);

setTimeout(() => {
barRef.current?.classList.remove(styles.GreenBar);
}, 1200);
},
500,
{leading: true, trailing: false},
);

useEventListener(
'onLeaveDirtyState' as keyof WindowEventMap,
handleLeaveConfirmation,
);

const {
value: discardConfirmationModalVisible,
toggle: toggleDiscardConfirmationModal,
Expand All @@ -39,13 +60,6 @@ export function ContextualSaveBar({
? discardAction.content
: i18n.translate('Polaris.ContextualSaveBar.discard');

let discardActionHandler;
if (discardAction && discardAction.discardConfirmationModal) {
discardActionHandler = toggleDiscardConfirmationModal;
} else if (discardAction) {
discardActionHandler = discardAction.onAction;
}

const discardConfirmationModalMarkup = discardAction &&
discardAction.onAction &&
discardAction.discardConfirmationModal && (
Expand All @@ -61,7 +75,7 @@ export function ContextualSaveBar({
variant="tertiary"
size="slim"
url={discardAction.url}
onClick={discardActionHandler}
onClick={discardAction?.onAction}
loading={discardAction.loading}
disabled={discardAction.disabled}
accessibilityLabel={discardAction.content}
Expand Down Expand Up @@ -95,7 +109,7 @@ export function ContextualSaveBar({
);

return (
<>
<div ref={barRef}>
<div className={styles.ContextualSaveBar}>
<div className={contentsClassName}>
<div className={styles.MessageContainer}>
Expand All @@ -116,6 +130,6 @@ export function ContextualSaveBar({
</div>
</div>
{discardConfirmationModalMarkup}
</>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React from 'react';
import {mountWithApp} from 'tests/utilities';

import {Button} from '../../../../Button';
import {Image} from '../../../../Image';
import {ContextualSaveBar} from '../ContextualSaveBar';
import {DiscardConfirmationModal} from '../components';

Expand Down
Loading

0 comments on commit 6eb350e

Please sign in to comment.