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

fix: remove color-context JS in favor of color-scheme and light-dark() #2138

Draft
wants to merge 35 commits into
base: main
Choose a base branch
from

Conversation

zeroedin
Copy link
Collaborator

@zeroedin zeroedin commented Jan 22, 2025

What I did

  1. This is an exploration of using color-scheme as the basis for our context color switching. By utilizing the light-dark() color function, we can reduce the overhead of additional Javascript that is not currently providing any more functionality than what these CSS properties and the cascade can do.

TODO

  • Update tests
    • rh-surface tests: Since context is removed, JS eventing is no longer present, these tests need to be re-evaluated to determine how we would approach them. Surface is now only a passive element that sets a parent color-scheme. I'm unsure how much testing we'd want to do here as it would be mainly style testing which we've tended to avoid doing.
    • rh-badge tests in this component and in any component tests that include testing of CSS properties contained in color-scheme.css. will need to be updated to include those CSS in the test fixture output.

Testing Instructions

  1. View the Deploy preview

Notes to Reviewers

Some components had their CSS modified to accommodate this approach. Avatar and Breadcrumbs used the .dark consumer class to swap images. I took a couple of different approaches in this PR.

In Avatar, the default SVG was swapped in the render() based on context; in this PR, it now styles the SVG internals using light-dark() and just loads a single SVG in the render(), no swapping necessary.

Breadcrumbs used data URI SVG and swapped the URI based on the .dark class. Unfortunately, we can not use light-dark() to swap a background image, so instead, I used the data URI SVG as a mask and then used light-dark() to style the background color the mask cuts out. Same result, different approach.

Other than that, the addition of the color-scheme.css is necessary. My assumption is that maybe this file could be served by the tokens repo as part of global.css or as a separate file.

Please think about these changes and future-forward feature sets that will be here soon (i.e., style queries). Am I missing something? Is there potential where this doesn't work?

In this PR, I personally did not find a current use case that it doesn't work, only places we needed to take a slightly different approach mentioned above.

@zeroedin zeroedin added the feature New feature or request label Jan 22, 2025
@zeroedin zeroedin requested a review from bennypowers January 22, 2025 20:33
@zeroedin zeroedin self-assigned this Jan 22, 2025
Copy link

changeset-bot bot commented Jan 22, 2025

⚠️ No Changeset found

Latest commit: a95f9d8

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

Copy link

netlify bot commented Jan 22, 2025

Deploy Preview for red-hat-design-system ready!

Name Link
🔨 Latest commit a95f9d8
🔍 Latest deploy log https://app.netlify.com/sites/red-hat-design-system/deploys/6793ab7e4e57920008e7b2b6
😎 Deploy Preview https://deploy-preview-2138--red-hat-design-system.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link
Contributor

github-actions bot commented Jan 22, 2025

Size Change: -3.4 kB (-1.65%)

Total Size: 203 kB

