# Custom Theming

Kanoa MES is styled with standard Ignition Perspective themes, so you can brand and restyle your installation by creating your own theme. This page explains where Kanoa's styles live, why the Kanoa style classes look empty in the Designer, and how to create a custom theme that survives module updates.

## Where Kanoa's Styles Live

All of Kanoa's styling is in its **Perspective themes** on the gateway: `kanoa-light`, `kanoa-dark`, and the color variants `kanoa-light-forest`, `kanoa-light-firetruck`, `kanoa-light-grape` and `kanoa-light-orange`. The themes define the color palette as CSS variables and contain the CSS rules for Kanoa's views and components.

The themes are stored in this folder on the gateway server:

| Ignition version | Themes folder |
| --- | --- |
| 8.1 | `<Ignition install>/data/modules/com.inductiveautomation.perspective/themes/` |
| 8.3 | `<Ignition install>/data/config/resources/core/com.inductiveautomation.perspective/themes/` |

The **Perspective > Styles** folder in the `kanoaAPP` project does not contain Kanoa's styles. See [About the Kanoa Style Classes](#about-the-kanoa-style-classes).

## About the Kanoa Style Classes

The style classes in `kanoaAPP` under **Perspective > Styles** are **stub classes**. They are intentionally empty. Each stub only registers a class name so that you can pick it from the style class list in the Designer. The styles for those classes are defined in the Kanoa theme files.

This is why, when you override one of these style classes (or the `stylesheet.css` advanced stylesheet) in an inheriting project, the inherited value is blank. With most Ignition projects, an override starts from the inherited styles. With Kanoa, there are no styles in the project to inherit.

