-
Notifications
You must be signed in to change notification settings - Fork 8
feat!: Paragon 23 and External CSS support #111
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
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
f391dc1
refactor: Move runtime react hooks into separate files
arbrandes 2119e05
feat!: Paragon 23 and External CSS support
arbrandes 5831fad
feat: Update to Node 24 and regenerate package-lock
arbrandes 385787e
fix: Build error caused by [email protected]
arbrandes File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 20 | ||
| 24 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,147 @@ | ||
| # Theming support with `@openedx/paragon` and `@openedx/brand-openedx` | ||
|
|
||
| > [!IMPORTANT] | ||
| > This document describes theming with design tokens. | ||
| > | ||
| > Information on theming MFEs that do not yet have design tokens support: | ||
| > | ||
| > - <https://github.com/openedx/brand-openedx> | ||
| > | ||
| > Information on the design tokens project: | ||
| > | ||
| > - <https://github.com/openedx/paragon/blob/release-23.x/docs/decisions/0019-scaling-styles-with-design-tokens.rst> | ||
| > - <https://github.com/openedx/paragon/tree/release-23.x?tab=readme-ov-file#design-tokens> | ||
|
|
||
| ## Overview | ||
|
|
||
| This document is a guide for using `@openedx/frontend-base` to support | ||
| theming with Paragon by loading branded CSS externally (e.g., from a CDN). | ||
|
|
||
| To do this, configured URLs pointing to relevant CSS files from | ||
| `@openedx/brand-openedx` are loaded and injected to the HTML document at | ||
| runtime. This differs from the deprecated method of importing the styles from | ||
| `@openedx/brand-openedx` directly, which includes these styles in the | ||
| application's production assets. | ||
|
|
||
| This override mechanism works by compiling the design tokens defined in | ||
| `@openedx/brand-openedx` with the core Paragon tokens to generate overrides to | ||
| Paragon's default CSS variables and then compiling the output CSS with any SCSS | ||
| theme customizations not possible through a design token override. | ||
|
|
||
| The CSS urls for `@openedx/brand-openedx` overrides will be applied after the | ||
| Paragon base styles load, thus overriding any previously set CSS variables | ||
| and/or styles. | ||
|
|
||
| By loading a theme's CSS externally, consuming applications of Paragon no | ||
| longer need to be responsible for compiling the brand SCSS to CSS themselves | ||
| and instead use a pre-compiled CSS file. In doing so, this allows making | ||
| changes to the site theme without needing to necessarily re-build and re-deploy | ||
| all consuming applications. | ||
|
|
||
| ### Dark mode and theme variant preferences | ||
|
|
||
| `@openedx/frontend-base` supports both `light` (required) and `dark` (optional) | ||
| theme variants. The choice of which theme variant should be applied on page load | ||
| is based on the following preference cascade: | ||
|
|
||
| 1. **Get theme preference from localStorage.** Supports persisting and loading | ||
| the user's preference for their selected theme variant, until cleared. | ||
| 1. **Detect user system settings.** Rely on the `prefers-color-scheme` media | ||
| query to detect if the user's system indicates a preference for dark mode. If | ||
| so, use the default dark theme variant, if one is configured. | ||
| 1. **Use the default theme variant as configured (see below).** Otherwise, load | ||
| the default theme variant as configured by the `defaults` option described | ||
| below. | ||
|
|
||
| Whenever the current theme variant changes, an attribute | ||
| `data-theme-variant="*"` is updated on the `<html>` element. This | ||
| attribute enables applications both JS and CSS to have knowledge of the | ||
| currently applied theme variant. | ||
|
|
||
| ### Supporting custom theme variants beyond `light` and `dark` | ||
|
|
||
| If your use case requires additional variants beyond the default `light` and | ||
| `dark` theme variants, you may pass any number of custom theme variants. Custom | ||
| theme variants will work via the user's persisted localStorage setting (i.e., if a | ||
| user switches to a custom theme variant, the app will continue to load the | ||
| custom theme variant by default). By supporting custom theme variants, it also | ||
| supports having multiple or alternative `light` and/or `dark` theme variants. | ||
| You can see the [Configuration options](#configuration-options) example for | ||
| better understanding. | ||
|
|
||
| ## Development | ||
|
|
||
| ### Configuration options | ||
|
|
||
| To use a custom theme, the `theme` site configuration setting may be configured | ||
| with the following: | ||
|
|
||
| | Property | Data Type | Description | | ||
| | ----------------------------------- | --------- | --------------------------------------------------------------------------------------- | | ||
| | `core` | Object | Metadata about the core theme's core styles . | | ||
| | `core.url` | String | URL for the theme's core stylesheet. | | ||
| | `defaults` | Object | Mapping of theme variants to Paragon's default supported light and dark theme variants. | | ||
| | `defaults.light` | String | Default `light` theme variant from the theme variants in the `variants` object. | | ||
| | `defaults.dark` | String | Default `dark` theme variant from the theme variants in the `variants` object. | | ||
| | `variants` | Object | Metadata about each supported theme variant. | | ||
| | `variants.light` | Object | Metadata about the theme's light variant styles. | | ||
| | `variants.light.url` | String | URL for the theme's light variant stylesheet. | | ||
| | `variants.dark` | Object | Metadata about the theme's dark variant styles. | | ||
| | `variants.dark.url` | String | URL for the theme's dark variant stylesheet. | | ||
|
|
||
| The `dark` theme variant is optional. | ||
|
|
||
| A simple example: | ||
|
|
||
| ```ts | ||
| const siteConfig: SiteConfig = { | ||
| theme: { | ||
| core: { | ||
| url: "https://cdn.jsdelivr.net/npm/@my-org/[email protected]/dist/core.min.css", | ||
| }, | ||
| defaults: { | ||
| light: "light", | ||
| }, | ||
| variants: { | ||
| light: { | ||
| url: "https://cdn.jsdelivr.net/npm/@my-org/[email protected]/dist/light.min.css", | ||
| }, | ||
| }, | ||
| }, | ||
| }; | ||
| ``` | ||
|
|
||
| A complete example, including custom variants: | ||
|
|
||
| ```js | ||
| const siteConfig: SiteConfig = { | ||
| theme: { | ||
| core: { | ||
| url: "https://cdn.jsdelivr.net/npm/@my-org/[email protected]/dist/core.min.css", | ||
| }, | ||
| defaults: { | ||
| light: "light", | ||
| dark: "dark", | ||
| }, | ||
| variants: { | ||
| light: { | ||
| url: "https://cdn.jsdelivr.net/npm/@my-org/[email protected]/dist/light.min.css", | ||
| }, | ||
| // Optional dark mode | ||
| dark: { | ||
| url: "https://cdn.jsdelivr.net/npm/@my-org/[email protected]/dist/dark.min.css", | ||
| }, | ||
| // Configure any extra theme using a custom @openedx/brand-openedx package | ||
| green: { | ||
| url: "https://cdn.jsdelivr.net/npm/@my-org/[email protected]/dist/green.min.css", | ||
| }, | ||
| red: { | ||
| url: "https://cdn.jsdelivr.net/npm/@my-org/[email protected]/dist/red.min.css", | ||
| }, | ||
| "high-contrast-dark": { | ||
| url: "https://cdn.jsdelivr.net/npm/@my-org/[email protected]/dist/high-contrast-dark.min.css", | ||
| }, | ||
| }, | ||
| }, | ||
| }; | ||
| ``` | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.