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

Add isolation:isolate to ButtonGroup container #2910

Merged
merged 4 commits into from
Feb 21, 2023
Merged

Conversation

iansan5653
Copy link
Contributor

Using z-index in reusable components is generally a bad idea, because z-index is one of the most subtle side-effecting CSS rules in existence. It will inevitably break things down the road. The only way to use z-index internally without affecting surrounding UI is to create a new stacking context to isolate the effects

In ButtonGroup, the z-index on the focused element is necessary to be able to show the focused button's outline above the other buttons. So we can't remove it altogether. But we can definitely isolate it, and there's no reason not to - the only goal here is to make the element show above its fellow buttons - not above the entire app. The easiest way to make a new stacking context with no other effects is isolation: isolate.

Fixes https://github.com/github/memex/issues/8722

@iansan5653 iansan5653 requested review from a team and colebemis February 17, 2023 19:29
@changeset-bot
Copy link

changeset-bot bot commented Feb 17, 2023

🦋 Changeset detected

Latest commit: e9f6ccc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@primer/react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Feb 17, 2023

size-limit report 📦

Path Size
dist/browser.esm.js 94.55 KB (+0.01% 🔺)
dist/browser.umd.js 95.14 KB (+0.01% 🔺)

@github-actions github-actions bot temporarily deployed to storybook-preview-2910 February 17, 2023 19:36 Inactive
@iansan5653 iansan5653 temporarily deployed to github-pages February 17, 2023 19:39 — with GitHub Actions Inactive
@github-actions github-actions bot temporarily deployed to storybook-preview-2910 February 17, 2023 19:39 Inactive
@iansan5653 iansan5653 temporarily deployed to github-pages February 17, 2023 20:20 — with GitHub Actions Inactive
@github-actions github-actions bot temporarily deployed to storybook-preview-2910 February 17, 2023 20:21 Inactive
@joshblack
Copy link
Member

Loved your explanation for this @iansan5653, thanks for taking the time to write that up 🙏

Do you know if there is a good lint rule or test that we could include to try and catch this stuff across components? Would love to make sure z-index usage by default also uses isolation unless it requires coordination in a parent context that we don't control.

@iansan5653
Copy link
Contributor Author

iansan5653 commented Feb 21, 2023

🤔 I think it would be pretty tricky to figure out how to lint for this. You might be able to test for it by walking up the DOM tree and checking for a new stacking context but even that would be tricky to get right. Alternatively we could lint for all instances of z-index / zIndex and force a lint disable comment explaining why it is needed and how it is contained.

There is an open tech debt issue in Memex on the same topic where I outline a set of rules that we can universally follow. We can document this in a flowchart:

flowchart TD
    A[Does this need to render<br> over the entire application?]
    A -->|Yes| B
    A -->|No| C
    B(Use <code>Portal</code> to render into<br> the default <code>primerPortalRoot</code>)
    C[Can you rearrange the DOM to<br> control stacking?]
    C -->|Yes| D
    C -->|No| E
    D(Render the element that should<br> be on top last in the DOM)
    E(Use <code>z-index</code> and also apply <code>isolation: isolate</code><br> to the component's container)
Loading

Alternatively, maybe we can create a new Primer abstraction to help with this? Just thinking out loud here, but maybe some sort of context provider that also acts as a stacking context container, like so:

const AvatarStackingContext = createStackingContext()

const AvatarStack = (users) => (
  <AvatarStackingContext.Container>
    {users.map((user, i) => (
      <AvatarStackingContext.Layer level={users.length - i} key={user.login}>
        <Avatar user={user} />
      </AvatarStackingContext.Layer>
    )}
  </AvatarStackingContext.Container>
)

It's verbose, but maybe it's worth it for the explicit management of stacking here? Maybe we can make it more intuitive with named layers, or validate the layers somehow (maybe only allow each layer number to be used once). Then we could ban z-index entirely. Or maybe it's overkill and we should just use isolation: isolate 🤷.

@iansan5653 iansan5653 added this pull request to the merge queue Feb 21, 2023
Merged via the queue into main with commit 0c70192 Feb 21, 2023
@iansan5653 iansan5653 deleted the button-group-isolation branch February 21, 2023 21:52
@primer-css primer-css mentioned this pull request Feb 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants