|
| 1 | +--- |
| 2 | +title: "Theme: setTheme deprecated, layered API replaces it" |
| 3 | +description: "The legacy setTheme() function and data-dt-theme attribute have been deprecated in favor of the new layered API: initDialtoneTheme, setMode, setBrand, setContrast, and setMaterial." |
| 4 | +--- |
| 5 | + |
| 6 | +## TLDR |
| 7 | + |
| 8 | +> [!WARNING] Breaking change |
| 9 | +> `setTheme()` is deprecated and `data-dt-theme` no longer set by default. Projects adopting `next` must migrate to the layered API. Run the migration script to automate the transition. |
| 10 | +
|
| 11 | +- `setTheme()` still works but is deprecated. Migrate to `initDialtoneTheme()` for startup, `setMode()` / `setBrand()` / `setContrast()` / `setMaterial()` for runtime switching. |
| 12 | +- Root attributes: `data-dt-theme` is no longer set. New attributes are `data-dt-mode`, `data-dt-brand`, `data-dt-contrast`, and `data-dt-material`. |
| 13 | +- Run `npx dialtone-migration-helper` and select **theme to mode** to automate most of this. |
| 14 | + |
| 15 | +## Why |
| 16 | + |
| 17 | +The old `setTheme()` model coupled three independent concerns — color mode (light/dark), brand (dp/tmo/melon), and contrast (default/high) — into a single monolithic theme object. Switching from light to dark required swapping the entire object, including brand tokens that hadn't changed. |
| 18 | + |
| 19 | +The layered API separates these four orthogonal dimensions: |
| 20 | + |
| 21 | +- **Mode** (`setMode`) — light or dark. Changes instantly with a single attribute toggle. |
| 22 | +- **Brand** (`setBrand`) — which color palette overrides to apply (dp, tmo, melon, etc.). |
| 23 | +- **Contrast** (`setContrast`) — default or high contrast, for WCAG AAA accessibility. |
| 24 | +- **Material** (`setMaterial`) — surface texture layer (`sandstone` default, plus `steel`, `graphite`, `iron`, `amethyst`, `jade`). Applied independently of mode or brand; some brands lock their material — see [Brand-locked materials](/guides/theme-and-mode/#brand-locked-materials) for details. |
| 25 | + |
| 26 | +You can now switch any dimension independently, which reduces bundle work, enables runtime contrast toggles without a full theme reload, and maps cleanly to user preferences (OS dark-mode + a brand choice + an accessibility setting + a material preference are four separate controls). |
| 27 | + |
| 28 | +## What Changed |
| 29 | + |
| 30 | +| | Before | After | |
| 31 | +| --- | --- | --- | |
| 32 | +| Startup call | `setTheme(DpLight)` | `initDialtoneTheme(Dp, 'light')` | |
| 33 | +| Mode switching | `setTheme(DpDark)` | `setMode('dark')` | |
| 34 | +| Brand switching | `setTheme(TmoLight)` | `setBrand(Tmo)` | |
| 35 | +| Contrast | `setTheme(theme, root, HighContrast)` | `setContrast(HighContrast)` | |
| 36 | +| Disable contrast | `setTheme(theme, root, null)` | `setContrast(null)` | |
| 37 | +| Material | *(not available)* | `setMaterial('sandstone')` | |
| 38 | +| Root attribute (mode) | `data-dt-theme="dp-light"` | `data-dt-mode="light"` | |
| 39 | +| Root attribute (brand) | `data-dt-brand="dp"` *(already existed)* | `data-dt-brand="dp"` *(unchanged)* | |
| 40 | +| Root attribute (contrast) | `data-dt-contrast="default"` *(already existed)* | `data-dt-contrast="default"` *(unchanged)* | |
| 41 | +| Root attribute (material) | *(not available)* | `data-dt-material="sandstone"` | |
| 42 | +| CSS selector | `[data-dt-theme="dp-light"]` | `[data-dt-mode="light"]` | |
| 43 | + |
| 44 | +> [!INFO] setTheme still works |
| 45 | +> `setTheme()` is not removed. It continues to work with both legacy theme objects and the new layered format. Deprecation means it will be removed in a future major release. The migration script handles the rewrite automatically. |
| 46 | +
|
| 47 | +## Quick Checklist |
| 48 | + |
| 49 | +1. Run the migration script: `npx dialtone-migration-helper --cwd ./src` and select **theme to mode**. |
| 50 | +2. Review any `data-dt-theme="invert"` patterns the script flagged — decide whether each should adopt `v-dt-mode` (see [Manual Review](#manual-review-for-v-dt-mode-candidates)). |
| 51 | +3. Smoke-test your app: toggle light/dark, switch brand if applicable, toggle high contrast if used, apply a material if your app uses one. |
| 52 | + |
| 53 | +## Migration |
| 54 | + |
| 55 | +Run the migration helper from your project root: |
| 56 | + |
| 57 | +```bash |
| 58 | +npx dialtone-migration-helper --cwd ./src |
| 59 | +``` |
| 60 | + |
| 61 | +Select **theme to mode** from the interactive menu. Add `--dry-run` to preview changes without writing files. Add `--yes` to apply without prompting. |
| 62 | + |
| 63 | +The script handles the patterns below automatically. After it runs, also run `npx eslint --fix` to clean up the `setTheme` named import that becomes unused after the call-site rewrite. |
| 64 | + |
| 65 | +### Startup call |
| 66 | + |
| 67 | +<div class="d-d-grid d-g-200 d-g-cols1 md:d-g-cols2"> |
| 68 | +<div> |
| 69 | + |
| 70 | +### Before |
| 71 | + |
| 72 | +```js |
| 73 | +setTheme(DpLight); |
| 74 | +``` |
| 75 | + |
| 76 | +</div> |
| 77 | +<div> |
| 78 | + |
| 79 | +### After |
| 80 | + |
| 81 | +```js |
| 82 | +initDialtoneTheme(Dp, 'light'); |
| 83 | +``` |
| 84 | + |
| 85 | +</div> |
| 86 | +</div> |
| 87 | + |
| 88 | +Call `initDialtoneTheme()` once on startup. It loads core tokens, sets the initial mode and brand, and sets contrast to `'default'`. |
| 89 | + |
| 90 | +### Runtime mode switching |
| 91 | + |
| 92 | +<div class="d-d-grid d-g-200 d-g-cols1 md:d-g-cols2"> |
| 93 | +<div> |
| 94 | + |
| 95 | +### Before |
| 96 | + |
| 97 | +```js |
| 98 | +setTheme(DpDark); |
| 99 | +``` |
| 100 | + |
| 101 | +</div> |
| 102 | +<div> |
| 103 | + |
| 104 | +### After |
| 105 | + |
| 106 | +```js |
| 107 | +setMode('dark'); |
| 108 | +``` |
| 109 | + |
| 110 | +</div> |
| 111 | +</div> |
| 112 | + |
| 113 | +### Root attribute (HTML/CSS) |
| 114 | + |
| 115 | +<div class="d-d-grid d-g-200 d-g-cols1 md:d-g-cols2"> |
| 116 | +<div> |
| 117 | + |
| 118 | +### Before |
| 119 | + |
| 120 | +```html |
| 121 | +<html data-dt-theme="dp-light"> |
| 122 | +``` |
| 123 | + |
| 124 | +```css |
| 125 | +[data-dt-theme="dp-light"] .d-banner { ... } |
| 126 | +``` |
| 127 | + |
| 128 | +</div> |
| 129 | +<div> |
| 130 | + |
| 131 | +### After |
| 132 | + |
| 133 | +```html |
| 134 | +<html data-dt-mode="light" data-dt-brand="dp" data-dt-contrast="default" data-dt-material="sandstone"> |
| 135 | +``` |
| 136 | + |
| 137 | +```css |
| 138 | +[data-dt-mode="light"] .d-banner { ... } |
| 139 | +``` |
| 140 | + |
| 141 | +</div> |
| 142 | +</div> |
| 143 | + |
| 144 | +If your code reads `getAttribute('data-dt-theme')` or sets it manually, the migration script rewrites `setAttribute`/`getAttribute` call first arguments and CSS `[data-dt-theme]` selectors automatically. |
| 145 | + |
| 146 | +### Contrast |
| 147 | + |
| 148 | +<div class="d-d-grid d-g-200 d-g-cols1 md:d-g-cols2"> |
| 149 | +<div> |
| 150 | + |
| 151 | +### Before |
| 152 | + |
| 153 | +```js |
| 154 | +import HighContrast from '@dialpad/dialtone/themes/high-contrast'; |
| 155 | + |
| 156 | +// Enable on init |
| 157 | +setTheme(DpLight, document.documentElement, HighContrast); |
| 158 | + |
| 159 | +// Toggle on/off — required full re-init |
| 160 | +setTheme(DpLight); |
| 161 | +setTheme(DpLight, document.documentElement, HighContrast); |
| 162 | +``` |
| 163 | + |
| 164 | +</div> |
| 165 | +<div> |
| 166 | + |
| 167 | +### After |
| 168 | + |
| 169 | +```js |
| 170 | +import HighContrast from '@dialpad/dialtone/themes/high-contrast'; |
| 171 | + |
| 172 | +// Enable |
| 173 | +setContrast(HighContrast); |
| 174 | + |
| 175 | +// Disable (return to default) |
| 176 | +setContrast(null); |
| 177 | +``` |
| 178 | + |
| 179 | +</div> |
| 180 | +</div> |
| 181 | + |
| 182 | +## Manual Review for v-dt-mode Candidates |
| 183 | + |
| 184 | +The script flags `data-dt-theme="invert"` patterns with a comment rather than auto-rewriting them: |
| 185 | + |
| 186 | +```html |
| 187 | +<!-- TODO: review for v-dt-mode adoption — see /guides/migration/theme-to-mode/ --> |
| 188 | +<section data-dt-theme="invert">...</section> |
| 189 | +``` |
| 190 | + |
| 191 | +**Why not auto-rewrite?** The `v-dt-mode` directive resolves the inverted mode against the *live* parent mode using a MutationObserver — it stays reactive when the parent mode changes at runtime. A static `data-dt-mode="dark"` replacement would be wrong for any component sitting inside a dynamic parent. The correct rewrite depends on what the surrounding mode context is in your app. |
| 192 | + |
| 193 | +For each flagged location, decide: |
| 194 | + |
| 195 | +**Adopt `v-dt-mode` (recommended when the parent mode is dynamic):** |
| 196 | + |
| 197 | +```html |
| 198 | +<!-- Before: manually inverted region --> |
| 199 | +<section data-dt-theme="invert">Dark island inside a light page</section> |
| 200 | + |
| 201 | +<!-- After: reactive invert via directive --> |
| 202 | +<section v-dt-mode>Dark island inside a light page</section> |
| 203 | +``` |
| 204 | + |
| 205 | +```js |
| 206 | +import { DtModeDirective } from '@dialpad/dialtone/vue'; |
| 207 | +app.use(DtModeDirective); |
| 208 | +``` |
| 209 | + |
| 210 | +**Keep a static override (acceptable when the parent mode never changes):** |
| 211 | + |
| 212 | +```html |
| 213 | +<section data-dt-mode="dark">Always dark regardless of parent</section> |
| 214 | +``` |
| 215 | + |
| 216 | +**Use `DtModeIsland` (when you need a styled container with background):** |
| 217 | + |
| 218 | +```html |
| 219 | +<dt-mode-island mode="invert">Inverted region with surface color</dt-mode-island> |
| 220 | +``` |
| 221 | + |
| 222 | +For full directive documentation see the [v-dt-mode Storybook page](https://dialtone.dialpad.com/vue/next/?path=/docs/directives-mode--docs). For `DtModeIsland`, see the [Mode Island component page](/components/mode-island.html). |
| 223 | + |
| 224 | +> [!INFO] Dynamic bindings and template literals |
| 225 | +> The script only rewrites static `data-dt-theme="invert"` string literals. Vue dynamic bindings (`:data-dt-theme="expr"`) and JavaScript template literals are not covered. After running the script, grep your codebase for any remaining `data-dt-theme` references: `grep -r 'data-dt-theme' ./src`. |
| 226 | +
|
| 227 | +## Need Help? |
| 228 | + |
| 229 | +If you have any troubles, please let us know in the **#dialtone** Dialpad channel. |
0 commit comments