Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ui): modal scrolling behavior on mobile #1620

Merged
merged 9 commits into from
Oct 28, 2024

Conversation

unrenamed
Copy link
Contributor

@unrenamed unrenamed commented Oct 23, 2024

What does this PR do?

Moves the scrollable section one level down, placing it directly inside <Drawer.Content /> as its child. This change ensures that when scrolling is active, no :after pseudo-elements are unintentionally visible. Improves visual consistency and resolves minor aesthetic bugs related to scrollbars and overflow.

Fixes: #1609

TL;DR

Although @aritradevelops were right in their #1612 PR about the use of Vaul's drawer that is shipped with some default CSS, the actual root cause was quite unexpected.

Screenshot 2024-10-23 at 18 01 35

Issue Diagnosis

Who is the bad guy?

This was the first question to answer: how is it possible that the scrollable drawer from the official Vaul website does NOT have such an issue. Check this yourself: https://vaul.emilkowal.ski/default#scrollable. It also has that same :after pseudo-element with height: 200% property.

Screenshot 2024-10-23 at 18 32 34

And if you take a closer look, you may notice that the <Drawer.Content /> isn’t the one getting scrolled when its content expands. Nope, it’s the first child <div> block that’s hogging all the action!

Screenshot 2024-10-23 at 18 34 35

But why does it break the UI?

It's easy. overflow: auto enables scrolling for the drawer parent container (the <Drawer.Content /> component). The default CSS shipped with the package contains an :after pseudo-element, which is a child of the parent container. Enabling scrolling for the parent container made all children — including the :after — visible. Removing overflow: auto fixes the problem, but introduces another: the Create button gets cut off at the bottom.

Ugh, what now?

Do you see that max-h-[95h] class on the parent element? It does a few things:

  1. restricts the height of an element to a maximum value, in this case, 95% of the viewport height
  2. the element grows up to 95vh, but not beyond it, even if its content exceeds this height
  3. when content inside the element is taller than 95vh, the element will either overflow (if overflow is allowed) or be constrained by its height.

Key point: if overflow is allowed. And guess what? It’s not! We removed it from the parent container, remember? Did we add one to any of its children? Nope!

So, what's the fix?

Adding overflow or overflow-y to the children of the <Drawer.Content /> allows them to handle scrolling when the inner content exceeds the specified height. Check the code for a clearer picture.

Why this is anyway better than the fix suggested in #1612 PR?

I see two big red flags with overriding CSS globally:

  1. Overuse of !important: It makes future overrides difficult and leads to maintenance issues.
  2. Global impact: The rule applies broadly to all matching elements, potentially causing unintended side effects across the app. E.g. in other component using vaul's drawer like input select or popover.

Result

This is how the fixed modal looks on mobile:

Screen.Recording.2024-10-23.at.18.08.41.mov

And this is how it looks in full screen:

Screen.Recording.2024-10-23.at.18.11.07.mov

Moves the scrollable section one level down, placing it directly inside <Drawer.Content /> as its child. This change ensures that when scrolling is active, no :after pseudo-elements are unintentionally visible. Improves visual consistency and resolves minor aesthetic bugs related to scrollbars and overflow.
Copy link

vercel bot commented Oct 23, 2024

@unrenamed is attempting to deploy a commit to the Dub Team on Vercel.

A member of the Team first needs to authorize it.

@unrenamed
Copy link
Contributor Author

@steven-tey Just merged with the latest main. Feel free to review the PR.

Copy link
Collaborator

@TWilson023 TWilson023 left a comment

Choose a reason for hiding this comment

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

@unrenamed previously our AddEditDomainModal and AddEditTokenModal were scrollable on desktop (with a short window height), but now they aren't - can we restore this?

Ideally all of our modals would just be scrollable by default, but I'm not sure how big of a lift that would be.

@unrenamed
Copy link
Contributor Author

unrenamed commented Oct 24, 2024

@TWilson023 My bad, I missed that the className property is shared between Radix Dialog and vaul Drawer components.

Adding scrollbar-hide overflow-y-auto to Dialog.Content fixes the current issue, but there’s a problem with three other modals that used to rely (not sure why) on overflow: visible (see the screenshot). Now, they'll get overflow-y: auto. If that’s an issue, a Modal refactor is likely needed to separate the class names for Dialog and Drawer.

image

@unrenamed
Copy link
Contributor Author

@TWilson023 Feel free to check again. I pushed the fix. As for, scrollbar-hidden class, I've added it for consistency. If scroll visibility needs to be conditional depending on the modal, further adjustments will be required.

Copy link
Collaborator

@TWilson023 TWilson023 left a comment

Choose a reason for hiding this comment

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

@unrenamed this is looking better now, thank you!

I did notice one more issue that I'm not seeing on main: on Chrome iOS, I can't seem to open the AddEditDomainModal or other updated modals. Any chance you're able to reproduce this on another mobile device?

modal.mp4

@unrenamed
Copy link
Contributor Author

unrenamed commented Oct 26, 2024

@TWilson023 The issue might be due to Chrome on iOS using the WebKit engine, as I can reproduce it in Safari as well. Applying height: fit-content to Vaul's <Drawer.Content> component seems to trigger it. Will push the fix in a moment.

@unrenamed
Copy link
Contributor Author

@TWilson023 The fix appears to work on my end. Can you confirm if it’s resolved for you as well?

@unrenamed
Copy link
Contributor Author

unrenamed commented Oct 26, 2024

@TWilson023 @steven-tey Here are a few questions for further refactoring:

  1. Is there any reason not to set a default max-h-[95dvh] (or similar) for all modals? We could add it directly to the component to ensure each modal stays within the viewport.

  2. Some modals apply custom widths via the className prop, which affects both Drawer and Dialog components on mobile. This leads to issues (see screenshot) in uncommon screen sizes, suggesting that a shared className might not be ideal for both. Separate configuration props could better account for their distinct behavior, though it may add complexity to component usage. WDYT?

apps/web/ui/modals/import-csv-modal/index.tsx

className="max-h-[95dvh] max-w-lg"

image

Copy link
Collaborator

@TWilson023 TWilson023 left a comment

Choose a reason for hiding this comment

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

There's still some mobile glitchiness with the software keyboard for some drawers but I don't think this PR is causing any additional issues now. We'll probably want to do a separate Vaul upgrade PR soon and see if we can work out some of the remaining issues.

re further refactoring:

  1. Having a default max-h-[95dvh] and overflow-y-auto seems like a good idea to me - not sure if it'd be that simple or cause any new problems.
  2. Separating the drawer & modal classNames seems like something we'll have to do, though if we don't need them separated for most use cases, we could do something like a className?: string | (isDrawer: boolean) => string prop to keep things simple and avoid updating a bunch of existing uses.

Up to @steven-tey for where any of this additional work fits in!

@steven-tey steven-tey merged commit 869b31b into dubinc:main Oct 28, 2024
4 of 5 checks passed
Copy link

oss-gg bot commented Oct 28, 2024

Awarding unrenamed: 750 points 🕹️ Well done! Check out your new contribution on oss.gg/unrenamed

@steven-tey
Copy link
Collaborator

Just merged! Thanks so much for your work on this again @unrenamed 🙏

@steven-tey
Copy link
Collaborator

/award 750

Copy link

oss-gg bot commented Oct 28, 2024

Awarding unrenamed: 750 points 🕹️ Well done! Check out your new contribution on oss.gg/unrenamed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

UI Breaks on Add New API Key Drawer with Restricted Permissions on Mobile
3 participants