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.
setTheme() still works but is deprecated. Migrate to initDialtoneTheme() for startup, setMode() / setBrand() / setContrast() / setMaterial() for runtime switching.data-dt-theme is no longer set. New attributes are data-dt-mode, data-dt-brand, data-dt-contrast, and data-dt-material.npx dialtone-migration-helper and select theme to mode to automate most of this.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.
The layered API separates these four orthogonal dimensions:
setMode) — light or dark. Changes instantly with a single attribute toggle.setBrand) — which color palette overrides to apply (dp, tmo, melon, etc.).setContrast) — default or high contrast, for WCAG AAA accessibility.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 for details.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).
| Before | After | |
|---|---|---|
| Startup call | setTheme(DpLight) | initDialtoneTheme(Dp, 'light') |
| Mode switching | setTheme(DpDark) | setMode('dark') |
| Brand switching | setTheme(TmoLight) | setBrand(Tmo) |
| Contrast | setTheme(theme, root, HighContrast) | setContrast(HighContrast) |
| Disable contrast | setTheme(theme, root, null) | setContrast(null) |
| Material | (not available) | setMaterial('sandstone') |
| Root attribute (mode) | data-dt-theme="dp-light" | data-dt-mode="light" |
| Root attribute (brand) | data-dt-brand="dp" (already existed) | data-dt-brand="dp" (unchanged) |
| Root attribute (contrast) | data-dt-contrast="default" (already existed) | data-dt-contrast="default" (unchanged) |
| Root attribute (material) | (not available) | data-dt-material="sandstone" |
| CSS selector | [data-dt-theme="dp-light"] | [data-dt-mode="light"] |
npx dialtone-migration-helper --cwd ./src and select theme to mode.data-dt-theme="invert" patterns the script flagged — decide whether each should adopt v-dt-mode (see Manual Review).Run the migration helper from your project root:
npx dialtone-migration-helper --cwd ./src
Select theme to mode from the interactive menu. Add --dry-run to preview changes without writing files. Add --yes to apply without prompting.
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.
Call initDialtoneTheme() once on startup. It loads core tokens, sets the initial mode and brand, and sets contrast to 'default'.
<html data-dt-mode="light" data-dt-brand="dp" data-dt-contrast="default" data-dt-material="sandstone">
[data-dt-mode="light"] .d-banner { ... }
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.
import HighContrast from '@dialpad/dialtone/themes/high-contrast';
// Enable on init
setTheme(DpLight, document.documentElement, HighContrast);
// Toggle on/off — required full re-init
setTheme(DpLight);
setTheme(DpLight, document.documentElement, HighContrast);
import HighContrast from '@dialpad/dialtone/themes/high-contrast';
// Enable
setContrast(HighContrast);
// Disable (return to default)
setContrast(null);
The script flags data-dt-theme="invert" patterns with a comment rather than auto-rewriting them:
<!-- TODO: review for v-dt-mode adoption — see /guides/migration/theme-to-mode/ -->
<section data-dt-theme="invert">...</section>
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.
For each flagged location, decide:
Adopt v-dt-mode (recommended when the parent mode is dynamic):
<!-- Before: manually inverted region -->
<section data-dt-theme="invert">Dark island inside a light page</section>
<!-- After: reactive invert via directive -->
<section v-dt-mode>Dark island inside a light page</section>
import { DtModeDirective } from '@dialpad/dialtone/vue';
app.use(DtModeDirective);
Keep a static override (acceptable when the parent mode never changes):
<section data-dt-mode="dark">Always dark regardless of parent</section>
Use DtModeIsland (when you need a styled container with background):
<dt-mode-island mode="invert">Inverted region with surface color</dt-mode-island>
For full directive documentation see the v-dt-mode Storybook page. For DtModeIsland, see the Mode Island component page.
If you have any troubles, please let us know in the #dialtone Dialpad channel.
Theme: setTheme deprecated, layered API replaces it documentation last updated Friday, September 4, 2026
fix/popover-modal-zindex-scope