Announcing Confluence Cloud Theming Preview for Developer Canary Program

Hello Marketplace Partners :wave:

We recently announced and requested comments about user-driven theming coming to Confluence using updated colors and elevations within the Atlassian Design System, powered by a new approach: design tokens. Design tokens will simplify the process for designers and engineers alike to build experiences, make them more easily accessible (such as improving contrast), and support theming — including light/dark themes coming to Confluence Cloud later in 2023.

We’ve been busy incorporating design tokens in Confluence Cloud over the past few months to support new light and dark themes. We’re thrilled to share that these themes are now accessible to preview by Marketplace partners within the Developer Canary Program. These new themes are still a work in progress with gaps that will be progressively filled in the coming months (see specifics below). You’ll be able to try out Confluence in dark theme and see how your app fits in. We are aiming to release theming access to a small percentage of customers between June and July 2023 to get more eyes and hands using theming for broader feedback. We want you, our Marketplace partners, to have the earliest access to get you started with plenty of time for you to adopt before we move into a Beta phase, followed by General Availability (GA) later this year.

How to Enable Themes

  1. If you’re not already part of the Developer Canary Program, sign up here.
  2. Open your profile menu from your user avatar in the top right of Confluence, select “Theme”, and choose a theme from the pop-up menu.

Supporting Themes in Apps

Consistent with the guidance provided in our RFC, all apps will need to adopt design tokens in order to render correctly in the new light and dark themes. Apps taking advantage of @atlaskit components will require less effort because design tokens are already incorporated into those components.

