Skip to content

Commit 22a2dc5

Browse files
edonehoomcoker
andauthored
docs(theming): Adds new theming guidelines. (#4799)
* docs(theming): Adds new theming guidelines. * iss4770-2 * In progress working towards final draft * Update packages/documentation-site/patternfly-docs/content/design-guidelines/styles/theming/high-contrast-handbook.md Co-authored-by: Michael Coker <[email protected]> * Updates from PR review * Remove Figma details for now * A couple of final edits. --------- Co-authored-by: Michael Coker <[email protected]>
1 parent 05eb1b6 commit 22a2dc5

File tree

9 files changed

+634
-64
lines changed

9 files changed

+634
-64
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
id: Theming
3+
section: design-foundations
4+
source: dark-theme-handbook
5+
---
6+
7+
# Dark theme developer handbook
8+
9+
## Enabling dark theme
10+
11+
Dark theme is available with PatternFly by default. To enable dark theme, add the class `pf-[version]-theme-dark` (for example, `pf-v6-theme-dark`) to your application's `<html>` tag. This class can be added dynamically to toggle dark theme on and off in your application.
12+
13+
Dark theme can also be applied based on the browser’s `prefers-color-scheme` media query. When using this method, we recommend using JavaScript to detect the media query and apply the `pf-[version]-theme-dark` class. This allows you to manipulate a single class in order to toggle dark theme based on user preference. [Adam Argyle wrote a great article](https://web.dev/building-a-theme-switch-component/#javascript) on using JavaScript to manage dark theme preference, using the `prefers-color-scheme` media query alongside a manual button that toggles dark theme.
14+
15+
[Our token resources](https://github.com/patternfly/patternfly/tree/v6/src/patternfly/base/tokens) include styles for both light and dark themes. When dark theme is enabled, your product will automatically pull dark theme tokens in order to adapt visual styles appropriately.
16+
17+
The only features which will require additional work in order to support dark theme are charts and images.
18+
19+
### Charts
20+
21+
To use charts with dark themes, refer to our guidance for [developing with charts](/charts/about-charts#develop-with-charts).
22+
23+
### Images
24+
25+
To create images that adapt to light and dark themes, there are a few approaches you can take:
26+
27+
- Use inline SVG's with fill colors set to [PatternFly color tokens](/tokens/all-patternfly-tokens), which inherently adapt to light and dark themes.
28+
- Create images with colors that work well with both light and dark themes. These colors should meet [WCAG AA contrast requirements](https://webaim.org/resources/contrastchecker/).
29+
- Utilize background color, border color, border-radius, and padding/spacing to create a container that can hold dynamic/user-supplied images.
30+
- Write CSS and dynamically swap between 2 image variations:
31+
32+
```
33+
<img src="/light-theme.jpg" class="show-in-light">
34+
<img src="/dark-theme.jpg" class="show-in-dark">
35+
36+
<style>
37+
.show-in-dark,
38+
.pf-v6-theme-dark .show-in-light {
39+
display: none;
40+
}
41+
42+
.pf-v6-theme-dark .show-in-dark {
43+
display: revert;
44+
}
45+
</style>
46+
```
47+
48+
## Best practices
49+
50+
The most important step to ensure your application supports dark theme is to follow our [general theming best practices](/design-foundations/theming#best-practices). Adhering to these guidelines, especially by using design tokens instead of hard-coded values, will resolve most adoption challenges.
51+
52+
Additionally, keep these key points in mind:
53+
54+
- **Plan for static images:** If you can't use SVGs that are compatible with both light and dark backgrounds, you will need to create two versions of you image and swap them based on the active theme.
55+
- **Test custom components in both themes:** When building custom components, always check your work in both light and dark themes. This helps you catch issues early, like hard-coded colors or styles that don't adapt as expected.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
id: Theming
3+
section: design-foundations
4+
source: high-contrast-handbook
5+
---
6+
7+
# High contrast mode developer handbook
8+
9+
## High contrast mode vs. forced colors mode
10+
11+
Our high contrast mode increases the contrast of PatternFly components, often introducing additional borders to distinguish between elements, states, and interactions that otherwise rely on subtle background colors. High contrast mode is enabled by applying styles that are meant to target the [`prefers-contrast: more`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-contrast) media query, which is the mode triggered on MacOS via **System Settings** > **Accessibility** > **Display** > **Increase contrast**.
12+
13+
This is different from [`forced-colors: active`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/forced-colors), which is a more aggressive contrast mode where the browser enforces a limited, user-chosen color palette on a webpage, often by replacing author-defined colors with CSS system colors and removing styles like background colors and box shadows. Common triggers for forced colors mode are enabling Windows High Contrast Mode and Firefox High Contrast Mode. As outlined in [“Automatic high contrast”](#automatic-high-contrast), we recommend applying high contrast mode when `forced-colors: active` is `true`.
14+
15+
## Enabling high contrast mode
16+
17+
High contrast mode is designed to work with both our standard light and dark themes, and it's available with PatternFly by default. To enable high contrast mode, add the class `.pf-v6-theme-high-contrast` to your application’s `<html>` tag. This class can be added dynamically to toggle high contrast mode on and off in your application.
18+
19+
[Adam Argyle's "Building a theme switch" article](https://web.dev/articles/building/a-theme-switch-component) outlines principles that should be applied to a high contrast mode theme switcher.
20+
21+
### Automatic high contrast
22+
23+
To apply high contrast mode automatically, based off of a user’s OS and browser contrast preferences, you can use `window.matchMedia()` to detect the browser’s `prefers-contrast` and `forced-colors` media queries. Because our high contrast mode often introduces additional borders, we recommend detecting `forced-colors` and applying high contrast styles when the value is `active`.
24+
25+
Even when high contrast mode is enabled automatically, it’s important to also add a manual toggle that allows users to toggle the theme on and off. A user's manual toggle of high contrast should always override the OS and browser preference.
26+
27+
### Dynamic high contrast
28+
29+
To allow your users to apply high contrast mode dynamically, independent of their OS and browser preferences, you can place an interactive toggle in a prominent location of your application. It is best practice store a user’s most recent toggle selection by storing their preference in `localStorage`, and using it enable or disable high contrast mode automatically when they return.
30+
31+
## High contrast design tokens
32+
33+
The following tokens have been introduced specifically for use in high contrast mode.
34+
35+
| **Token** | **Default theme value** | **High contrast mode value** |
36+
| :---: | :---: | :---: |
37+
| `--pf-t--global--border--color--high-contrast` | `transparent` | `--pf-t--global--border--color--default` <br /><br/>Light mode value: #4D4D4D<br />Dark mode value: #C7C7C7 |
38+
| `--pf-t--global--border--width--high-contrast--regular` | 0px | `--pf-t--global--border--width--regular` <br /><br/>Value: 1px |
39+
| `--pf-t--global--border--width--high-contrast--strong` | 0px | `--pf-t--global--border--width--strong` <br /><br/>Value: 2px |
40+
| `--pf-t--global--border--width--high-contrast--extra-strong`| 0px | `--pf-t--global--border--width--extra-strong` <br /><br/>Value: 3px|
41+
42+
**Note:** The `--pf-t--global--border--color--high-contrast` token can be used strategically to support styles in `forced-colors` mode, as transparent borders will become visible when this mode is active.
43+
44+
### Plain action tokens
45+
46+
We also added the following tokens for plain actions (actions with a transparent background). These are now used in PatternFly anywhere where an action has a transparent background, such as plain buttons or navigation items.
47+
48+
| **Token** | **Default theme value** | **High contrast mode value** |
49+
| :---: | :---: | :---: |
50+
| `--pf-t--global--border--width--action--plain--default` | 0px| 0px|
51+
| `--pf-t--global--border--width--action--plain--hover` | 0px | `--pf-t--global--border--width--100` <br /><br/>Value: 1px |
52+
| `--pf-t--global--border--width--action--plain--clicked` | 0px | `--pf-t--global--border--width--200` <br /><br/>Value: 2px |
53+
54+
## Best practices
55+
56+
In addition to the [general theming best practices](/design-foundations/theming#best-practices), ensure that you adhere to the following guidelines when working in high contrast mode.
57+
58+
### Color and contrast
59+
60+
- **Meet text contrast ratios:** All normal text must meet a minimum contrast ratio of 7:1 against its background. While WCAG allows a 4.5:1 ratio for large text (18px or larger), it is best to aim for a 7:1 ratio for all text sizes to ensure maximum readability.
61+
- **Meet non-text contrast ratios:** All other UI elements, like icons and borders must meet a minimum contrast ratio of 4.5:1 against their background.
62+
63+
### Boundaries
64+
65+
- **Add borders for clarity:** If an element's background color doesn't have a 4.5:1 contrast ratio, add a visible border. For example, add borders to elements with a secondary background color that are placed on top of a primary background.
66+
- **Replace shadows with borders:** To properly separate elements from the background, add a border to any elements that rely on a shadow in default themes.
67+
- **Thicken borders on interaction:** Use border width to provide clear feedback for interactive states. An element's border should become progressively thicker on hover, focus, and click.
68+
- Example: An element with no default border should have a 1px border on hover and a 2px border when clicked.

0 commit comments

Comments
 (0)