Mastering Light & Dark Themes in Forge Apps

Overview

I have an exciting idea for an application tailored for the Atlassian Marketplace. Picture this: your team is in the middle of sprint planning, tasked with estimating a new feature in story points. But there's a problem - team members can't reach a consensus. Some are convinced of one estimate, while others argue for a different number, leading to a stalemate. What can be done to resolve this deadlock?

Enter a new kind of solution: an application that invites the entire team to sing a motivating song together. After that, the energy shifts, and the team is not only more motivated but also better aligned, enabling quicker and more efficient decision-making.

The app must look great in both light and dark themes. After all, many developers swear by the dark mode, and without this option, they might not be as enthusiastic about participating. Ensuring a visually appealing interface in both themes is critical for the app's success.

This new application will be developed for Jira Cloud, leveraging the power of the Forge framework to create a seamless and engaging experience.

First Proof of Concept

We're not going to dive into the step-by-step process of building an app from scratch here - we've got plenty of guides for that ( , ). For now, let's say we've used the Forge Issue Panel module to display our app’s content, paired with React for a Custom UI. Fast-forward through the setup, and voilà, our first version of the app is up and running! (Picture it: light theme on the left, dark theme on the right).

img-1.png

It’s clearly amazing... but let’s be honest, it’s not quite looking like a Jira-native masterpiece just yet. Here’s what we need to fix:

  • Fonts, spacing, and basic styles: These need to match Jira’s default look, so our app feels like a natural extension of the platform.

  • Background and colors: They need to adapt seamlessly to whatever theme the user has - whether they’re a fan of the sunny light mode or living in the dark side with the dark theme.

  • Controls: Right now, it’s just a button, but even that should look and feel like it belongs in Jira.

Resetting basic styles

A quick and easy win? Just one simple import from the css-reset (check it out here: https://atlassian.design/components/css-reset/examples) and boom - your padding, margins, and fonts are instantly aligned with Jira’s look.

import '@atlaskit/css-reset';

And voilà! The result is looking a bit better. The font now matches Jira's, which is great... but sadly, the colors and background? Still off. Baby steps, right?

img-2.png

Enabling Theme and Design Tokens

So, after bravely conquering this massive guide (https://developer.atlassian.com/platform/forge/design-tokens-and-theming/), we’re ready to make two key updates to our app:

1. Wrap all our code in the index.tsx file with the magic snippet below.

// index.tsx 

import { view } from '@forge/bridge';

import ReactDOM from 'react-dom/client';

import { App } from './app/App';

import '@atlaskit/css-reset';

void view.theme.enable().then(() => { const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement); root.render( , ); });

2. Replace all those hard-coded color names with sleek “tokens” like this example.

// App.tsx
import
{ token } from '@atlaskit/tokens';

export const App = () => {
return (

<div>

<button>Next song</button>

<div
style={{ color: token('color.text'), whiteSpace: 'pre-line', }} >

... the rest part of the App ...

And guess what? The result looks way better - whether you’re rocking Light or Dark mode, the fonts, colors, and spacing are all on point now.

img-4.png

UI Components

Time for a few more tweaks - let’s upgrade our buttons and any other controls with some proper UI components. Trying to manually match Jira’s CSS styles? That’s a wild goose chase. Instead, we can use the same UI framework that Jira uses for its own elements: (https://atlaskit.atlassian.com/). It’s got everything you need for the UI - buttons, labels, inputs, tables, you name it.

// App.tsx
import
Button from '@atlaskit/button/new';
import { Box } from '@atlaskit/primitives';
import { token } from '@atlaskit/tokens';

export const App = () => {
return (

<Box>

<Button>Next song</Button>

<Box
style={{ color: token('color.text'), whiteSpace: 'pre-line', }} >

... the rest part of the App ...

The result? Our buttons (and everything else) will look just like they do in Jira. Success, right?

img-5.png

Wait, does this mean we’ve finally achieved a fully native-looking app in both light and dark themes? Can we start selling it on the Marketplace?! Well, almost… except for one small thing. There’s still that pesky issue with “raised” views, like when an Issue View pops up in a modal window (you know, when you click on an issue from the List view).

img-6.png

Background for Raised Views

To tackle that last little issue, we’ll create a styles.css file with the following magic:

/* styles.css */ 
html, body, #root {
background-color: transparent; /* fix for raised views */

Then, just import it into your index.tsx like this:

// index.tsx 

import './styles.css';

And behold the beauty! Raised views now blend in perfectly. It’s like the finishing touch on a masterpiece.

Screenshot 2024-09-17 at 10.00.17.png

Conclusion

Achieving flawless light and dark theme support for your Custom UI is easy - ust follow these four simple steps:

  1. Use @atlaskit/css-reset to reset all the styles in your app to the Jira “default.”

  2. Enable theme switching and use design tokens for all colors and spacing. No hard-coded colors allowed!

  3. Stick to Atlaskit components as much as possible - they look seamless and come with built-in theme support. Plus, they just make life easier.

  4. Set the default background color to transparent to handle those “raised” views like a pro (background-color: transparent;).

I was totally going to share the source code, but then I realized it’s so amazing that I have no choice but to sell it on the Atlassian Marketplace - as soon as they introduce the ‘Amazing Apps for Motivation’ category. Stay tuned!

0 comments

Comment

Log in or Sign up to comment
TAGS
AUG Leaders

Atlassian Community Events