From 364ada59e92078f4b8572dec2d48b0131a1ca6e2 Mon Sep 17 00:00:00 2001 From: Sophie Schneider Date: Tue, 23 Apr 2024 09:52:29 -0400 Subject: [PATCH] [Frame] Only add rounded styles when `topBar` exists (#11925) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### WHY are these changes introduced? Fixes https://github.com/Shopify/polaris-internal/issues/1598 ### WHAT is this pull request doing? Only applies rounded frame styles when the `Frame` component has a `topBar` prop ### How to 🎩 For `WithoutATopBar`, make sure [story](https://5d559397bae39100201eedc1-agsvebvhin.chromatic.com/?path=/story/all-components-frame--without-a-top-bar) is the same with feature flag on and off https://admin.web.web-81d9.sophie-schneider.us.spin.dev/store/shop1 ### 🎩 checklist - [x] Tested a [snapshot](https://github.com/Shopify/polaris/blob/main/documentation/Releasing.md#-snapshot-releases) - [x] Tested on [mobile](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting.md#cross-browser-testing) - [x] Tested on [multiple browsers](https://help.shopify.com/en/manual/shopify-admin/supported-browsers) --- .changeset/mean-kangaroos-move.md | 5 + .../components/AppProvider/AppProvider.tsx | 14 - .../src/components/Frame/Frame.stories.tsx | 333 +++++++++++++++++- polaris-react/src/components/Frame/Frame.tsx | 166 +++++---- 4 files changed, 421 insertions(+), 97 deletions(-) create mode 100644 .changeset/mean-kangaroos-move.md diff --git a/.changeset/mean-kangaroos-move.md b/.changeset/mean-kangaroos-move.md new file mode 100644 index 00000000000..8394f2f9abf --- /dev/null +++ b/.changeset/mean-kangaroos-move.md @@ -0,0 +1,5 @@ +--- +'@shopify/polaris': patch +--- + +Updated Frame to only apply rounded Frame when passed a `topBar` diff --git a/polaris-react/src/components/AppProvider/AppProvider.tsx b/polaris-react/src/components/AppProvider/AppProvider.tsx index 5dc95e9a124..dbed43729fe 100644 --- a/polaris-react/src/components/AppProvider/AppProvider.tsx +++ b/polaris-react/src/components/AppProvider/AppProvider.tsx @@ -138,8 +138,6 @@ export class AppProvider extends Component { const {i18n, linkComponent} = this.props; this.setRootAttributes(); - /* Temporary for dynamicTopBarAndReframe feature. Remove when feature flag is removed. */ - this.setBodyStyles(); if (i18n === prevI18n && linkComponent === prevLinkComponent) { return; @@ -152,20 +150,8 @@ export class AppProvider extends Component { } setBodyStyles = () => { - const {features} = this.props; - document.body.style.backgroundColor = 'var(--p-color-bg)'; document.body.style.color = 'var(--p-color-text)'; - - /* Temporary for dynamicTopBarAndReframe feature. - * Remove when feature flag is removed and apply - * styles directly to body in the global stylesheet. - */ - if (features?.dynamicTopBarAndReframe) { - document.body.style.overflow = 'hidden'; - } else { - document.body.style.overflow = ''; - } }; setRootAttributes = () => { diff --git a/polaris-react/src/components/Frame/Frame.stories.tsx b/polaris-react/src/components/Frame/Frame.stories.tsx index 19e02332eb5..0b622937a63 100644 --- a/polaris-react/src/components/Frame/Frame.stories.tsx +++ b/polaris-react/src/components/Frame/Frame.stories.tsx @@ -35,10 +35,18 @@ export default { } as Meta; export const InAnApplication = { - render: (_args: Args) => , + render: (_args: Args, {globals: {dynamicTopBarAndReframe}}) => ( + + ), }; -function InAnApplicationComponent() { +function InAnApplicationComponent({ + dynamicTopBarAndReframe, +}: { + dynamicTopBarAndReframe: boolean; +}) { const defaultState = useRef({ emailFieldValue: 'dharma@jadedpixel.com', nameFieldValue: 'Jaded Pixel', @@ -356,6 +364,7 @@ function InAnApplicationComponent() { }, }, }} + features={{dynamicTopBarAndReframe}} > , + render: (_args: Args, {globals: {dynamicTopBarAndReframe}}) => ( + + ), }; -function WithAnOffsetComponent() { +function WithAnOffsetComponent({ + dynamicTopBarAndReframe, +}: { + dynamicTopBarAndReframe: boolean; +}) { const defaultState = useRef({ emailFieldValue: 'dharma@jadedpixel.com', nameFieldValue: 'Jaded Pixel', @@ -698,6 +713,7 @@ function WithAnOffsetComponent() { }, }, }} + features={{dynamicTopBarAndReframe}} > , + render: (_args: Args, {globals: {dynamicTopBarAndReframe}}) => ( + + ), }; -function WithSidebarEnabled() { +function WithSidebarEnabled({ + dynamicTopBarAndReframe, +}: { + dynamicTopBarAndReframe: boolean; +}) { const defaultState = useRef({ emailFieldValue: 'dharma@jadedpixel.com', nameFieldValue: 'Jaded Pixel', @@ -1055,6 +1077,7 @@ function WithSidebarEnabled() { }, }, }} + features={{dynamicTopBarAndReframe}} > ); } + +export const WithoutATopBar = { + render: (_args: Args, {globals: {dynamicTopBarAndReframe}}) => ( + + ), +}; + +function WithoutATopBarComponent({ + dynamicTopBarAndReframe, +}: { + dynamicTopBarAndReframe: boolean; +}) { + const defaultState = useRef({ + emailFieldValue: 'dharma@jadedpixel.com', + nameFieldValue: 'Jaded Pixel', + }); + const skipToContentRef = useRef(null); + + const [toastActive, setToastActive] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const [isDirty, setIsDirty] = useState(false); + const [mobileNavigationActive, setMobileNavigationActive] = useState(false); + const [modalActive, setModalActive] = useState(false); + const [nameFieldValue, setNameFieldValue] = useState( + defaultState.current.nameFieldValue, + ); + const [emailFieldValue, setEmailFieldValue] = useState( + defaultState.current.emailFieldValue, + ); + const [storeName, setStoreName] = useState( + defaultState.current.nameFieldValue, + ); + const [supportSubject, setSupportSubject] = useState(''); + const [supportMessage, setSupportMessage] = useState(''); + + const handleSubjectChange = useCallback( + (value) => setSupportSubject(value), + [], + ); + const handleMessageChange = useCallback( + (value) => setSupportMessage(value), + [], + ); + const handleDiscard = useCallback(() => { + setEmailFieldValue(defaultState.current.emailFieldValue); + setNameFieldValue(defaultState.current.nameFieldValue); + setIsDirty(false); + }, []); + const handleSave = useCallback(() => { + defaultState.current.nameFieldValue = nameFieldValue; + defaultState.current.emailFieldValue = emailFieldValue; + + setIsDirty(false); + setToastActive(true); + setStoreName(defaultState.current.nameFieldValue); + }, [emailFieldValue, nameFieldValue]); + const handleNameFieldChange = useCallback((value) => { + setNameFieldValue(value); + value && setIsDirty(true); + }, []); + const handleEmailFieldChange = useCallback((value) => { + setEmailFieldValue(value); + value && setIsDirty(true); + }, []); + const toggleToastActive = useCallback( + () => setToastActive((toastActive) => !toastActive), + [], + ); + const toggleMobileNavigationActive = useCallback( + () => + setMobileNavigationActive( + (mobileNavigationActive) => !mobileNavigationActive, + ), + [], + ); + const toggleIsLoading = useCallback( + () => setIsLoading((isLoading) => !isLoading), + [], + ); + const toggleModalActive = useCallback( + () => setModalActive((modalActive) => !modalActive), + [], + ); + + const toastMarkup = toastActive ? ( + + ) : null; + + const contextualSaveBarMarkup = isDirty ? ( + + ) : null; + + const searchResultsMarkup = ( + + ); + + const navigationMarkup = ( + + + + + ); + + const loadingMarkup = isLoading ? : null; + + const skipToContentTarget = ( + + + Account details + + + ); + + const actualPageMarkup = ( + + + {skipToContentTarget} + + + + + + + + + + + ); + + const loadingPageMarkup = ( + + + + + + + + + + + + + ); + + const pageMarkup = isLoading ? loadingPageMarkup : actualPageMarkup; + + const modalMarkup = ( + + + + + + + + + ); + + const logo = { + width: 86, + topBarSource: + 'https://cdn.shopify.com/s/files/1/2376/3301/files/Shopify_Secondary_Inverted.png', + contextualSaveBarSource: + 'https://cdn.shopify.com/s/files/1/2376/3301/files/Shopify_Secondary_Inverted.png', + accessibilityLabel: 'Shopify', + }; + + return ( +
+ + + {contextualSaveBarMarkup} + {loadingMarkup} + {pageMarkup} + {toastMarkup} + {modalMarkup} + + +
+ ); +} diff --git a/polaris-react/src/components/Frame/Frame.tsx b/polaris-react/src/components/Frame/Frame.tsx index eb4730c8032..800ec755fc7 100644 --- a/polaris-react/src/components/Frame/Frame.tsx +++ b/polaris-react/src/components/Frame/Frame.tsx @@ -23,7 +23,6 @@ import type { } from '../../utilities/frame'; import {UseTheme} from '../../utilities/use-theme'; import {UseFeatures} from '../../utilities/features'; -import type {FeaturesConfig} from '../../utilities/features'; import { ToastManager, @@ -63,6 +62,7 @@ export interface FrameProps { type CombinedProps = FrameProps & { i18n: ReturnType; mediaQuery: ReturnType; + dynamicTopBarAndReframe?: boolean; }; interface State { @@ -98,6 +98,7 @@ class FrameInner extends PureComponent { } this.setGlobalRibbonRootProperty(); this.setOffset(); + this.setBodyStyles(); } componentDidUpdate(prevProps: FrameProps) { @@ -105,6 +106,7 @@ class FrameInner extends PureComponent { this.setGlobalRibbonHeight(); } this.setOffset(); + this.setBodyStyles(); } render() { @@ -240,34 +242,26 @@ class FrameInner extends PureComponent { } : {}; - const getFrameClassName = (features: FeaturesConfig) => + const getFrameClassName = (hasDynamicTopBar?: boolean) => classNames( styles.Frame, - features?.dynamicTopBarAndReframe && styles['Frame-TopBarAndReframe'], + hasDynamicTopBar && styles['Frame-TopBarAndReframe'], navigation && styles.hasNav, topBar && styles.hasTopBar, sidebar && styles.hasSidebar, - sidebar && - features?.dynamicTopBarAndReframe && - styles['hasSidebar-TopBarAndReframe'], + sidebar && hasDynamicTopBar && styles['hasSidebar-TopBarAndReframe'], ); - const contextualSaveBarMarkup = ( - - {({dynamicTopBarAndReframe}) => - dynamicTopBarAndReframe ? ( - <> - ) : ( - - - - ) - } - + const contextualSaveBarMarkup = this.props.dynamicTopBarAndReframe ? ( + <> + ) : ( + + + ); const navigationOverlayMarkup = @@ -294,68 +288,64 @@ class FrameInner extends PureComponent { contextualSaveBarProps: this.contextualSaveBar, }; + const hasDynamicTopBar = + this.props.dynamicTopBarAndReframe && Boolean(topBar); + return ( - - {(features) => ( -
- {skipMarkup} - {topBarMarkup} - {features?.dynamicTopBarAndReframe ? null : navigationMarkup} - {contextualSaveBarMarkup} - {loadingMarkup} - {navigationOverlayMarkup} - {features?.dynamicTopBarAndReframe ? ( -
- {navigationMarkup} -
+
+ {skipMarkup} + {topBarMarkup} + {hasDynamicTopBar ? null : navigationMarkup} + {contextualSaveBarMarkup} + {loadingMarkup} + {navigationOverlayMarkup} + {hasDynamicTopBar ? ( +
+ {navigationMarkup} +
+
+ {hasDynamicTopBar ? (
- {features?.dynamicTopBarAndReframe ? ( -
- {children} -
- ) : ( - children - )} + {children}
-
+ ) : ( + children + )}
- ) : ( -
-
{children}
-
- )} - - {globalRibbonMarkup} - +
+ ) : ( +
+
{children}
+
)} - + + {globalRibbonMarkup} + +
); } @@ -385,6 +375,17 @@ class FrameInner extends PureComponent { ); }; + private setBodyStyles = () => { + if (!document) { + return; + } + if (this.props.dynamicTopBarAndReframe && Boolean(this.props.topBar)) { + document.body.style.overflow = 'hidden'; + } else { + document.body.style.overflow = ''; + } + }; + private showToast = (toast: ToastPropsWithID) => { this.setState(({toastMessages}: State) => { const hasToastById = @@ -489,5 +490,16 @@ export function Frame(props: FrameProps) { const i18n = useI18n(); const mediaQuery = useMediaQuery(); - return ; + return ( + + {({dynamicTopBarAndReframe}) => ( + + )} + + ); }