Filename Size Change
./elements/rh-accordion/rh-accordion-header.js 2.65 kB -45 B (-1.67%)
./elements/rh-accordion/rh-accordion-panel.js 1.38 kB +24 B (+1.77%)
./elements/rh-accordion/rh-accordion.js 3.39 kB +178 B (+5.54%) 🔍
./elements/rh-alert/rh-alert.js 4.21 kB -45 B (-1.06%)
./elements/rh-audio-player/rh-audio-player-scrolling-text-overflow.js 1.47 kB -66 B (-4.31%)
./elements/rh-audio-player/rh-audio-player.js 13 kB -102 B (-0.78%)
./elements/rh-avatar/rh-avatar.js 2.64 kB -213 B (-7.47%)
./elements/rh-badge/rh-badge.js 1.5 kB -50 B (-3.22%)
./elements/rh-blockquote/rh-blockquote.js 1.29 kB -62 B (-4.57%)
./elements/rh-breadcrumb/rh-breadcrumb.js 996 B -507 B (-33.73%) 🎉
./elements/rh-button/rh-button.js 3.28 kB -960 B (-22.63%) 🎉
./elements/rh-card/rh-card.js 3.46 kB -113 B (-3.16%)
./elements/rh-code-block/rh-code-block.js 7.16 kB -184 B (-2.51%)
./elements/rh-cta/rh-cta.js 4.02 kB -13 B (-0.32%)
./elements/rh-footer/rh-footer-universal.js 3.92 kB -67 B (-1.68%)
./elements/rh-footer/rh-footer.js 4.85 kB -108 B (-2.18%)
./elements/rh-health-index/rh-health-index.js 2.31 kB -45 B (-1.91%)
./elements/rh-menu/rh-menu.js 1.16 kB -130 B (-10.05%) 👏
./elements/rh-navigation-secondary/rh-navigation-secondary-menu.js 1.76 kB +11 B (+0.63%)
./elements/rh-navigation-secondary/rh-navigation-secondary.js 5.27 kB +8 B (+0.15%)
./elements/rh-pagination/rh-pagination.js 5.36 kB -45 B (-0.83%)
./elements/rh-site-status/rh-site-status.js 2.42 kB -80 B (-3.21%)
./elements/rh-spinner/rh-spinner.js 1.36 kB -22 B (-1.59%)
./elements/rh-stat/rh-stat.js 2.09 kB -47 B (-2.2%)
./elements/rh-subnav/rh-subnav.js 2.62 kB -107 B (-3.92%)
./elements/rh-surface/rh-surface.js 1.11 kB -33 B (-2.89%)
./elements/rh-switch/rh-switch.js 2.9 kB -25 B (-0.85%)
./elements/rh-table/rh-sort-button.js 1.46 kB -28 B (-1.88%)
./elements/rh-table/rh-table.js 3.46 kB -25 B (-0.72%)
./elements/rh-tabs/rh-tab-panel.js 925 B -120 B (-11.48%) 👏
./elements/rh-tabs/rh-tab.js 2.95 kB -64 B (-2.12%)
./elements/rh-tabs/rh-tabs.js 3.91 kB +143 B (+3.79%)
./elements/rh-tag/rh-tag.js 2.62 kB -167 B (-5.99%)
./elements/rh-tile/rh-tile.js 5.08 kB -13 B (-0.26%)
./elements/rh-tooltip/rh-tooltip.js 2.68 kB -46 B (-1.68%)
./elements/rh-video-embed/rh-video-embed.js 4.51 kB -71 B (-1.55%)
./lib/elements/rh-context-demo/rh-context-demo.js 1.2 kB -85 B (-6.61%)
./lib/elements/rh-context-picker/rh-context-picker.js 2.16 kB -79 B (-3.53%)
ℹ️ View Unchanged
Filename Size
./elements.js 473 B
./elements/rh-accordion/context.js 162 B
./elements/rh-audio-player/rh-audio-player-about.js 1.8 kB
./elements/rh-audio-player/rh-audio-player-rate-stepper.js 1.85 kB
./elements/rh-audio-player/rh-audio-player-subscribe.js 1.38 kB
./elements/rh-audio-player/rh-cue.js 1.95 kB
./elements/rh-audio-player/rh-transcript.js 2.7 kB
./elements/rh-avatar/random-pattern-controller.js 2.72 kB
./elements/rh-back-to-top/rh-back-to-top.js 2.1 kB
./elements/rh-code-block/prism.css.js 667 B
./elements/rh-code-block/prism.js 572 B
./elements/rh-dialog/rh-dialog.js 4.78 kB
./elements/rh-dialog/yt-api.js 617 B
./elements/rh-footer/rh-footer-block.js 714 B
./elements/rh-footer/rh-footer-copyright.js 362 B
./elements/rh-footer/rh-footer-links.js 1.17 kB
./elements/rh-footer/rh-footer-social-link.js 964 B
./elements/rh-icon/rh-icon.js 2.47 kB
./elements/rh-icon/ssr.js 181 B
./elements/rh-navigation-secondary/rh-navigation-secondary-dropdown.js 2.47 kB
./elements/rh-navigation-secondary/rh-navigation-secondary-menu-section.js 1.3 kB
./elements/rh-navigation-secondary/rh-navigation-secondary-overlay.js 571 B
./elements/rh-navigation-secondary/test/fixtures.js 769 B
./elements/rh-skip-link/rh-skip-link.js 1.19 kB
./elements/rh-surface/test/elements.js 423 B
./elements/rh-tabs/context.js 160 B
./elements/rh-tile/rh-tile-group.js 1.81 kB
./elements/rh-timestamp/rh-timestamp.js 983 B
./lib/context/color/consumer.js 1.41 kB
./lib/context/color/controller.js 947 B
./lib/context/color/provider.js 2.18 kB
./lib/context/event.js 593 B
./lib/context/headings/consumer.js 722 B
./lib/context/headings/controller.js 1.12 kB
./lib/context/headings/provider.js 1.24 kB
./lib/DirController.js 565 B
./lib/environment.js 194 B
./lib/functions.js 175 B
./lib/I18nController.js 1.38 kB
./lib/ScreenSizeController.js 849 B
./lib/ssr-controller.js 251 B
./react/rh-accordion/rh-accordion-header.js 199 B
./react/rh-accordion/rh-accordion-panel.js 185 B
./react/rh-accordion/rh-accordion.js 215 B
./react/rh-alert/rh-alert.js 184 B
./react/rh-audio-player/rh-audio-player-about.js 191 B
./react/rh-audio-player/rh-audio-player-rate-stepper.js 213 B
./react/rh-audio-player/rh-audio-player-scrolling-text-overflow.js 214 B
./react/rh-audio-player/rh-audio-player-subscribe.js 196 B
./react/rh-audio-player/rh-audio-player.js 183 B
./react/rh-audio-player/rh-cue.js 195 B
./react/rh-audio-player/rh-transcript.js 207 B
./react/rh-avatar/rh-avatar.js 173 B
./react/rh-back-to-top/rh-back-to-top.js 183 B
./react/rh-badge/rh-badge.js 174 B
./react/rh-blockquote/rh-blockquote.js 179 B
./react/rh-breadcrumb/rh-breadcrumb.js 179 B
./react/rh-button/rh-button.js 174 B
./react/rh-card/rh-card.js 172 B
./react/rh-code-block/rh-code-block.js 181 B
./react/rh-cta/rh-cta.js 170 B
./react/rh-dialog/rh-dialog.js 203 B
./react/rh-footer/rh-footer-block.js 184 B
./react/rh-footer/rh-footer-copyright.js 187 B
./react/rh-footer/rh-footer-links.js 185 B
./react/rh-footer/rh-footer-social-link.js 193 B
./react/rh-footer/rh-footer-universal.js 188 B
./react/rh-footer/rh-footer.js 174 B
./react/rh-health-index/rh-health-index.js 184 B
./react/rh-icon/rh-icon.js 202 B
./react/rh-menu/rh-menu.js 173 B
./react/rh-navigation-secondary/rh-navigation-secondary-dropdown.js 217 B
./react/rh-navigation-secondary/rh-navigation-secondary-menu-section.js 205 B
./react/rh-navigation-secondary/rh-navigation-secondary-menu.js 199 B
./react/rh-navigation-secondary/rh-navigation-secondary-overlay.js 201 B
./react/rh-navigation-secondary/rh-navigation-secondary.js 213 B
./react/rh-pagination/rh-pagination.js 178 B
./react/rh-site-status/rh-site-status.js 181 B
./react/rh-skip-link/rh-skip-link.js 181 B
./react/rh-spinner/rh-spinner.js 175 B
./react/rh-stat/rh-stat.js 171 B
./react/rh-subnav/rh-subnav.js 175 B
./react/rh-surface/rh-surface.js 175 B
./react/rh-switch/rh-switch.js 185 B
./react/rh-table/rh-sort-button.js 213 B
./react/rh-table/rh-table.js 174 B
./react/rh-tabs/rh-tab-panel.js 181 B
./react/rh-tabs/rh-tab.js 187 B
./react/rh-tabs/rh-tabs.js 174 B
./react/rh-tag/rh-tag.js 182 B
./react/rh-tile/rh-tile-group.js 183 B
./react/rh-tile/rh-tile.js 194 B
./react/rh-timestamp/rh-timestamp.js 176 B
./react/rh-tooltip/rh-tooltip.js 175 B
./react/rh-video-embed/rh-video-embed.js 227 B
./uxdot/uxdot-best-practice.js 742 B
./uxdot/uxdot-copy-button.js 1.2 kB
./uxdot/uxdot-copy-permalink.js 1.1 kB
./uxdot/uxdot-example.js 1.17 kB
./uxdot/uxdot-feedback.js 727 B
./uxdot/uxdot-header.js 1.07 kB
./uxdot/uxdot-hero.js 679 B
./uxdot/uxdot-installation-tabs.js 675 B
./uxdot/uxdot-masthead.js 809 B
./uxdot/uxdot-pattern-ssr-controller-client.js 604 B
./uxdot/uxdot-pattern-ssr-controller-server.js 1.68 kB
./uxdot/uxdot-pattern-ssr-controller.js 213 B
./uxdot/uxdot-pattern.js 2.12 kB
./uxdot/uxdot-repo-status-checklist.js 1.16 kB
./uxdot/uxdot-repo-status-list.js 1.07 kB
./uxdot/uxdot-repo-status-table.js 782 B
./uxdot/uxdot-repo.js 1.17 kB
./uxdot/uxdot-search.js 2.39 kB
./uxdot/uxdot-sidenav.js 2.67 kB
./uxdot/uxdot-spacer-tokens-table.js 2.45 kB
./uxdot/uxdot-toc.js 1.13 kB

