From ce6353b97a768bfbb4f56ec0cba03c8bc6d0c0cc Mon Sep 17 00:00:00 2001 From: Sophie Schneider Date: Wed, 10 Apr 2024 14:04:36 -0400 Subject: [PATCH] Create rounded corner frame content (#11846) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### WHY are these changes introduced? Part of https://github.com/Shopify/polaris-internal/issues/1470 ### WHAT is this pull request doing? Round corners of the admin frame content (nav and main content) behind a beta flag. To achieve this: * Change background color to `var(--p-color-bg-inverse)` * Wrap content and nav in the frame in a border radius shadow bevel container * Move scroll bar from full frame (including top bar) to just content + nav container * Wrap all new changes in a feature flag |Before|After| |-|-| |Screenshot 2024-04-08 at 9 29 12 PM|Screenshot 2024-04-08 at 9 29 01 PM| ### How to 🎩 Toggle `dynamicTopBarAndReframe` feature flag on details story Make sure feature flag off doesn't affect admin ([spin](https://admin.web.web-bua6.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) - [x] Tested for [accessibility](https://github.com/Shopify/polaris/blob/main/documentation/Accessibility%20testing.md) - [ ] Updated the component's `README.md` with documentation changes - [ ] [Tophatted documentation](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting%20documentation.md) changes in the style guide --- .changeset/clean-turtles-grab.md | 5 + .../components/AppProvider/AppProvider.tsx | 16 +++- .../src/components/Frame/Frame.module.css | 65 +++++++++++++ polaris-react/src/components/Frame/Frame.tsx | 91 +++++++++++++------ .../Navigation/Navigation.module.css | 4 + .../src/components/Navigation/Navigation.tsx | 20 +++- .../PolarisTestProvider.tsx | 2 +- 7 files changed, 171 insertions(+), 32 deletions(-) create mode 100644 .changeset/clean-turtles-grab.md diff --git a/.changeset/clean-turtles-grab.md b/.changeset/clean-turtles-grab.md new file mode 100644 index 00000000000..9cd9373819a --- /dev/null +++ b/.changeset/clean-turtles-grab.md @@ -0,0 +1,5 @@ +--- +'@shopify/polaris': patch +--- + +Restyled Frame content behind dynamicTopBarAndReframe feature flag diff --git a/polaris-react/src/components/AppProvider/AppProvider.tsx b/polaris-react/src/components/AppProvider/AppProvider.tsx index 7020b285235..5dc95e9a124 100644 --- a/polaris-react/src/components/AppProvider/AppProvider.tsx +++ b/polaris-react/src/components/AppProvider/AppProvider.tsx @@ -138,6 +138,8 @@ 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; @@ -150,8 +152,20 @@ 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 = () => { @@ -168,7 +182,7 @@ export class AppProvider extends Component { getThemeName = (): ThemeName => this.props.theme ?? themeNameDefault; render() { - const {children, features} = this.props; + const {children, features = {}} = this.props; const themeName = this.getThemeName(); const {intl, link} = this.state; diff --git a/polaris-react/src/components/Frame/Frame.module.css b/polaris-react/src/components/Frame/Frame.module.css index d731f678527..a79ae7b24a3 100644 --- a/polaris-react/src/components/Frame/Frame.module.css +++ b/polaris-react/src/components/Frame/Frame.module.css @@ -21,6 +21,25 @@ } } +.hasSidebar-TopBarAndReframe { + transition: width var(--p-motion-duration-250) var(--p-motion-ease); + + /* Sidebar breakpoint is 1200px */ + /* stylelint-disable-next-line polaris/media-queries/polaris/media-query-allowed-list -- custom breakpoint */ + @media screen and (min-width: 1200px) { + /* stylelint-disable-next-line polaris/conventions/polaris/custom-property-allowed-list -- private token from component */ + width: calc(100% - var(--pc-sidebar-width)); + } +} + +.Frame-TopBarAndReframe { + /* stylelint-disable -- Polaris component custom properties */ + --pc-sidebar-width: calc(356px + var(--p-space-100)); + /* stylelint-enable */ + background-color: var(--p-color-bg-inverse); + transition: width var(--p-motion-duration-250) var(--p-motion-ease); +} + .Navigation { position: fixed; z-index: var(--p-z-index-8); @@ -219,6 +238,24 @@ } } +.Main-TopBarAndReframe { + border-inline-end: none; + background-color: var(--p-color-bg); + border-top-left-radius: var(--p-border-radius-300); + border-top-right-radius: var(--p-border-radius-300); + height: 100vh; + overflow: hidden; + + .hasTopBar & { + /* stylelint-disable-next-line -- polaris custom global property */ + margin-top: var(--pg-top-bar-height); + padding-top: 0; + @media print { + margin-top: 0; + } + } +} + .Content { position: relative; /* stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY */ @@ -237,6 +274,21 @@ } } +.Content-TopBarAndReframe { + overflow-y: scroll; + /* stylelint-disable-next-line polaris/conventions/polaris/custom-property-allowed-list -- top bar global space */ + margin-bottom: var(--pg-top-bar-height); + margin-right: var(--p-space-050); + + .hasSidebar & { + /* Sidebar breakpoint is 1200px */ + /* stylelint-disable-next-line polaris/media-queries/polaris/media-query-allowed-list -- custom breakpoint */ + @media screen and (min-width: 1200px) { + margin-right: unset; + } + } +} + .GlobalRibbonContainer { position: fixed; z-index: var(--p-z-index-3); @@ -321,3 +373,16 @@ } } } + +.ShadowBevel { + width: 100%; + + @mixin shadow-bevel var(--p-shadow-100), var(--p-border-radius-300), + var(--p-z-index-1); + + &::before { + /* stylelint-disable-next-line polaris/conventions/polaris/custom-property-allowed-list -- top bar global space */ + top: var(--pg-top-bar-height); + background-color: var(--p-color-bg); + } +} diff --git a/polaris-react/src/components/Frame/Frame.tsx b/polaris-react/src/components/Frame/Frame.tsx index b79481e7838..4919b474338 100644 --- a/polaris-react/src/components/Frame/Frame.tsx +++ b/polaris-react/src/components/Frame/Frame.tsx @@ -22,6 +22,8 @@ import type { ToastPropsWithID, } from '../../utilities/frame'; import {UseTheme} from '../../utilities/use-theme'; +import {UseFeatures} from '../../utilities/features'; +import type {FeaturesConfig} from '../../utilities/features'; import { ToastManager, @@ -238,12 +240,17 @@ class FrameInner extends PureComponent { } : {}; - const frameClassName = classNames( - styles.Frame, - navigation && styles.hasNav, - topBar && styles.hasTopBar, - sidebar && styles.hasSidebar, - ); + const getFrameClassName = (features: FeaturesConfig) => + classNames( + styles.Frame, + features?.dynamicTopBarAndReframe && styles['Frame-TopBarAndReframe'], + navigation && styles.hasNav, + topBar && styles.hasTopBar, + sidebar && styles.hasSidebar, + sidebar && + features?.dynamicTopBarAndReframe && + styles['hasSidebar-TopBarAndReframe'], + ); const contextualSaveBarMarkup = ( { return ( -
- {skipMarkup} - {topBarMarkup} - {navigationMarkup} - {contextualSaveBarMarkup} - {loadingMarkup} - {navigationOverlayMarkup} -
-
{children}
-
- - {globalRibbonMarkup} - -
+ + {(features) => ( +
+ {skipMarkup} + {topBarMarkup} + {features?.dynamicTopBarAndReframe ? null : navigationMarkup} + {contextualSaveBarMarkup} + {loadingMarkup} + {navigationOverlayMarkup} + {features?.dynamicTopBarAndReframe ? ( +
+ {navigationMarkup} +
+
+ {children} +
+
+
+ ) : ( +
+
{children}
+
+ )} + + {globalRibbonMarkup} + +
+ )} +
); } diff --git a/polaris-react/src/components/Navigation/Navigation.module.css b/polaris-react/src/components/Navigation/Navigation.module.css index a08d4d6ec59..f75645460f6 100644 --- a/polaris-react/src/components/Navigation/Navigation.module.css +++ b/polaris-react/src/components/Navigation/Navigation.module.css @@ -50,6 +50,10 @@ } } +.NavigationFrame-TopBarAndReframe { + border-top-left-radius: var(--p-border-radius-300); +} + .PrimaryNavigation { display: flex; overflow: auto; diff --git a/polaris-react/src/components/Navigation/Navigation.tsx b/polaris-react/src/components/Navigation/Navigation.tsx index 125d293c2e8..1bf8b7e22fd 100644 --- a/polaris-react/src/components/Navigation/Navigation.tsx +++ b/polaris-react/src/components/Navigation/Navigation.tsx @@ -7,6 +7,7 @@ import {UnstyledLink} from '../UnstyledLink'; import {classNames} from '../../utilities/css'; import {getWidth} from '../../utilities/get-width'; import {useFrame} from '../../utilities/frame'; +import {useFeatures} from '../../utilities/features'; import {NavigationContext} from './context'; import {Section, Item} from './components'; @@ -71,12 +72,27 @@ export const Navigation: React.FunctionComponent & { [location, onDismiss], ); + const features = useFeatures(); + return ( -