The stub classes are not intended to be overridden. To change how Kanoa looks, [create a custom theme](#create-a-custom-theme) instead.

## Create a Custom Theme

Create your own theme that starts from a Kanoa theme and overrides its variables. Your theme still picks up Kanoa's theme fixes when you update the module.

:::warning
Don't edit the Kanoa theme files. Module updates overwrite the themes that Kanoa ships, so your changes are eventually lost. Module updates never change themes with other names.

When you name your theme, avoid these names, which Kanoa reserves:

- Any name that starts with `kanoa`
- `palette`, `common`, `app` and `base`

:::

1. On the gateway server, open the [themes folder](#where-kanoas-styles-live) for your Ignition version. Use the Kanoa theme files there as a reference.

2. Create a new CSS file named after your theme, for example `acme-light.css`. Import the Kanoa theme that you want to start from, then override variables in a `:root` block:

    ```css
    @import "./kanoa-light.css";

    :root {
      --kcPrimary: #0b5fa5;
      --kcOnPrimary: #ffffff;
      --kcBackground: #0b5fa5;
      --kcSurface: #f7f9fb;
    }
    ```

3. To make a dark version, create a second file that imports `kanoa-dark.css`. Include `dark` as a hyphen-separated word in the name, for example `acme-dark.css`. Some Kanoa components, such as [toasts](../components/kanoa/toast), use the theme name to decide whether a theme is dark.

    ```css
    @import "./kanoa-dark.css";

    :root {
      --kcPrimary: #95ccff;
    }
    ```

4. Make the gateway load the new theme:
    - **Ignition 8.1**: no action is needed. The gateway picks up new and changed theme files automatically.
    - **Ignition 8.3**: trigger a file system scan from the gateway web page.
    You don't need to restart the gateway.

5. In the Designer, set `session.props.theme` to the name of your theme (the file name without `.css`), for example `acme-light`. To use the theme for every session, set it in the session props of each runnable project, such as `kanoaMES`.

:::tip
Change one variable at a time and refresh your session to see what it affects. Most Kanoa components use the semantic variables, such as `--kcPrimary` and `--kcSurface`, so a few overrides are usually enough to rebrand the whole application.
:::

## Theme Variables

These are the variables defined in `kanoa-light`. The `kanoa-dark` theme defines the same variables with dark values.

### Semantic Colors

Most components use these variables. They are the ones to override for branding.

Each `--kcOn...` variable is the text and icon color to use on top of the matching background. For example, text on a `--kcPrimary` background uses `--kcOnPrimary`. If you change a background color, check that its `--kcOn...` color still has enough contrast.

| Variable | Default (light) | Used for |
| --- | --- | --- |
| `--kcPrimary` / `--kcOnPrimary` | `#00639a` / `#ffffff` | Primary brand color |
| `--kcPrimaryContainer` / `--kcOnPrimaryContainer` | `#cde5ff` / `#001d32` | Lighter primary areas |
| `--kcSecondary` / `--kcOnSecondary` | `#51606f` / `#ffffff` | Secondary accents |
| `--kcSecondaryContainer` / `--kcOnSecondaryContainer` | `#d5e4f6` / `#0e1d2a` | Lighter secondary areas |
| `--kcTertiary` / `--kcOnTertiary` | `#a04100` / `#ffffff` | Tertiary accents |
| `--kcTertiaryContainer` / `--kcOnTertiaryContainer` | `#ffdbcc` / `#351000` | Lighter tertiary areas |
| `--kcError` / `--kcOnError` | `#ba1a1a` / `#ffffff` | Errors |
| `--kcErrorContainer` / `--kcOnErrorContainer` | `#ffdad6` / `#410002` | Error messages and highlights |
| `--kcBackground` / `--kcOnBackground` | `#00639a` / `#ffffff` | Application background behind views |
| `--kcSurface` / `--kcOnSurface` | `#fcfcff` / `#1a1c1e` | Cards, containers and popups |
| `--kcSurfaceVariant` / `--kcOnSurfaceVariant` | `#dee3eb` / `#42474e` | Nested containers and tooltips |
| `--kcOutline` | `#72777f` | Card borders |
| `--kcOutlineVariant` | `#c2c7cf` | Input and tooltip borders |
| `--kcInverseSurface` / `--kcInverseOnSurface` | `#2f3033` / `#f0f0f4` | Elements that contrast with the surface |
| `--kcInversePrimary` | `#95ccff` | Primary color on an inverse surface |
| `--kcSurfaceTint` | `#00639a` | Tint applied to raised surfaces |
| `--kcShadow`, `--kcScrim` | `#000000` | Shadows and modal overlays |

### Status Colors

| Variable | Default (light) | Used for |
| --- | --- | --- |
| `--kcGood` / `--kcGoodContainer` / `--kcOnGoodContainer` | `#00639a` / `#cde5ff` / `#001d32` | Good status, for example in KPIs |
| `--kcOK` / `--kcOKContainer` / `--kcOnOKContainer` | `#f1b400` / `#ffdea0` / `#261a00` | Warning status |
| `--kcBad` / `--kcBadContainer` / `--kcOnBadContainer` | `#ba1a1a` / `#ffdad6` / `#410002` | Bad status |

### Component Variables

These variables are set from the semantic colors. If you override a semantic color, these follow it. You can also override them directly to change one kind of component.

| Variable | Default | Used for |
| --- | --- | --- |
| `--kcRootBackground` | `var(--kcBackground)` | Root container background |
| `--kcContainerBackground` | `var(--kcSurface)` | View container background |
| `--kcNestedBackground` | `var(--kcSurfaceVariant)` | Containers nested in other containers |
| `--kcDockBackground` / `--kcDockColor` | `var(--kcPrimary)` / `var(--kcOnPrimary)` | Docked header and navigation |
| `--kcDockBackgroundAccent` / `--kcDockColorAccent` | `var(--kcTertiary)` / `var(--kcOnTertiary)` | Highlighted items in docks |
| `--kcCardBackground` | `var(--kcSurface)` | Card background |
| `--kcCardBorder` | `var(--kcOutline)` | Card border |
| `--kcCardShadow` | `2px 2px 3px #88888844` | Card and button shadow |
| `--popupBackground` | `var(--kcSurface)` | Popup background |
| `--kcTooltipBackground` / `--kcTooltipColor` / `--kcTooltipBorder` | `var(--kcSurfaceVariant)` / `var(--kcOnSurfaceVariant)` / `var(--kcOutlineVariant)` | Tooltips |
| `--kcTooltipBackground-Error` / `--kcTooltipColor-Error` / `--kcTooltipBorder-Error` | `var(--kcErrorContainer)` / `var(--kcOnErrorContainer)` / `var(--kcOnError)` | Error tooltips |
| `--kcInputBorder` | `var(--kcOutlineVariant)` | Input borders |
| `--checkbox--checked` | `var(--kcPrimary)` | Checked checkboxes |

Buttons have their own variables for each variant. Each variant has a `Background`, `Color` and `Border` variable, for example `--kcButton-GreenBackground`, `--kcButton-GreenColor` and `--kcButton-GreenBorder`:

| Variant | Default background |
| --- | --- |
| `--kcButton-Default...` | `var(--kcGray-20)` |
| `--kcButton-Disabled...` | `var(--kcGray-30)` |
| `--kcButton-Green...` | `var(--kcGreen-40)` |
| `--kcButton-Red...` | `var(--kcRed-40)` |
| `--kcButton-Blue...` | `var(--kcBlue-40)` |

`--kcButtonShadow` sets the shadow for all buttons. It defaults to `var(--kcCardShadow)`.

### Chart Colors

Charts use `--kcChart-01` to `--kcChart-09` for series colors, in order. Override them to match your brand palette:

```css
:root {
  --kcChart-01: #0b5fa5;
  --kcChart-02: #f96900;
  --kcChart-03: #f7b801;
}
```

### Tonal Palettes

The theme also defines tonal palettes that you can use in your own styles:

| Palette | Variables | Notes |
| --- | --- | --- |
| Theme palettes | `--kcPrimary-0` to `--kcPrimary-100`, and the same steps for `--kcSecondary`, `--kcTertiary`, `--kcNeutral`, `--kcNeutralVariant` and `--kcError` | Steps 0, 10, 20, 25, 30, 35, 40, 50, 60, 70, 80, 90, 95, 98, 99 and 100. `0` is black and `100` is white. |
| General colors | `--kcRed-0` to `--kcRed-100`, and the same steps for `--kcOrange`, `--kcYellow`, `--kcGreen`, `--kcBlue`, `--kcPurple` and `--kcPink` | Steps of 10. `0` is white and `100` is black. |
| Grays | `--kcGray-0` to `--kcGray-100`, plus `--kcGray-05` | `--kcGrey-*` is an alias with the British spelling. |

:::note
The semantic colors are set to fixed values, not to the palette variables. If you override a palette, such as `--kcPrimary-40`, the semantic colors don't change. To rebrand, override the semantic colors, such as `--kcPrimary`, directly.
:::

The theme also maps Ignition's standard `--neutral-0` to `--neutral-100` variables to the Kanoa neutral palette, so standard Perspective components match Kanoa's colors.

## Add Your Own Style Classes

To style individual components in your own views, create your own style classes in your custom project, such as `_client_custom_mes` (see [Install Modules](../getting-started/installation/install-modules#kanoa-projects--custom-projects-and-inheritance)). Use a folder name of your own so your classes are separate from the Kanoa stubs, for example `acme/card-highlight`.

Reference theme variables in your style classes rather than fixed colors, for example `var(--kcPrimary)`. The class then works in both your light and your dark theme.

## Use the Advanced Stylesheet

For CSS that you can't express with a theme variable or a style class, use your project's advanced stylesheet (**Perspective > Styles > stylesheet.css** in the Designer). The advanced stylesheet is for your own rules. Kanoa doesn't put any rules in it, so it is empty when you override it.

```css
/* Applies to any component whose style.classes includes "my-header".
   Perspective adds the psc- prefix to class names in style.classes. */
.psc-my-header {
  min-height: 56px;
}
```

Rules in the advanced stylesheet apply to the project whatever theme is active. To give light and dark themes different values, define the values as variables in each theme and reference them from the stylesheet.

## Component-Specific Styling

Some Kanoa components have their own styling options:

- **Toasts**: set the `--kanoa-toast-*` variables. See [Styling Toasts](../components/kanoa/toast#styling-toasts).
- **Calendar**: apply style classes to individual parts of the calendar through its class properties. See [Calendar](../components/kanoa/calendar).

## Which Option Should I Use?

| You want to... | Use |
| --- | --- |
| Change brand colors or chart colors everywhere | A [custom theme](#create-a-custom-theme) |
| Use different colors in light and dark mode | Two custom themes, one importing each Kanoa theme |
| Change how a Kanoa view or component looks | A custom theme. Don't override the Kanoa stub classes. |
| Style components in your own views | [Your own style classes](#add-your-own-style-classes) |
| Add CSS rules for one project only | The [advanced stylesheet](#use-the-advanced-stylesheet) in that project |
| Change toast colors | The `--kanoa-toast-*` variables |