compressed-size-action

@bennypowers
Copy link
Member

Really impressive!

  • Shouldn't we use only for when color-palette is applied, and light dark when it's absent? This could be in a shared stylesheet
  • Instead of putting the light-dark() switch in every element, at evey callsite, it should be in the shared style sheet exported from tokens, element sheets would continue to reference the computed values. It could be that the only changes necessary in element sheets should be selectors (i.e. .on.dark)
  • We might just be able to get away with making this a minor or even patch release, due to previous design choices for the apis like insisting on private on

@zeroedin
Copy link
Collaborator Author

  • Shouldn't we use only

Yes looks like we should.

Instead of putting the light-dark() switch in every element, at evey callsite, it should be in the shared style sheet exported from tokens, element sheets would continue to reference the computed values.

Yes need to go through the changes I've made here with a fine tooth comb and ensure the changes in the element sheets can't be replaced with the computed value already present in color-scheme.css. I went through pretty quickly mainly looking for 'gotchas' that would disprove the idea.

  • We might just be able to get away with making this a minor or even patch release

That was my take away with the changes made, that there wasn't anything fundamentally changing for the user.

@zeroedin
Copy link
Collaborator Author

  • We might just be able to get away with making this a minor

Thinking about this more, what if someone has written a 3rd party component that relies on rh-surface to provide the context? Because rh-surface in this PR no longer provides this through an event could that be considered a breaking change for external usage? Is there a need to deprecate the JS portion and still have it available?

