This is a great project! Thanks so much for making it.
While adding a high-contrast theme (as proposed by #99) would be great, I’m curious how you would feel about also improving the contrast of the default theme as well.
One component that jumped out at me was Tag. I don’t personally have any visually impairments, but I found the text of the tags in the example, particularly "Success" and "Warning", to be difficult to read.
Here are the contrast ratios (as calculated by Chrome DevTools1):

Perhaps the default theme could seek a WCAG AA rating (4.5:1 contrast or above). This would still leave plenty of room for the high-contrast theme to achieve a WCAG AAA rating (7:1 contrast or above).
As you’re aware, the colors scales are generated with a fixed lightness at every "tier".
While the math is nice, the trouble with this approach is that _perceived_ lightness varies with hue and saturation2.
Without getting too fancy, I’ll just say that if you take the 5 colors, which currently each have their HSL lightness property set to 50% and adjust them to 35, 30, 40, 30, and 40, respectively, you get this:

I personally find that much easier to read, but still "colorful" enough that that the text doesn’t read as "plain black".
With these adjustments to the colors, the contrast ratios are 4.85, 4.54, 5.14, 4.90, and 4.91, respectively. (So all WCAG AA.) And the math is still pretty nice. ;)
I hope this was helpful!
Footnotes
Thanks for the well-written, detailed issue. I agree — the text colors were chosen rather arbitrarily and I always thought they were a bit too light. Fixed in 57b8632 per your suggestion.
While the math is nice, the trouble with this approach is that perceived lightness varies with hue and saturation2.
This is why I'm super excited for browser to support LCH colors. It would definitely make generating theme colors more consistent!
Regarding the contrast checker — how did you generate that screenshot? I can't get Chrome or Firefox to show me contrast checking. Ended up having to copy the RGB color, convert it to hex, and paste it into WebAIM. 🤷🏻♂️
That’s terrific. Thanks so much for that quick response and change! I’m happy to help with an analysis of other components as well if you’d like.
This is why I'm super excited for browser to support LCH colors. It would definitely make generating theme colors more consistent!
100% yes—I can’t wait.
Regarding the contrast checker — how did you generate that screenshot?
Heh. I was wondering if you’d mention that. __tl:dr;__ I faked it.
There are a couple of convenient ways to see contrast ratios in Chrome DevTools.
One way is to enter inspection mode, which you can enter with ⌘ ⇧ C (on macOS) or by clicking the top-left icon in the panel, depicted here:

When you enter inspection mode, you will generally get a contrast ratio in the inspection popover. Here’s an example of inspecting the h1 on example.com:

The second way is to enter a color picker in the elements panel.

I haven’t spent too much time deeply investigating how these work under the covers, but it’s clear to me from using them, and from my general understanding of CSS, that these checkers have to make certain assumptions and don’t necessarily provide perfect results.
One assumption it has to make is what the background color is. There could be an absolutely positioned element which happens to be underneath the text that has a different background color than the getComputedStyle one, e.g. In general, any sort of layering or opacity can make it inaccurate (in terms of the perceived contrast).
Most relevant to your question, in the case of inspecting elements, the popover _doesn’t always show the contrast ratio_. I would bet there is a heuristic or a set of checks that it goes through, and if a certain condition isn’t met (so it thinks it can’t provide an accurate result), it aborts.
In the case of the Tag component, when you inspect the sl-tag element itself, you get an inaccurate result (in terms of perception) due to it using the inherited document text/background color:

When inspecting the inner <span> elements, the contrast doesn’t show:


So, I faked it. I copied the color/background-color from the inner <span> elements onto the sl-tag element, then inspected each and screenshotted the results, then finally cropped/arranged the screenshots.
If I had to guess, the issue with the inspector in this case has to do with the shadow DOM, and the additional complexities around layering that introduces. But that’s just a guess.
It’s unfortunate that this is case, but then again I’m so happy DevTools added the convenience of contrast ratio checking in the first place! So I can’t complain. ☺️ I would also bet the folks who made it know about its shortcomings and are working on improving it.
Thanks again for making the change!
That's awesome. Thanks for taking the time to do it!
And as much as I've used "inspect," I never noticed that contract checker. 🤦🏻♂️
I’m happy to help with an analysis of other components as well if you’d like.
Forgot to mention that this would be great. The default theme should be AA for anything important. We'll save AAA for the high-contrast theme.
Amazing, that sounds great.
The Tab component is another low-hanging fruit for me:

