Skip to content

Commit eeedc67

Browse files
feat(design-tokens): DLT-3368 DLT-3371 DLT-3410 add material dimension and brand-locked pairings (#1252)
Co-authored-by: Joshua Hynes <jhynes@dialpad.com>
1 parent 83050ea commit eeedc67

104 files changed

Lines changed: 4070 additions & 1096 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 37 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,21 @@ npm install @dialpad/dialtone @dialpad/i18n
2020

2121
### Theming
2222

23+
Dialtone has four theming dimensions: **mode** (light/dark), **brand** (the color palette), **material** (the neutral ramp), and **contrast** (default/high). Each switches at runtime via `@dialpad/dialtone/themes/config`. See the [Theme and Mode guide](https://dialtone.dialpad.com/guides/theme-and-mode/) for the full API.
24+
2325
#### Quick Start
2426

25-
**Install packages:**
27+
**Install:**
2628

2729
```shell
28-
npm install @dialpad/dialtone @dialpad/dialtone-tokens
30+
npm install @dialpad/dialtone
2931
```
3032

3133
**Initialize (main.js or App.vue):**
3234

3335
```js
3436
import { initDialtoneTheme } from '@dialpad/dialtone/themes/config';
35-
import Dp from '@dialpad/dialtone-tokens/themes/dp';
37+
import Dp from '@dialpad/dialtone/themes/dp';
3638

3739
initDialtoneTheme(Dp, 'light');
3840
```
@@ -43,43 +45,46 @@ Done. Your app now has theming.
4345

4446
##### Basic Usage
4547

46-
**Toggle light/dark mode:**
47-
4848
```js
49-
import { setMode } from '@dialpad/dialtone/themes/config';
50-
setMode('dark');
51-
```
52-
53-
**Use different theme at startup:**
49+
import {
50+
setMode,
51+
setBrand,
52+
setMaterial,
53+
setContrast,
54+
} from '@dialpad/dialtone/themes/config';
55+
import Tmo from '@dialpad/dialtone/themes/tmo';
56+
import HighContrast from '@dialpad/dialtone/themes/high-contrast';
5457

55-
```js
56-
import Melon from '@dialpad/dialtone-tokens/themes/melon';
57-
initDialtoneTheme(Melon, 'light');
58+
setMode('dark'); // toggles data-dt-mode
59+
setBrand(Tmo); // injects brand CSS, sets data-dt-brand
60+
setMaterial('steel'); // toggles data-dt-material
61+
setContrast(HighContrast); // injects contrast CSS, sets data-dt-contrast
62+
setContrast(null); // remove contrast override
5863
```
5964

60-
**Switch themes dynamically:**
65+
`setMode` and `setMaterial` toggle attributes against pre-bundled CSS — no injection. `setBrand` and `setContrast` inject per-theme override CSS.
6166

62-
```js
63-
import { setBrand } from '@dialpad/dialtone/themes/config';
64-
import Tmo from '@dialpad/dialtone-tokens/themes/tmo';
65-
setBrand(Tmo);
66-
```
67+
---
68+
69+
##### Brand-locked materials
6770

68-
**Enable high contrast:**
71+
Most brands declare a paired material via the `shell.base.material` token in their token JSON. `setBrand` auto-applies the locked material in the same paint frame. Free-choice brands (`dp`, `tmo`, `prota-deuter`, `trita`) keep material independent.
6972

7073
```js
71-
import { setContrast } from '@dialpad/dialtone/themes/config';
72-
import HighContrast from '@dialpad/dialtone-tokens/themes/high-contrast';
74+
import { getBrandMaterial, hasBrandMaterialLock } from '@dialpad/dialtone/themes/config';
75+
import Botany from '@dialpad/dialtone/themes/botany';
7376

74-
setContrast(HighContrast);
75-
setContrast(null); // disable
77+
getBrandMaterial(Botany); // 'sandstone'
78+
hasBrandMaterialLock(Botany); // true
7679
```
7780

81+
Use these getters to drive picker UI (disable material options on locked brands).
82+
7883
---
7984

8085
##### Available Themes
8186

82-
51 themes total. Use any with `initDialtoneTheme()` or `setBrand()`.
87+
50+ themes total. Pass theme modules to `initDialtoneTheme()` or `setBrand()`.
8388

8489
**Standard:** dp, tmo, aegean, botany, buttercream, high-desert, melon, plum, sunflower, verdant-haze
8590

@@ -89,10 +94,10 @@ setContrast(null); // disable
8994

9095
**Contrast:** high-contrast
9196

92-
**Import pattern:**
97+
**Materials** (string names, no module imports): sandstone, steel, graphite, iron, amethyst, jade
9398

9499
```js
95-
import ThemeName from '@dialpad/dialtone-tokens/themes/theme-name';
100+
import ThemeName from '@dialpad/dialtone/themes/theme-name';
96101
```
97102

98103
---
@@ -118,7 +123,7 @@ initDialtoneTheme(Dp, 'light', this);
118123
Then set attributes:
119124

120125
```html
121-
<html data-dt-mode="light" data-dt-brand="dp" data-dt-contrast="default">
126+
<html data-dt-mode="light" data-dt-brand="dp" data-dt-material="sandstone" data-dt-contrast="default">
122127
```
123128

124129
**Mode sections:**
@@ -129,29 +134,18 @@ See [Mode Island component](https://dialtone.dialpad.com/components/mode-island.
129134

130135
##### Legacy Theming System (Backward Compatible)
131136

132-
The original theming system remains fully supported for existing projects. New projects should use the layered system above for better performance and smaller bundle sizes.
133-
134-
**Note:** Both systems support Shadow DOM identically - pass the host element as the second parameter.
137+
The original `setTheme()` API remains supported for existing projects. New projects should use the layered system above for smaller bundle sizes and finer-grained switching across all four dimensions.
135138

136139
```js
137140
import { setTheme } from '@dialpad/dialtone/themes/config';
138141
import DpLight from '@dialpad/dialtone/themes/dp-light';
139142
import DpDark from '@dialpad/dialtone/themes/dp-dark';
140-
import TmoLight from '@dialpad/dialtone/themes/tmo-light';
141-
import TmoDark from '@dialpad/dialtone/themes/tmo-dark';
142143

143-
// Set theme (automatically detected as legacy)
144-
setTheme(DpLight);
145-
146-
// Shadow DOM support
147-
setTheme(DpLight, document.querySelector('#my-shadow-root-host'));
144+
setTheme(DpLight); // auto-detected as legacy
145+
setTheme(DpLight, document.querySelector('#my-shadow-root-host')); // Shadow DOM support
148146
```
149147

150-
**Legacy themes available:**
151-
152-
- `DpLight`, `DpDark`, `TmoLight`, `TmoDark`
153-
154-
**Note:** Legacy system loads complete token files (~1256KB per theme). Consider migrating to layered system for better performance.
148+
**Legacy themes:** `DpLight`, `DpDark`, `TmoLight`, `TmoDark` — each ships the complete token set (~1256KB per theme), versus the layered system's small per-dimension overrides.
155149

156150
#### Dialtone icons
157151

apps/dialtone-documentation/docs/.vuepress/baseComponents/BaseColor.vue

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
<template>
2-
<dt-stack as="aside" gap="50">
2+
<dt-stack as="aside" gap="100">
33
<dt-stack v-if="stops.length" as="header" direction="row" justify="between" align="baseline">
4-
<dt-text
5-
as="h4"
6-
kind="headline"
7-
:size="400"
8-
class="d-tt-capitalize"
9-
text-box-trim="start"
10-
tabindex="-1"
11-
>
12-
{{ colorName }}
13-
</dt-text>
4+
<dt-box padding-inline="150">
5+
<dt-text
6+
as="h4"
7+
kind="headline"
8+
:size="300"
9+
class="d-tt-capitalize"
10+
text-box-trim="start"
11+
tabindex="-1"
12+
>
13+
{{ colorName }}
14+
</dt-text>
15+
</dt-box>
1416
<dt-text
1517
v-dt-tooltip="`Lightness Contrast (APCA) against either pure white or black. 60 is considered AA accessible.`"
1618
as="abbr"
@@ -29,25 +31,25 @@
2931
align="center"
3032
justify="space-between"
3133
:class="[
32-
'd-px-150 d-py-100 d-text-code--xs',
34+
'color-stop d-px-150 d-py-100 d-text-code--xs',
3335
{
3436
'd-bbsr-300': index === 0,
3537
'd-bber-300': index === (stops.length - 1),
3638
},
3739
]"
3840
:style="`background-color: ${stop.value}`"
3941
>
40-
<dt-stack gap="50" :class="fontColorClass(stop.lightness)">
42+
<dt-stack gap="50" :class="['color-stop__meta', fontColorClass(stop.lightness)]">
4143
<dt-text as="strong" class="d-us-all">
42-
{{ `var(--dt-color-${colorName}-${stop.stop})` }}
44+
{{ tokenName(stop.stop) }}
4345
</dt-text>
4446
<dt-text class="d-o75 d-us-all">
4547
{{ stop.value }}
4648
</dt-text>
4749
</dt-stack>
4850
<dt-text
4951
strength="bold"
50-
:class="fontColorClass(stop.lightness)"
52+
:class="['color-stop__lc', fontColorClass(stop.lightness)]"
5153
>
5254
{{ formattedContrast(activeContrast(stop)) }}
5355
</dt-text>
@@ -70,10 +72,23 @@ const props = defineProps({
7072
type: String,
7173
required: true,
7274
},
75+
// Token-name display format. 'color' (default) renders `var(--dt-color-{name}-{stop})`
76+
// since named ramps are CSS variables. Any other value renders the source-path
77+
// form `{namespace}.{name}.{stop}` — used by `material` since material ramps
78+
// don't emit CSS variables.
79+
namespace: {
80+
type: String,
81+
default: 'color',
82+
},
7383
});
7484
7585
const LIGHTNESS_THRESHOLD = 0.65;
7686
87+
function tokenName (stop) {
88+
return props.namespace === 'color'
89+
? `var(--dt-color-${props.colorName}-${stop})`
90+
: `${props.namespace}.${props.colorName}.${stop}`;
91+
}
7792
function fontColorClass (lightness) {
7893
return lightness >= LIGHTNESS_THRESHOLD
7994
? 'd-fc-neutral-black'

apps/dialtone-documentation/docs/.vuepress/baseComponents/BlogPost.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ const blogLink = computed(() => {
121121
122122
:where(code, kbd) {
123123
background-color: var(--dt-color-background-default);
124-
color: var(--dt-color-foreground-info);
124+
color: var(--dt-color-foreground-info-strong);
125125
font: var(--dt-text-code-xs);
126126
font-size: 85%;
127127
}

apps/dialtone-documentation/docs/.vuepress/baseComponents/tokens/TokensBar.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,23 @@
3838
select-class="d-w-200"
3939
:model-value="format"
4040
:options="formatSelectMenuOptions"
41-
@change="updateFormat"
41+
@update:model-value="updateFormat"
4242
/>
4343
<dt-select-menu
4444
name="mode-select"
4545
label="Mode"
4646
select-class="d-w-200"
4747
:model-value="mode"
4848
:options="MODES"
49-
@change="updateMode"
49+
@update:model-value="updateMode"
5050
/>
5151
<dt-select-menu
5252
name="theme-select"
5353
label="Theme"
5454
select-class="d-w-200"
5555
:model-value="theme"
5656
:options="THEMES"
57-
@change="updateTheme"
57+
@update:model-value="updateTheme"
5858
/>
5959
<dt-button
6060
v-dt-tooltip:top-end="shareLinkTooltip"

0 commit comments

Comments
 (0)