@bennypowers
Copy link
Member

gotchas

dark-alt, saturated, and base are your gotchas. of the three, dark-alt is the only one in current use. that's why it needs to be removed and replaced with colour transforms in oklch. The existence of dark-alt screws with the maths of the rest of the theming system. cc @marionnegp @coreyvickery

@bennypowers
Copy link
Member

  • We might just be able to get away with making this a minor

Thinking about this more, what if someone has written a 3rd party component that relies on rh-surface to provide the context? Because rh-surface in this PR no longer provides this through an event could that be considered a breaking change for external usage? Is there a need to deprecate the JS portion and still have it available?

I'm preemptively invalidating that user's abuse of the context system.

@zeroedin
Copy link
Collaborator Author

I'm preemptively invalidating that user's abuse of the context system.

I'm even just talking about this:

<rh-surface>
  <random-element> <!-- is a @colorContextConsumer() -->
</rh-surface>

If we say surface no longer provides the means to satiate @colorContextConsumer() and that they need to update their component to use light-dark() internally instead. While it's not breaking internally to RHDS it may lead to 3rd party components no longer working without the upgrade warning of a breaking, yes? no?.

@zeroedin
Copy link
Collaborator Author

zeroedin commented Jan 23, 2025

dark-alt, saturated, and base are your gotchas

