Implementing Dynamic Tone & Intensity Styles
Let's make the
tone prop and the
impact prop work together.
tone prop has three values:
We want to combine this with the
impact variants for
default tone should take the same color as the current one, which is `
Instructor: 0:00 Let's make the tone prop and the impact prop work together. Our new tone prop has three values -- default, danger, and success. We want to combine this with the impact -- bold, light or none, possible values.
0:13 Scrolling down, I'll remove some of this comment here to have a bit more space. You can see, the default tone should take the same color as the current one, which is the indigo. Then, the danger would have red with the same number shades, and success will have green with the same number shades.
0:29 We want to satisfy our new impactClasses shape, which is a Record where the keys are the tone prop, so default, danger, success. Then the values, instead of strings, are a new Record key-value pair, where each key is the impact, so bold, light and none.
0:45 If I press Ctrl+space, we should see the tone props here. We would have default, and then nested inside of this, we would have an object which has the three impact props. I could move all of that up here. This would satisfy the first default prop value. Then I can copy that a couple of times and change the keys to -- TypeScript should tell me -- danger and success.
1:11 You can see we've now achieved the correct impactClasses object expected shape. We want to keep the same shades, so 500, 600, 100, 700, etc., but we want to change the actual underlying color. We'll keep all of the default stuff to indigo, change all of the danger stuff to red, and change all of the success stuff to green.
1:37 As you can see, it's not working. We have broken all of our color styles. You can probably guess why. If I scroll down to the className attribute, for our impact classes, you can see we reach directly for the impact. Remember, impact is bold, light, or none.
1:52 We look for impactClasses.bold, for example. ImpactClasses doesn't have a bold primary key. It's nested now inside default, danger, or success. We need to reach for, first, the tone prop with the dynamic tone value, which is one of these three, and then reach out for the dynamic impact value.
2:12 Before the impact, I will first reach for the tone prop. When I hit Save, the buttons should take the exact colors that we're expecting. Check this out.
2:23 Are we done? We're not done. Look at this. If I tab through the buttons here, you can see that our tones have specific ring colors. Right now, if I continue tabbing through the buttons, check what happens. The danger tone and success tone are still using the indigo ring color. We've got to fix that.
2:45 If I scroll up here, the reason this happens is we have abstracted at the very beginning the focus colors, using the Indigo class here. Everything else can remain in the base classes. We just need to take out the focus-ring color here, so I will cut that. In our impactClasses, we need to implement this.
3:07 Now we're in a bit of a dilemma because we want our focus-ring color to be applied to all three possible impact prop. We have two options. We can copy the same focus class in all three impact variants, but you could come up with the base impactClasses string that you then compose with the rest if you really wanted to avoid having three times the same class.
3:28 It's all about finding what works for your specific requirements. Here, having the same focus-ring color three times is not a big deal. I will select the three lines and add the focus-visible-indigo-500. Then for the danger, I will paste this, but change indigo to red. Finally, for success, I will change this to green. Now when I tab through my dynamic buttons, the ring color is correct.
4:01 There you have it. We now have a Button component that composed four different style variants together. If you look at the className attribute in our Button component, everything is composed together without complexity creeping in. This is easy to read and reason about.
4:14 All our styles are composed together in a styles lookup directory, in one place, all in full strings, to play nice with the Tailwind just-in-time engine. Nice.