-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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 z-index stack for .pt-button-group and .pt-control-group elements #592
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@llorca Here are some explanatory comments to guide you through the CSS rule-shuffles.
.pt-button, | ||
.pt-input, | ||
.pt-select select { | ||
.pt-select { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved from old line 107.
|
||
&:not(.pt-vertical) > * { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved this block to the bottom of the file to keep z-index-related stuff in one clump.
margin-right: -$button-border-width; | ||
} | ||
// define disabled styles last so that they override all other | ||
// equally-specific styles. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will delete one of these explanations (it's also explained in the top-level comment above).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
@@ -185,11 +340,4 @@ Styleguide components.forms.control-group | |||
border-radius: 0 0 $pt-border-radius $pt-border-radius; | |||
} | |||
} | |||
|
|||
.pt-dark & { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to line 212 to keep z-index-related rules in one clump.
|
||
> :first-child { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to line 289.
.pt-button, | ||
.pt-select { | ||
position: relative; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to the top of the file.
} | ||
|
||
&:not([readonly], :disabled, .pt-disabled):focus { | ||
z-index: 6; | ||
border-radius: $pt-border-radius; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to line 197.
|
||
// establish new stacking context so focus state covers neighbors | ||
.pt-button:focus, | ||
select:focus { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now handled with higher z-indexes in the same stacking context.
.pt-select::after { | ||
z-index: 7; | ||
z-index: $control-group-z-index-select-caret; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved the carets to a z-index all their own that explicitly sits them on top of everything, just to be absolutely safe.
@@ -54,7 +61,7 @@ | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: space-between; | |||
height: $pt-grid-size * 13; | |||
height: $pt-grid-size * 50; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels weird that we have to explicitly set a height. Why not just have docs containers expand and contract automatically with the height of the child contents?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
they should do that... casual flex box. why do you have to set a height?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's already the case. Setting a height here will evenly space out the children so there's spacing in between them. Without this line:
So what we can do instead is remove this line and add an additional rule in the same block:
.pt-control-group-example {
> .pt-control.group:not(:last-child) {
margin-bottom: $pt-grid-size * 2;
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Derp, don't know why I didn't think to try that. Thanks, @llorca.
Not opposed to adding chai-enzyme as a devDependency. Sounds like it could be useful. |
|
||
// have consecutive elements share a border | ||
&:not(.pt-vertical) > * { | ||
margin-right: -$button-border-width; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's actually only correct for light theme.
The visuals look different in dark theme, depending on whether you use a button group or single buttons for consecutive buttons (top is bad, bottom is good):
So we can keep that line for the light theme, but we need to take care of dark theme. Proposal (to be refactored in the appropriate place):
.pt-dark &:not(.pt-vertical) {
> * {
margin-right: 0;
}
> .pt-button + .pt-button {
margin-left: $button-border-width;
}
}
We also need to handle this situation in the .pt-vertical
case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed and incorporated as follows:
// have consecutive elements share a border
&:not(.pt-vertical) {
> * {
margin-right: -$button-border-width;
}
.pt-dark & {
> * {
margin-right: 0;
}
// conseuctive buttons within a button group look okay out of the box, but
// we need need to make a small correction for non-grouped buttons
> .pt-button + .pt-button {
margin-left: $button-border-width;
}
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great! For clarity, maybe also mention that we're basically replicating what's happening in dark button groups?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done 👍
// | ||
// (highest z-index) | ||
|
||
$control-group-z-index-input-disabled: 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 Qs about maintainability:
-
if our visual design changes and we ever need to update the stacking of elements in control groups, we can simply modify the values of these variables, right? No need to mess with the selectors and CSS specificities below?
-
these variables wouldn't get exported, and I'm pretty sure they wouldn't be used anywhere else. Maybe we should use a map object instead of single variables for every value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
Yep, just change the z-indexes!
-
Moving everything into a list so we can just use the
index()
helper.
@@ -38,6 +38,13 @@ | |||
|
|||
// Section-Specific Styles | |||
|
|||
#{section-id("components.button-group")} { | |||
.docs-button-group-example-set .pt-button-group { | |||
margin-top: 20px; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$pt-grid-size * 2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
@@ -54,7 +61,7 @@ | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: space-between; | |||
height: $pt-grid-size * 13; | |||
height: $pt-grid-size * 50; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's already the case. Setting a height here will evenly space out the children so there's spacing in between them. Without this line:
So what we can do instead is remove this line and add an additional rule in the same block:
.pt-control-group-example {
> .pt-control.group:not(:last-child) {
margin-bottom: $pt-grid-size * 2;
}
}
"intent-button-default", | ||
"intent-button-focus", | ||
"intent-button-hover", | ||
"intent-button-active"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i see two duplicated lists here. what happened to a single intent-boost
variable?
then you go index(list, "disabled") + $intent-boost
(pseudocode).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then you could create a mixin that wraps up lines 151-172 and reuse it in the intent block by passing a single fixed "booster" value. @include z-index-state-layers($boost)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was meant to be just an incremental change. Will play with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@giladgray chatted and worked through a potential refactor with Antoine. The intent-boost
approach works well for button groups, but it's more tricky than helpful in control groups, where differently ordered .pt-input
layers get in the way.
One approach we're considering now is to use a single list of named layers that is shared between control groups and button groups, since the relative ordering of elements doesn't actually change between the two contexts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 TLDR: 1 list with everything ($control-group-stack
or something), and button groups use a subset of that list via index()
// | ||
// (highest z-index) | ||
|
||
$-button-group-z-index-stack: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove extra -
before button
. Also, can we just go for $button-group-stack
or something simpler? Is z-index
really necessary in the name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@llorca Fixed. I ended up creating a single $control-group-stack
variable, putting it in forms/_common.scss
, and importing it into _control-group.scss
and _button-group.scss
. LMK how that looks.
margin-right: 0; | ||
} | ||
|
||
// conseuctive buttons within a button group look okay out of the box, but |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- consecutive
- dark theme
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha, fixed.
I'm a fan of this approach! Much cleaner, less code, 1 reusable list. Big comment explanation no longer needed, code speaks for itself 💯 |
<input type="text" class="pt-input" value="from:ggray to:allorca" /> | ||
<span class="pt-icon pt-icon-people"></span> | ||
<input type="text" class="pt-input pt-intent-success" placeholder="I am a text input..." style="padding-right:94px" /> | ||
<div class="pt-input-action"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.pt-input-action
shouldn't be needed when wrapping a .pt-button
. InputGroup
always uses it because it can't know about the contents but should be safe to remove in these static HTML examples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
</div> | ||
<div class="pt-control-group"> | ||
<div class="pt-input-group"> | ||
<span class="pt-icon pt-icon-people"></span> | ||
<input type="text" class="pt-input" placeholder="Find collaborators..." style="padding-right:94px" /> | ||
<input type="text" class="pt-input pt-intent-success" placeholder="I am a text input..." style="padding-right:94px" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why the placeholder change? kinda breaks the example metaphor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the development phase, it was tricky to tell at a glance what was a button and what was an input when either was disabled:
Explicit placeholder text helped with that. Totally not wedded to these examples, by the way. They're here just to allow easy testing during the development phase, but I'd prefer CSS unit tests as a longer-term solution.
<button class="pt-button pt-intent-warning">Button</button> | ||
<button class="pt-button pt-intent-success">Button</button> | ||
<button class="pt-button">Button</button> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cmslewis are we planning to ship all these example changes? on one hand, they're useful for testing, but on the other they're somewhat unsightly and are usages that we may not want to promote so visibly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On that note, the 3 examples we currently serve in the docs are more interesting indeed. Once we're confident everything looks good, let's bring back those examples, and maybe we can think of additional 1 or 2 to showcase as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, totally down to revert to our prior examples before merging.
"intent-input-focus", | ||
"input-group-children", | ||
|
||
"select-caret"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cmslewis planning to remove this in a future increment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed!
⭐️ the single stack variable approach works nicely! |
@giladgray and @llorca. LMK if this looks good to you now; if so, I'll revert to the previous examples and merge. |
// for best visual results, button group and control group elements should be | ||
// stacked in the following order to ensure sharp edges in all cases and states: | ||
|
||
$control-group-stack: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think it'd be helpful to wrap this in parens, which is the convention for an explicit sass list.
$control-group-stack: (
...
);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sweet. Doing so now.
@giladgray @llorca Oh no! When I reverted the examples to the originals, I found a caret bug on focus: Having |
// very particular order for best visual results. in each level of selector | ||
// specificity, we define disabled styles last so that they override all other | ||
// equally-specific styles (e.g. we don't want mouse interactions or focus | ||
// changes to change the z-index of a disabled element). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No official issue filed, but originally discovered problems here while working on #249 and #189
Checklist
chai-enzyme
to access computed styles for mounted React components - should we add it as a dependency?).Changes proposed in this pull request:
.pt-button-group
elements to ensure sharp edges in all cases and states:.pt-control-group
elements to ensure sharp edges in all cases and states:Reviewers should focus on:
Definitely look at the diff in "Split" mode, not "Unified" mode.
Screenshot