These 3 things are not "gotchas" from my position.

If anything, saturated and base might really be themes; I don't think they are context (light, dark). Also, we haven't even implemented those anywhere; it's been a fragment of an idea from inception from my point of view. Definitely, it's something to clarify between us and design, and I look forward to those conversations.

dark-alt as a "surface" color is a strange bird indeed as it is currently not tied to "provider" [color-palette] attr. But, AFAIK, it is usually directly applied in specific instances rather than using a light-dark computed value. I think that is likely 'ok'. Do we want a color-palette="dark-alt"? Maybe not, but we could do that if we really find it necessary; just not sure it is at this time.

@bennypowers
Copy link
Member

I'm preemptively invalidating that user's abuse of the context system.

I'm even just talking about this:

<rh-surface>
  <random-element> <!-- is a @colorContextConsumer() -->
</rh-surface>

If we say surface no longer provides the means to satiate @colorContextConsumer() and that they need to update their component to use light-dark() internally instead. While it's not breaking internally to RHDS it may lead to 3rd party components no longer working without the upgrade warning of a breaking, yes? no?.

could be, but i sincerely doubt this is a real case in the wild

If anything, saturated and base might really be themes;

100%. they should be removed from the context system and treated as themes

dark-alt ... if we really find it necessary;

the reasons we find it necessary are for contrast in specific scenarios: a better solution is colour transforms in oklch

@zeroedin
Copy link
Collaborator Author

a better solution is colour transforms in oklch

Yeah, if you are just suggesting the removal of dark-alt and converting dark with a transform for those cases, I'm all for that as well.

@marionnegp
Copy link
Collaborator

Do we want a color-palette="dark-alt"? Maybe not, but we could do that if we really find it necessary; just not sure it is at this time.

This might be a dumb question, but if we don't add it as a color palette, does this prevent us from using it as a surface token in an element?

If anything, saturated and base might really be themes;

100%. they should be removed from the context system and treated as themes

Agreed. We may have a need for more than just light and dark theme in the future, but right now, designers are focusing on getting at least those two themes working for stuff like docs.redhat.com. Better to tackle any saturated or base theming later.

Thinking about this more, what if someone has written a 3rd party component that relies on rh-surface to provide the context? Because rh-surface in this PR no longer provides this through an event could that be considered a breaking change for external usage? Is there a need to deprecate the JS portion and still have it available?

I'm preemptively invalidating that user's abuse of the context system.

Should rh-surface be used only to give RHDS elements and patterns context ideally?

Comment on lines +15 to +17
color:
light-dark(var(--rh-color-text-primary-on-dark, #ffffff),
var(--rh-color-text-primary-on-light, #151515));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
color:
light-dark(var(--rh-color-text-primary-on-dark, #ffffff),
var(--rh-color-text-primary-on-light, #151515));
color: var(--rh-color-text-primary);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file should

  1. live in the tokens repo
  2. be generated through style dictionary build there
  3. have two flavours: :host([color-palette=whatev]) for shadow and [color-palette=whatev] for light (not super sure about the lightdom one...)

@zeroedin zeroedin changed the title [POC] Remove color-context JS in favor of color-scheme and light-dark() fix: remove color-context JS in favor of color-scheme and light-dark() Jan 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

3 participants