What do you think would be the best way to tackle the work of making these changes in general?
If it's a logical change, go ahead and submit a PR. If it's something that merits discussion (e.g. too drastic, doesn't look good, etc.), feel free to post an issue instead.
If you're not comfortable submitting PRs, I'm happy to make the changes myself if you provide a list of before/after values. 😄
To complete the work of making the core default theme components WCAG AA, assuming 5% lightness intervals, we’d need to make the following changes:
_The following numbers represent the new lightness value needed for the HSL colors, as changed from 50%:_
__WCAG AA:__
Tab (active state)Button and BadgeFor Tab I think this change is great.
For Button and Badge however, I think we may not be particularly satisfied with the look.
After some experimentation, looking at the contrast ratios, I feel pretty good about at least the following compromise:
__Compromise:__
Button and BadgeIn some cases these come very close to AA.
So I’d recommend trying the full WCAG AA changes above, but if after seeing those, the colors seem too dark, the compromise values (5% lower in each case) would be a welcome alternative.
The rest of the components look great.
For visual reference, here are the original colors:

Here are the AA compliant adjustments:

And here are the close-to-compliant adjustments:

While I feel that having AA compliance is a great goal, I don't think I'm comfortable with such a drastic change for these components. Some of the buttons look very dull to me, and they almost seem like they're depressed without interacting with them.
I'm open to tweaking other HSL values if necessary, so if anyone has design suggestions here I'd love to see some AA-compliant examples that look good throughout.
I'm also curious what other mainstream design systems and component libraries are doing in this regard. (Are they AA, close, or are they ignoring it?)
I'll have to think on this one a bit.
I do agree that the current primary and the success colors are a bit bright, at least. 🤔
Bootstrap comes close, with their lowest button scoring ~3.9. Something they do which helps is use a dark text color for the "warning" type.

Github’s comment button on this thread fails, at ~3.2.

So you’re in good company ;) I think we all can do better on this though.
A couple of my recent projects, including e.g. https://isbgpsafeyet.com, and https://web.scraper.workers.dev, use a UI library I’ve been privately building for some time, which I hope to open-source. Both of those sites exceed AA, nearing AAA for the crucial elements. And IMHO, they look pretty good.
That being said, the UI library defaults I have right now are still not so great, which is one of the reasons I still haven’t open-sourced it yet. So I totally can relate to how tough it can be for a more generic, less-opinionated, library to achieve AA out of the box.
Part of my interest in this project is actually that since it overlaps somewhat my own work, I’m hopeful that working with you and other upcoming component library authors, I can help the broader community solve these problems together, and move us all in a good direction.
It’s likely the case that some of the “hot” or “flashy” designs we’re used to from the last decade will need to be modified. Personally, for properties I design, it’s an easy to choice to improve color contrast at the potential cost of not having the “hottest” design. That being said, not every project has the same requirements: e.g. a personal project someone builds for a tablet display to be used in just their own home only needs to work for them.
Anything we can all do together is still _something_, and I think it’s good for us to challenge ourselves to come up with creative new designs that are accessible to everyone. There are definitely often tradeoffs here though, and I accept that it’s not always possible to please everyone.
I sincerely appreciate your thoughtful responses, and I’m excited to see Shoelace iterate over time. Cheers
So you’re in good company ;) I think we all can do better on this though.
I agree. We can do better as designers. Screen readers (et al) can do better as assistive technologies. I feel like there's a point where we can all converge, but I don't think it should sacrifice creativity nor make things less appealing for the majority of users.
Having a high-contrast theme would be a great start. If we can provide users an easy way to offer it to _their_ users, the default theme probably doesn't need to be held to the same standard. Not that we shouldn't care about it, but some of the creative restrictions can be relaxed.
I'd love to get to a point where there's an AA-compliant theme that's very similar to the default theme, then users can choose based on their needs and requirements. Maybe it can be enabled by default through prefers-contrast if that gets standardized and implemented.
I'm going to leave this open to encourage discussion. Thanks again for taking the time to research this!
Try to make the star rating component accessible.
yellow is impossible, it would have to be changed to dark orange or red.
It's a shame because everything looks uglier
With the color update that occurred in #283, contrast was improved a bit in most of the areas discussed in this thread. I'm still hoping to get around to designing a high-contrast theme (follow #99 for details), but for now I think I'm happy with where the default theme is.
If there are blatant contrast issues moving forward then feel free to post a new issue. 😄