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

Add Theme Support 🎨 #10391

Merged
merged 187 commits into from
Feb 25, 2025
Merged

Add Theme Support 🎨 #10391

merged 187 commits into from
Feb 25, 2025

Conversation

thsparks
Copy link
Contributor

@thsparks thsparks commented Feb 19, 2025

Overview

This is a first pass at adding color theme support for arcade (and other targets in the future).

See the theme README.md file (theme\color-themes\README.md) for details on what each theme variable is for. They are loosely based on fluentUI, though of course, we have a much smaller set to deal with.

Upload Target: https://arcade.makecode.com/app/8ff7826fe1b820f3793c301c11dabf0ce5bcfdc0-0927214d31

Key Areas

Most of this change is just updating colors, but here are a few spots that deserve special attention:

  1. react-common\components\theming\themeManager.ts - this is what handles actual theme-related operations
  2. cli\cli.ts - this is where theme json is added to the target bundle
  3. webapp\src\app.tsx & pxtlib\auth.ts -> loading / saving themes
  4. react-common\components\theming\ThemePickerModal.tsx & related elements

How It Works

In short, when a user changes themes, we swap out the variable definitions and apply any override css directly on a theme-override style element in the document head (we create it if it does not exist). See the ThemeManager for implementation.

A Few Shortcuts I Took

  1. I considered going through and scanning all uses of @ color variables, but it was too much. I'm planning to just address these as bug fixes if/when we notice issues.
  2. I considered doing away with the color css classes too (red/green/teal/etc…) just because they seem so tightly integrated with semantic ui and run vaguely counter to the idea of theming in general…but I think they are actually quite helpful in some scenarios, so I've left them in and overridden them instead. (Also, it'd be infeasible and likely undesirable to go through each one and create bespoke classes related to the specific component.)
  3. A proper high contrast theme in this new infrastructure will require taking all the .hc and .high-contrast css adjustments and putting them into the overrides file. This will be a significant chunk of work, so for now I've added a workaround that just add those css classes when switching to the hc theme specifically.

Additional Notes

  1. The term "theme" is used all over the codebase, so I've used "color theme" when I felt there was a risk of confusion.
  2. We decided to go with all css theme variables (as opposed to less) so they can be swapped out at runtime, no need for less compilation.
  3. Since semantic UI has its own way of theming that is less flexible for switching at runtime, I had to override quite a lot of semantic UI styling. I've tried to encapsulate all of this in a single react-common\styles\semantic-ui-overrides.less file. I think this was still less work than removing semantic UI altogether. But it certainly isn't tidy. I didn't want to use !important all over the place, so I've opted for using weirdly specific css selectors instead.
  4. I don't love adding a "tertiary" type alongside primary/secondary, but there were enough places where one version of the app used primary and another used secondary that it made sense to create a third option which accounted for that. The alternative was a adding bunch of css overrides to maintain consistency with existing styles, which seemed less ideal to me.
  5. I haven't made any changes for kiosk, but I also didn't notice any issues testing locally, so I'm planning to leave it as-is for now.

Remaining Work (after PR)

  1. Better dark theme. Toolbox color contrast will also be a challenge here...
  2. Make high contrast theme work without hc/high-contrast root classes

@abchatra
Copy link
Collaborator

Awesome to see this. Ok to assign copilot to review this change (I am curious what it will do) ?

@thsparks
Copy link
Contributor Author

Awesome to see this. Ok to assign copilot to review this change (I am curious what it will do) ?

Sure, I'll assign it

@thsparks thsparks requested a review from Copilot February 24, 2025 17:33
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot reviewed 106 out of 120 changed files in this pull request and generated 1 comment.

Files not reviewed (14)
  • react-common/styles/controls/Button.less: Language not supported
  • react-common/styles/controls/Card.less: Language not supported
  • react-common/styles/controls/DraggableGraph.less: Language not supported
  • react-common/styles/controls/Dropdown.less: Language not supported
  • react-common/styles/controls/EditorToggle.less: Language not supported
  • react-common/components/controls/TeachingBubble.tsx: Evaluated as low risk
  • react-common/components/controls/Modal.tsx: Evaluated as low risk
  • react-common/components/profile/SignInModal.tsx: Evaluated as low risk
  • react-common/components/Notification.tsx: Evaluated as low risk
  • pxtlib/auth.ts: Evaluated as low risk
  • react-common/components/share/ShareInfo.tsx: Evaluated as low risk
  • pxteditor/editorcontroller.ts: Evaluated as low risk
  • pxtservices/editorDriver.ts: Evaluated as low risk
  • gulpfile.js: Evaluated as low risk
Comments suppressed due to low confidence (1)

react-common/components/theming/themeManager.ts:115

  • The use of DOMPurify.sanitize on the programmatically generated CSS string is unnecessary and might strip out necessary CSS rules. Consider removing this sanitization step.
css = DOMPurify.sanitize(css);

@thsparks thsparks merged commit 016dd9f into master Feb 25, 2025
6 checks passed
@thsparks thsparks deleted the thsparks/themes2 branch February 25, 2025 23:02
thsparks added a commit to microsoft/pxt-arcade that referenced this pull request Feb 27, 2025
This adds light, legacy, and dark themes for arcade, based on changes in microsoft/pxt#10391

It also bumps pxt-core to get those changes.
thsparks added a commit to microsoft/pxt-microbit that referenced this pull request Mar 5, 2025
The new theming changes in pxt (microsoft/pxt#10391) removed some less variables and set others to css variables, which cannot be used in less color-manipulation functions (like lighten, darken, etc...). As a result, the build for microbit broke when referencing newer versions of pxt (or local).

In this change, I fix those css build errors, add a default theme, and update themepack variables to reference new theme variables. In time, we may want to fully swap over from themepack to this, but this is a stop-gap until we're focused on micro:bit again.

This isn't meant to look perfect. I mostly want to make sure everything can still build. Making it look nice is secondary, and more likely something we'll focus on when it comes time for our next micro:bit release.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants