# Theming Learn how to create and customise a theme. Section: guides Docs: https://nebula.kaluza.com/guides/theme --- ## Create a theme Creating your first theme is as simple as calling the `createTheme` function. It's ready to go out-of-the-box with the default theme. The next few sections will show you how to customise the theme to match your brand. ```tsx import { createTheme } from '@kaluza-platform/nebula'; import { ThemeProvider } from 'styled-components'; const theme = createTheme({}); const MyApp = () => ( Welcome to my app! ); ``` ## Customise a theme Themes are built on a set of **core tokens** or [Foundations](/category/foundations). These tokens correspond to raw values, such as a font size or hex value. ```tsx const myTheme = createTheme<{}>({ colors: { primary: 'green', primaryAlt: 'darkgreen', }, fonts: { body: 'Tahoma' }, borderWidths: { heavy: '2rem' } }); ``` Our approach to theming is to set default values and then allow you to override the theme. **Themes are combined with a deep merge**. This will update any dynamic tokens. When you add custom theme values you should also provide the typings. ```tsx const myTheme = createTheme<{ fonts: { superDisplay: string }, borderRadius: { full: string } }>({ fonts: { superDisplay: 'Verdana' }, borderRadius: { full: '50%' }, colors: { primary: 'tomato' } }); ``` It is also possible to extend the theme, adding your own variables. ```tsx type AdditionalValues = { somethingCustom: { color: string; }, } const myTheme = createTheme({ colors: { primary: 'green', primaryAlt: 'darkgreen', }, somethingCustom: { color: 'tomato', }, }); ``` ## CSS Reset You will need to import the css reset in order for the theme to display components correctly. It will adjust the font size of the page to make it easier to work with rems. [Rem Units in CSS](https://www.sitepoint.com/understanding-and-using-rem-units-in-css/) ## Transitional configuration The `config` block of the theme object contains properties used to manage the rollout of breaking changes. These are **transitional mechanisms only** — they exist to let apps adopt new behaviour on their own schedule and are not intended as permanent configuration options. All apps are expected to migrate to the default (enabled) state. ### `markRequiredFormFields` Controls whether the new required field marking behaviour is active. - `false` (default during rollout) - Existing behaviour: `optional` prop appends "(optional)" text; no asterisk is shown - `true` - New behaviour: required fields display a red asterisk; `optional` suppresses it; `Form` renders the "Fields marked * are required" key This applies consistently across every Nebula field component, including `RadioField`, `CheckboxField`, and `DateField`, not just `Field`-based components like `TextField` and `SelectField`. ```tsx const theme = createTheme({ config: { markRequiredFormFields: true, }, }); ``` When adopting this change: 1. Set `markRequiredFormFields: true` in your theme. 2. Audit your forms for fields that are genuinely optional and add `optional` to them. 3. Check forms that use field components outside the Nebula `Form` component - you will need to add the key text manually. Once all teams have migrated, this property will be removed and the new behaviour will become the unconditional default. ### `accessibleBadge` Controls whether the accessible badge styling is active. - `false` (default during rollout) - Existing badge styles displayed - `true` - New badge styles displayed (all existing badge styles map to one of the new styles ```tsx const theme = createTheme({ config: { accessibleBadge: true, }, }); ``` When adopting this change: 1. Set `accessibleBadge: true` in your theme. 2. Check badges render as expected - note that there is now only a single style per variant, and no outlined/filled distinction Once all teams have migrated, this property will be removed and the new behaviour will become the unconditional default. ### `disableAutocomplete` Controls whether browser autofill is disabled by default on form fields. - `false` (default during rollout) - Existing behaviour: fields do not set `autocomplete`/`aria-autocomplete`, so browsers offer autofill suggestions as normal - `true` - New behaviour: form fields default `autoComplete` to `"off"` to suppress browser autofill; a field's own `autoComplete` prop still overrides this ```tsx const theme = createTheme({ config: { disableAutocomplete: true, }, }); ``` When adopting this change: 1. Set `disableAutocomplete: true` in your theme. 2. Audit any screens where a field relies on browser autofill and add an explicit `autoComplete` prop to those fields. 3. Note that Chrome and Firefox deliberately ignore `autocomplete="off"` on password fields to preserve password-manager suggestions, so `PasswordInput`/`PasswordField` will still show that browser UI regardless of this setting. Once all teams have migrated, this property will be removed and the new behaviour will become the unconditional default.