-
Notifications
You must be signed in to change notification settings - Fork 30
ValuesWithChange
Election Trackers Component
#13920
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
Conversation
Adds a new election trackers component to display a list of values and the amount by which they've changed. This could be used, for example, to display a list of seats won in an election along with the changes since the last election. The included stories show examples of this. This component is one of several that will allow rendering election trackers within DCAR.
Hello 👋! When you're ready to run Chromatic, please apply the You will need to reapply the label each time you want to run Chromatic. |
Size Change: +283 B (+0.03%) Total Size: 974 kB
ℹ️ View Unchanged
|
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.
Looks good 👍 Just left a few questions
gridTemplateColumns: 'repeat(auto-fill, minmax(84px, 1fr))', | ||
rowGap, | ||
'--column-gap': '10px', | ||
columnGap: 'var(--column-gap)', |
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.
How come for row-gap we are using rowGap const defined on line 57 but for column-gap we're doing it differently?
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.
Although both are used in multiple places, the value of row gap never changes whereas the column gap needs to vary by breakpoint (line 80). By setting it as a CSS variable we can use it in multiple places and have it automatically update when changed via the media query here.
<li | ||
style={{ | ||
'--before-background-colour': value.colour, | ||
}} |
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.
Just wondering why it's necessary to add the style
prop here? Can we not directly use the value.colour
in backgroundColour
? like this: backgroundColor: value.colour,
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.
The background colour is an example of what Emotion refers to as a "dynamic style", i.e. a style that's likely to be unique to each single instance of a component (an element)1.
Most of the properties passed here to the css
prop are "static" styles, common to all instances of the Value
component; every instance will have white-space: nowrap
and position: relative
. However, because the colour used for background-color
comes from the value
prop, it can be different every time the component is called with a different set of props (and it is different, because each party in an election typically has a different colour representing it). This means that the background-color
declaration will be different for every instance of the component.
Emotion generates a new class and CSS rule for each unique collection of styles. In this case, even though most of the declarations are the same, because that one background-color
declaration is different, a new CSS rule is generated each time. If you were to pass background-color
directly to the css
prop you'd see this in the DOM; each li
in this list would have a different class. This generates duplicate CSS and thus increases page weight.
<style>
.list-item-1 {
white-space: nowrap;
position: relative;
background-color: blue;
}
.list-item-2 {
white-space: nowrap;
position: relative;
background-color: red;
}
</style>
<ul>
<li class="list-item-1">Blue element</li>
<li class="list-item-2">Red element</li>
</ul>
The solution to this is to put every CSS declaration that's common to all instances of a component (the "static" styles) in the css
prop, and any that are not (the "dynamic styles") in the style
prop. That way a single class and CSS rule can be shared across all instances of the component, and only the unique, dynamic styles create additional CSS in the page. You can see this in the DOM for these list items; each one has the same class, and only the style
attributes contain the different background-color
s. Generally speaking I think you can differentiate whether something should be a static or dynamic style by checking if it's derived from a prop; if it is then it's dynamic, if not then it's probably static.
<style>
.list-item {
white-space: nowrap;
position: relative;
}
</style>
<ul>
<li class="list-item" style="background-color: blue;">Blue element</li>
<li class="list-item" style="background-color: red;">Red element</li>
</ul>
The simpler cases of this pattern can be seen in #13921, in the Bar
and ChangeText
components, where some different styles are applied based on the value of the change
prop. The case above though is slightly more complicated because you cannot style pseudo-elements2 like ::before
3 with inline styles, i.e. via the style
prop. Instead you can write the full ::before
rule as static styles via the css
prop, but defer the value of background-color
to a CSS variable4. This is then set as a dynamic style derived from the props.
<style>
.list-item {
white-space: nowrap;
position: relative;
}
.list-item::before {
background-color: var(--before-background-colour);
}
</style>
<ul>
<li class="list-item" style="--before-background-colour: blue;">Blue element</li>
<li class="list-item" style="--before-background-colour: red;">Red element</li>
</ul>
Footnotes
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.
Thanks so much for this thorough explanation. It makes full sense and a great learning for me 👌
css={{ | ||
['&']: css(headlineBold24), | ||
lineHeight: 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.
Could this have been written like this as well?
css={[
headlineBold24,
{
lineHeight: 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.
Yes, and I have written it like that in the past. I just figured out that it could also be written like this, and I thought it was perhaps a little clearer using the commonly recognised nesting selector (&
), and having everything in one object rather than an array. It also means less indentation, and I think makes it a little easier to read in situations where you also have media queries (see the Abbreviation
and ChangeText
components in #13921).
What do you think?
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.
Each of the presets has an object version so you should be able to spread the properties like so:
css={{
...headlineBold24Object,
lineHeight: 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.
This is a great suggestion, I didn't realise we had this API, thanks @jamesmockett !
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.
Nice, yea I agree having an object rather than an array looks easier to read 👍
Source has an object styles API for fonts, which integrates better with the object styles in this component.
Adds a new election trackers component to display a list of values and the amount by which they've changed. This could be used, for example, to display a list of seats won in an election along with the changes since the last election. The included stories show examples of this. This component is one of several that will allow rendering election trackers within DCAR.
Seen on PROD (merged by @JamieB-gu 8 minutes and 48 seconds ago) Please check your changes! |
Adds a new election trackers component to display a list of values and the amount by which they've changed. This could be used, for example, to display a list of seats won in an election along with the changes since the last election. The included stories show examples of this.
This component is one of several that will allow rendering election trackers within DCAR.
Screenshots