Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/red-doors-retire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/polaris': minor
---

Updated the Frame and Topbar components to stay clear of a scrollbar. This reduces the overall jumpiness in the UI when scrollbars appear and disappear when using a Polaris app.
38 changes: 38 additions & 0 deletions polaris-react/src/components/AppProvider/AppProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,43 @@ import type {FeaturesConfig} from '../../utilities/features';
import './AppProvider.scss';
import './global.scss';

const MAX_SCROLLBAR_WIDTH = 20;
const SCROLLBAR_TEST_ELEMENT_PARENT_SIZE = 30;
const SCROLLBAR_TEST_ELEMENT_CHILD_SIZE =
SCROLLBAR_TEST_ELEMENT_PARENT_SIZE + 10;

function measureScrollbars() {
const parentEl = document.createElement('div');
parentEl.setAttribute(
'style',
`position: absolute; opacity: 0; transform: translate3d(-9999px, -9999px, 0); pointer-events: none; width:${SCROLLBAR_TEST_ELEMENT_PARENT_SIZE}px; height:${SCROLLBAR_TEST_ELEMENT_PARENT_SIZE}px;`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be 3d? Might be slightly more performant:

Suggested change
`position: absolute; opacity: 0; transform: translate3d(-9999px, -9999px, 0); pointer-events: none; width:${SCROLLBAR_TEST_ELEMENT_PARENT_SIZE}px; height:${SCROLLBAR_TEST_ELEMENT_PARENT_SIZE}px;`,
`position: absolute; opacity: 0; transform: translate(-9999px, -9999px); pointer-events: none; width:${SCROLLBAR_TEST_ELEMENT_PARENT_SIZE}px; height:${SCROLLBAR_TEST_ELEMENT_PARENT_SIZE}px;`,

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think translate3d is more performant because it runs the process in the GPU but I haven't looked at this in awhile so it's worth double checking

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I learned way back when too, but I wouldn't be surprised if the whole "trigger GPU" trick has passed its best before date 😀

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking it would be more performant because it shouldn't have to trigger the gpu. There's no visibility in this but yes, probably negligible

);

const child = document.createElement('div');
child.setAttribute(
'style',
`width:100%; height: ${SCROLLBAR_TEST_ELEMENT_CHILD_SIZE}; overflow:scroll`,
);
parentEl.appendChild(child);
document.body.appendChild(parentEl);

const scrollbarWidth =
SCROLLBAR_TEST_ELEMENT_PARENT_SIZE -
(parentEl.firstElementChild?.clientWidth ?? 0);

const scrollbarWidthWithSafetyHatch = Math.min(
scrollbarWidth,
MAX_SCROLLBAR_WIDTH,
);

document.documentElement.style.setProperty(
'--pc-app-provider-scrollbar-width',
`${scrollbarWidthWithSafetyHatch}px`,
);

document.body.removeChild(parentEl);
}

interface State {
intl: I18n;
link: LinkLikeComponent | undefined;
Expand Down Expand Up @@ -65,6 +102,7 @@ export class AppProvider extends Component<AppProviderProps, State> {
this.setBodyStyles();
this.setRootAttributes();
}
measureScrollbars();
}

componentDidUpdate({
Expand Down
6 changes: 5 additions & 1 deletion polaris-react/src/components/Frame/Frame.scss
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,11 @@ $sidebar-breakpoint: 1200px;
align-items: stretch;

min-width: 0;
max-width: 100%;
@media #{$p-breakpoints-sm-up} {
// stylelint-disable -- polaris/conventions/polaris/custom-property-allowed-list -- Polaris component custom properties
max-width: calc(100vw - var(--pc-app-provider-scrollbar-width));
// stylelint-enable -- polaris/conventions/polaris/custom-property-allowed-list
}

// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
@include safe-area-for(padding-right, 0, right);
Expand Down
12 changes: 9 additions & 3 deletions polaris-react/src/components/TopBar/TopBar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ $right-column: 1fr;

.TopBar {
position: relative;
display: grid;
grid-template-columns: $left-column $search-column $right-column;
align-items: center;
height: $top-bar-height;
box-shadow: var(--p-shadow-sm);
background-color: var(--p-color-bg);
Expand Down Expand Up @@ -45,6 +42,15 @@ $right-column: 1fr;
}
}

.Container {
display: grid;
grid-template-columns: $left-column $search-column $right-column;
align-items: center;
// stylelint-disable -- polaris/conventions/polaris/custom-property-allowed-list -- Polaris component custom properties
width: calc(100vw - var(--pc-app-provider-scrollbar-width));
// stylelint-enable -- polaris/conventions/polaris/custom-property-allowed-list
}

.LogoDisplayControl {
display: none;
@media #{$p-breakpoints-md-up} {
Expand Down
18 changes: 10 additions & 8 deletions polaris-react/src/components/TopBar/TopBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,16 @@ export const TopBar: React.FunctionComponent<TopBarProps> & {

return (
<div className={styles.TopBar}>
<div className={styles.LeftContent}>
{navigationButtonMarkup}
{contextMarkup}
</div>
<div className={styles.Search}>{searchMarkup}</div>
<div className={styles.RightContent}>
<div className={styles.SecondaryMenu}>{secondaryMenu}</div>
{userMenu}
<div className={styles.Container}>
Copy link
Contributor

@mattkubej mattkubej Jul 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is going to conflict with what I just drafted here, where I'm converting the TopBar to a grid layout in order to achieve newly desired alignment of the elements. Specifically, the search field.

I'm guessing the Container is being added in this manner to constrain the width, but also allow the TopBar div to stretch the width of the screen. I suppose with the change I have above, the grid styles would then need to be applied to a child div of the Container div. What are your thoughts?

Something we'll need to be cognizant of with the ordering of delivering this and what I have staged.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing the Container is being added in this manner to constrain the width, but also allow the TopBar div to stretch the width of the screen.

Correct!

the grid styles would then need to be applied to a child div of the Container div

Yeah, this sounds right to me. I'm basically just adding another child in here and adding display: flex to it as well, so that the flex behaviour is passed down to the children below.

<div className={styles.LeftContent}>
{navigationButtonMarkup}
{contextMarkup}
</div>
<div className={styles.Search}>{searchMarkup}</div>
<div className={styles.RightContent}>
<div className={styles.SecondaryMenu}>{secondaryMenu}</div>
{userMenu}
</div>
</div>
</div>
);
Expand Down