.example {
  background: var(--ds-surface-raised, #E0E0E0);
}
  • For CSS-in-JS, design tokens would be used through the @atlaskit/tokens npm package. For example,
import { token } from "@atlaskit/tokens";

const example = {
  backgroundColor: token("color.background.selected", #DEEBFF),
};
  • In both of the above examples, the first value represents the token, or variable, that defines a color when a theme is active. If that variable is not defined (no theme is active), the second value is used as the fallback.

Connect Apps

  • Connect apps should follow the approach as detailed in Theming Connect Apps. In particular, Connect apps would need to invoke window.AP.theming.initializeTheming().
    • Invoke window.AP.theming.initializeTheming() as early as possible in your application startup to avoid any “flashing” of nonthemed elements before theming is applied. This will apply the appropriate data-theme and data-color-mode attributes to the tag based on the theme defined by Confluence.
    • For example,
<html>
  <head>
    <style>
      :root {
        background-color: var(--ds-surface);
      }
    </style>
    <script src="https://connect-cdn.atl-paas.net/all.js"></script>
  </head>
  <body>
     <script>
          window.AP.theming.initializeTheming();
     </script>
  </body>
</html>
  • After invoking window.AP.theming.initializeTheming(), your app will pull the theme information from Confluence and the HTML tag of your app should look something like:
<html data-theme="dark:dark light:light" data-color-mode="dark">

Forge Apps

  • Forge apps using UI Kit without any color customizations will automatically inherit tokens.
  • Forge apps using Custom UI will need to apply design tokens as described above. The implementation would follow closely to what was described for Connect apps. See more about Theming Forge Apps. In particular, Forge Custom UI apps would need to invoke view.theme.enable():
    • Invoke view.theme.enable() as early as possible in your application startup to avoid any “flashing” of nonthemed elements before theming is applied. This will apply the appropriate data-theme and data-color-mode attributes to the tag based on the theme defined by Confluence, consistent with the solution described above for Connect apps.
import { view } from "@forge/bridge";

view.theme.enable();

NOTE: Currently there is a known issue where Forge Custom UI apps will render in the same theme as Confluence but will not stay in-sync with Confluence if the theme is changed while the Forge app is rendered. We will provide updates when this issue is resolved.

Bespoke Color Schemes

If your application uses colors that correspond to your unique brand, it is still possible to theme your app by querying the html[data-color-mode] attribute and styling your applications with your own tokens.

However, we advise against this in nearly every case because a set of colors that don’t use tokens would not stay up to date with any changes we make to Confluence in the future. It might look great on Day 1, but you could have to do the same work all over again on Day 500 (or sooner).

For example,

html[data-color-mode="light"] {
  --my-custom-background-token: white;
  --my-custom-text-token: black;
}

html[data-color-mode="dark"] {
  --my-custom-background-token: black;
  --my-custom-text-token: white;
}

See Bespoke color schemes for more detail.

Backward Compatibility

In the short term, the default theme will be Original, which will render the soon-to-be legacy Confluence colors (i.e. no tokens enabled). So, it’ll be important to provide your original fallback colors when using design tokens so it will still render when no theme has been specified. For @atlaskit components, this is already handled.

NOTE: We plan to remove the Original option in our GA release, so all apps will need to use design tokens before this happens.

Staying Up-To-Date

Design tokens may evolve over time through a lifecycle of active, deprecated, and deleted. All deprecations will be communicated well in advance with clear cutoff dates.

To simplify the migration and adoption, we recommend you install and configure the following linters that will provide warnings and errors for deprecated and deleted tokens. They also have built-in auto-fixers that allow you to update your code via eslint --fix and stylelint --fix.

See Staying up to date for more detail.

Current Confluence Gaps

These experiences have not yet been fully converted to use design tokens and as such will look particularly odd using the dark theme. We will be progressively closing these gaps in the weeks and months ahead.

  • Global Admin/Settings pages
  • Space Admin/Settings pages
  • Whiteboards
  • Personal Settings
  • PDF Export
  • Page History
  • Page Info
  • Atlassian-developed Connect & Forge apps
  • Custom illustrations / icons

What’s Next?

Please take the time to review design tokens, the guidance provided here, as well as the linked documentation. If you have questions or concerns, please share them here - we’re listening.

Remember - your tokens will only be activated when you’ve opted-in to theming and when a theme is set in Confluence. Furthermore, this feature will only be enabled for a limited set of customers for the next few months.

Even if you’re not ready to opt-in to theming via the respective Connect and Forge APIs, we hope you’ll start adjusting your apps to use design tokens soon and can try them out in your sites. We’d love to see your progress!

Thank you!

Alex White, Engineering Lead, Confluence Cloud Ecosystem
:dark_sunglasses:

6 Likes

Dear @AlexWhite

thanks for sharing this information.

I have two concrete questions:

  1. Can you already foresee how the solution will look like for icons - e.g. the ones shown in the side-bar for custom content? We currently use SVGs for those which Confluence wraps inside an img tag => no styling goes down to the SVG.
  2. Our UIs are based on AUI not atlaskit. We will for sure use the dark mode of AUI but for this it would be very helpful to get the color-mode back from window.AP.theming.initializeTheming(). In case this is not possible is there any alternative apart from a mutation observer checking when data-color-mode is added to the html tag?

Thank you and best regards

Andreas

3 Likes

Thanks for the question, @andreas1

Some answers to your questions:

  1. I discussed this particular question with our Design System team and reviewed some discussions with the Ecosystem Platform team. The solution for dynamically changing the app icon based on theme has not yet been solidified and our recommendation at this time is to utilize a single icon which displays well in both light and dark color modes. This can be achieved directly via color choice or by using a light border around a darker icon which allows for it to be distinguished in dark mode. We’ll follow-up when we can provide any more specific guidance.

  2. At the moment AUI doesn’t directly utilize design tokens but there is working being done now to migrate its variables to use tokens. And its existing themes will be ported to use design tokens. This is expected to be released in an upcoming 9.x version of AUI. After this is released and partners utilize this version, elements using AUI classes will have support for light and dark theming baked in.

As an aside, if you need access to the current color mode from your app, you can utilize useThemeObserver in React code and ThemeMutationObserver in non-React code.

Dear @AlexWhite

thank you for the insights.

Actually AUI 9.6 together with the aui-prototyping-darkmode.min.css already looks quite well.

For all the other readers - we are now using a js file included with defer like <script th:src="@{/js/theme.js}" type="text/javascript" defer></script> and the following content:

const themeObserver = new MutationObserver(function() {
	$("body").toggleClass("aui-theme-dark", $(document.documentElement).attr("data-color-mode") === "dark");
});
themeObserver.observe(document.documentElement, { attributes: true, childList: false, subtree: false });

window.AP.theming.initializeTheming();

Update: with AUI 9.7 a themeObserver does not seem to be necessary anymore. Just add aui-theme-design-tokens as class to the body tag of your HTML document using AUI and execute window.AP.theming.initializeTheming();. That’s it.

2 Likes

Hi @andreas1 ,
Thanks for the code snippet.

Is it possible to toggle between dark and light mode?

And how do you load the aui-prototyping-darkmode.min.css?

Yes you can toggle.

This is how we include the entire piece in a HTML page returned e.g. for a dialog:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
    <head>
  		<script src="//connect-cdn.atl-paas.net/all.js" type="text/javascript"></script>
  		<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
		<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/aui/9.6.0/aui/aui-prototyping.min.css" integrity="sha512-eyMwJMEjoEdPB6P9E74LZv9XWqf53ps/cgPt83o1QQrJ8y9Zidt1kVKuhqq/ONVrmJG9HUh5F1vy4sj/xdpfqg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
		<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/aui/9.6.0/aui/aui-prototyping-darkmode.min.css" integrity="sha512-3Bdo8km9KptiYNAoK4AbGstWLaa1/8YJzbTEfg0zRYzGc9jTAXzZTjLSY70p4p+F0v7dI4BeXfAmKW9jglzk2g==" crossorigin="anonymous" referrerpolicy="no-referrer" />		    	    	
 		<script src="https://cdnjs.cloudflare.com/ajax/libs/aui/9.6.0/aui/aui-prototyping.min.js" integrity="sha512-iCrH6FIR84U+0G0bhA+rePh3VWwtUiU7JwglCAPBXp3f5rwZJsmJH+flqTFfGSRdshoL6d0NpWwOoJfAfVWFdA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
		<script th:src="@{/js/theme.js}" type="text/javascript" defer></script>
		...
    </head>
	
	<body>
		...
	</body>
</html>

Update: with AUI 9.7 you don’t need the …darkmode.min.css anymore. Just add aui-theme-design-tokens as class to the body tag of your HTML document using AUI.

1 Like

Can you provide an example of a single icon that looks in place in both themes?

How do you access the design tokens when rendering macros?
I have a macro that is rendered as :

<div style="background-color: #F1F2F4; /* ... */">
Macro text
</div>

I tried both using var(--ds-surface), or rgba(128,128,128, 0.1), but these properties get removed before being inserted in the Confluence page.

1 Like

Hi @AlexWhite ,

Where is the best place to report problems with tokens and dark mode? (Here?)

I see an oddity where tokens have different values in the host product’s HTML document versus the Connect iframe. (The whole point of tokens is that these values should always be the same, right?)

For example, in the main Confluence HTML, I see this:

<style data-theme="dark">
html[data-color-mode="dark"][data-theme~="dark:dark"] {
    /* ... */
    --ds-surface-overlay: #282E33;
}

After tokens are injected into the app iframe with window.AP.theming.initializeTheming(), I get this in the app iframe:

<style data-theme="dark">
html[data-color-mode="dark"][data-theme~="dark:dark"] {
    /* ... */
    --ds-surface-overlay: #22272B;
}

As you might guess, this doesn’t look correct when the app’s iframe has a background color of --ds-surface-overlay and it is nested inside a larger Confluence div that is also colored with --ds-surface-overlay.

Here are a few more issues:

  1. In dark mode, web-items which use an inline dialog target currently have an unavoidable flashing of an empty white background until the target iframe is fully loaded. This occurs while the iframe is being loaded, before the app has any chance to initialize the theming system.
  2. In dark mode, contentBylineItems declared by Connect apps have a blue link color (--ds-link), whereas built-in Confluence content bylines and Forge-driven content bylines have a grey link color (--ds-text-subtle).
  3. I did not perform exhaustive testing, but the prior issue with --ds-surface-overlay is not the only discrepancy between the host and app iframe. I see differences in --ds-surface too (#161A1D app iframe vs #1D2125 Confluence), and I assume there are probably others.

Hi @Corentin Tokens can be used either via the @atlaskit/tokens npm package in JavaScript or can be done used manually via the CSS variables, as you referenced. You mentioned the “rendered” macro HTML - is this your HTML? Is this a Connect or Forge app?

If this is a snippet of your code, you should implement something like:

<div style="background-color: var(--ds-surface, rgba(128,128,128, 0.1)); /* ... */">
Macro text
</div>

The browser will render the value of the variable, if present (theme is active), or otherwise render the value of the fallback (rgba value in this case).

Thanks for the comments @scott.dudley . This topic is fine for development questions for now. You can also use our feedback option at the bottom of the theme selector in-product for general feedback about colors/usability.

  • Regarding why apps are receiving different dark values than Confluence - there was an issue with Atlassian Design System (ADS) which prevented the updated dark values being propagated into apps. Confluence tagged along with Jira’s recent update to the not-as-dark dark theme values. ADS said these new dark values will become standard soon (within a week or so) and so when that happens, you should also start seeing these values be consistent between your apps and Confluence.

  • Regarding the inline dialog, we’ll take a look at this and work w/ ADS and the Connect team to figure out what might be happening there. This would be a good item for the theme selector feedback option in the future.

  • We’ll address the contentBylineItems discrepancy. This would also be a good item for the theme selector feedback option in the future.

Hi @AlexWhite ,
I believe the usage is in a static content macro. This macro is rendered by Confluence, but Confluence removes parts of the markup.

Hi @AlexWhite. Sorry for the delayed answer, but I was on holidays.

Marc is absolutely correct, the use case is a static content macro.

Dear @AlexWhite ,

during our implementation we found out that the footer and header of dialogs created with AP.dialog.create and chrome: true are not properly tokenized. The background is wrong, the rest seems fine.

Did we miss something or is this issue known?

Thank you

Andreas

Dear @AlexWhite

another issue which Atlassian may wants to address.

When navigating to another piece of content from an app’s iframe the look and feel switches back to light before switching to dark again. This happens with absolute links (target="_top") and AP.navigator.go.

Thank you

Andreas

Hi @AlexWhite

Do you have any updates yet on when dark theme is likely going to GA? Also, is there any progress that can be reported on any of the issues noted earlier in the comments section here?

Thanks!
Scott

@marc @Corentin @andreas1 @scott.dudley

My apologies for delays in answering these questions! It’s been a busy summer with holidays and Confluence theming work!

Some quick updates:

  • All apps should now be using the same Light and Dark theme color values as Confluence itself - please let us know if you see any discrepancy!
  • Forge Custom UI theming solution is now functional - Forge apps that opt into theming will now automatically update when Confluence updates.

In response to some questions:

  • As for app icons, our current guidance is to choose icons which will present well in both Light and Dark modes. Consider following icon guidelines by Apple or Google and you should be in good shape. We may provide a customization for this at a later time but it’s not currently on the roadmap.

  • We’ve been methodically working through the Confluence codebase applying tokens in place of hard-coded original colors. You should be seeing less of these now, though, our efforts to identify and update all of them are ongoing. In situations where UI elements are created by the app, it may be a situation of the AUI version not being up-to-date. Tokens were added to AUI in version 9.7 so you’ll want to prioritize updating to that version if you’re not already there or higher.

  • In some cases where you see brief flashes of light (unthemed) UI before the theme takes effect, we’ve been improving these experiences over time. We’ll continue to make improvements as more scenarios are identified. Ultimately it’s related to loading in the theme styles and scripts very early in page load to avoid rendering anything before the theme is applied. This is sometimes easier said than done and is seen more prevalently when opening pages that are not assisted with SSR pre-rendering and that are full page renderings as opposed to a transition within a SPA. We appreciate reporting of these issues either here in the developer community forum or via the theme selector feedback mechanism.

Up Next:
We’ll be providing some documentation updates and more details on our rollout timeline by the end of next week. Our currently planned timeline has us moving into GA late September at the earliest. This is due to very positive results during our Alpha phase and no major feedback concerns from users.

2 Likes

Hi @AlexWhite ,
thank you for the update.

Has your team looked into styling in static content macros? It seems that Confluence removes design tokens as part of the sanitization.

2 Likes

We see a similar issue, now the background of header and footer it’s fine but the text color is not correct

1 Like