Skip to content

Commit 3d73a43

Browse files
authored
docs: DLT-3016 migration docs (#1224)
Co-authored-by: iropolo <ignacio.ropolo@dialpad.com>
1 parent ecf5f85 commit 3d73a43

17 files changed

Lines changed: 3051 additions & 3 deletions

File tree

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<template>
2+
<dt-banner
3+
v-if="shouldShow"
4+
kind="info"
5+
:important="false"
6+
title="Dialtone Next: Migration Guide Available"
7+
@close="sessionDismiss"
8+
>
9+
<template #icon>
10+
<dt-icon name="rocket" />
11+
</template>
12+
<dt-stack direction="row" gap="200" align="center">
13+
<dt-text :size="200">
14+
The next major version of Dialtone includes breaking changes.
15+
Review the migration guide for step-by-step instructions and automated tooling.
16+
</dt-text>
17+
<router-link
18+
to="/guides/migration/"
19+
class="d-link d-link--primary d-fw-semibold d-ws-nowrap"
20+
>
21+
View Migration Guide
22+
</router-link>
23+
<button
24+
class="d-link d-link--muted d-fw-semibold d-ws-nowrap"
25+
@click="permanentDismiss"
26+
>
27+
Don't show again
28+
</button>
29+
</dt-stack>
30+
</dt-banner>
31+
</template>
32+
33+
<script setup>
34+
import { ref, computed, onMounted } from 'vue';
35+
import { useRoute } from 'vue-router';
36+
37+
const STORAGE_KEY = 'dt-migration-banner-dismissed';
38+
const route = useRoute();
39+
const dismissed = ref(false);
40+
const permanentlyDismissed = ref(false);
41+
42+
const isOnMigrationGuide = computed(() => {
43+
return route.path.startsWith('/guides/migration/');
44+
});
45+
46+
const shouldShow = computed(() => {
47+
return !dismissed.value && !permanentlyDismissed.value && !isOnMigrationGuide.value;
48+
});
49+
50+
onMounted(() => {
51+
try {
52+
permanentlyDismissed.value = localStorage.getItem(STORAGE_KEY) === 'true';
53+
} catch {
54+
// localStorage unavailable
55+
}
56+
});
57+
58+
function sessionDismiss () {
59+
dismissed.value = true;
60+
}
61+
62+
function permanentDismiss () {
63+
permanentlyDismissed.value = true;
64+
try {
65+
localStorage.setItem(STORAGE_KEY, 'true');
66+
} catch {
67+
// localStorage unavailable
68+
}
69+
}
70+
</script>

apps/dialtone-documentation/docs/.vuepress/client.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import CodeExample from './baseComponents/CodeExample.vue';
2121
import SvgLoader from './baseComponents/SvgLoader.vue';
2222
import DialtoneUsage from './baseComponents/DialtoneUsage.vue';
2323
import UiKitsComparisonTable from './baseComponents/UiKitsComparisonTable.vue';
24+
import MigrationBanner from './baseComponents/MigrationBanner.vue';
2425

2526
export default defineClientConfig({
2627
enhance ({ app }) {
@@ -44,6 +45,7 @@ export default defineClientConfig({
4445
app.component('SvgLoader', SvgLoader);
4546
app.component('DialtoneUsage', DialtoneUsage);
4647
app.component('UiKitsComparisonTable', UiKitsComparisonTable);
48+
app.component('MigrationBanner', MigrationBanner);
4749
},
4850
setup () {
4951
const headers = shallowRef([]);

apps/dialtone-documentation/docs/.vuepress/theme/client.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
22
import { defineClientConfig } from 'vuepress/client';
33
import Layout from './layouts/Layout.vue';
44
import NotFound from './layouts/NotFound.vue';
@@ -99,7 +99,8 @@ export default defineClientConfig({
9999
// Resolve any pending transition before starting a new one
100100
resolveViewTransition?.();
101101

102-
if (document.startViewTransition) {
102+
// Skip view transitions for same-page hash navigation (e.g. TOC clicks)
103+
if (document.startViewTransition && to.path !== from.path) {
103104
const domUpdatePromise = new Promise(resolve => {
104105
resolveViewTransition = resolve;
105106
});
@@ -371,4 +372,3 @@ async function importDialtoneThemes (app) {
371372
console.error(`Couldn't import dialtone themes: ${error}`);
372373
}
373374
}
374-

apps/dialtone-documentation/docs/.vuepress/theme/layouts/Layout.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
<sidebar />
4242
</template>
4343
<template #default>
44+
<migration-banner />
4445
<home v-if="$frontmatter.home" />
4546
<page
4647
v-else
@@ -58,6 +59,7 @@ import Sidebar from '../components/Sidebar.vue';
5859
import Home from '../components/Home.vue';
5960
import Page from '../components/Page.vue';
6061
import MobileSidebar from '../components/MobileSidebar.vue';
62+
import MigrationBanner from '../../baseComponents/MigrationBanner.vue';
6163
import { computed, ref, watch, onMounted, onUnmounted } from 'vue';
6264
import { useRoute } from 'vue-router';
6365
import { useThemeLocaleData } from '@vuepress/plugin-theme-data/client';

apps/dialtone-documentation/docs/_data/site-nav.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,56 @@
198198
"text": "What's New",
199199
"link": "/dialtone/whats-new/"
200200
},
201+
{
202+
"text": "Migration Guide",
203+
"link": "/guides/migration/",
204+
"children": [
205+
{
206+
"text": "CSS Cascade Layers",
207+
"link": "/guides/migration/css-cascade-layers/"
208+
},
209+
{
210+
"text": "Color Stops",
211+
"link": "/guides/migration/color-stops/"
212+
},
213+
{
214+
"text": "HSL to OKLCH",
215+
"link": "/guides/migration/hsl-to-oklch/"
216+
},
217+
{
218+
"text": "Layout & Spacing Tokens",
219+
"link": "/guides/migration/layout-and-spacing-tokens/"
220+
},
221+
{
222+
"text": "Flex to DtStack",
223+
"link": "/guides/migration/flex-to-stack/"
224+
},
225+
{
226+
"text": "Component Sizes",
227+
"link": "/guides/migration/component-sizes/"
228+
},
229+
{
230+
"text": "Avatar Updates",
231+
"link": "/guides/migration/avatar-updates/"
232+
},
233+
{
234+
"text": "Logical Naming",
235+
"link": "/guides/migration/logical-naming/"
236+
},
237+
{
238+
"text": "Recipes to UI Kits",
239+
"link": "/guides/migration/recipes-to-ui-kits/"
240+
},
241+
{
242+
"text": "Vue 2 Removal",
243+
"link": "/guides/migration/vue2-removal/"
244+
},
245+
{
246+
"text": "Component Props & Events",
247+
"link": "/guides/migration/component-props/"
248+
}
249+
]
250+
},
201251
{
202252
"text": "MCP Server",
203253
"link": "/guides/mcp-server/"
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
---
2+
title: "DtAvatar: Visual Refresh Updates"
3+
description: "DtAvatar has been updated as part of the Dialtone visual refresh. Size prop moves to a numeric scale, group avatars gain full size support, iconSize is removed, and new color, iconOnly, and deactivated props are introduced."
4+
---
5+
6+
## TLDR
7+
8+
> [!WARNING]
9+
>
10+
> - `clickable` prop **renamed** to `interactive`
11+
> - `iconSize` prop **removed** — icon size is now computed automatically from `size`
12+
> - Group avatars no longer forced to `xs` — they now respect the `size` prop
13+
> - Group count badge capping is size-aware: sizes 100–250 cap at `9+`, sizes 300+ cap at `99+`
14+
> - Presence indicator only renders for sizes `100` - `500`
15+
16+
## Size Prop
17+
18+
`DtAvatar`'s `size` prop now uses a numeric 100–900 scale. T-shirt size strings are still accepted but deprecated and will be removed in a future major version.
19+
20+
**Important:** The default changed from the string `'md'` to the number `300`. If you use `DtAvatar` without a `size` prop, no change is needed. If you bind `size` dynamically, ensure your data is now a number.
21+
22+
| Old value | New value |
23+
| --- | --- |
24+
| `"xs"` | `100` |
25+
| `"sm"` | `200` |
26+
| `"md"` *(previous default)* | `300` *(new default)* |
27+
| `"lg"` | `500` |
28+
| `"xl"` | `800` |
29+
30+
Additional sizes with no t-shirt equivalent: `150`, `250`, `400`, `600`, `700`, `900`
31+
32+
### Migration examples
33+
34+
**Static string → static number**
35+
36+
```html
37+
<!-- Before -->
38+
<dt-avatar size="lg" />
39+
40+
<!-- After -->
41+
<dt-avatar :size="500" />
42+
```
43+
44+
**Conditional size**
45+
46+
```html
47+
<!-- Before -->
48+
<dt-avatar :size="isLarge ? 'lg' : 'md'" />
49+
50+
<!-- After -->
51+
<dt-avatar :size="isLarge ? 500 : 300" />
52+
```
53+
54+
**Dynamic bound prop**
55+
56+
```html
57+
<!-- Before: avatarSize was the string 'md' -->
58+
<dt-avatar :size="avatarSize" />
59+
60+
<!-- After: avatarSize is now the number 300 -->
61+
<dt-avatar :size="avatarSize" />
62+
```
63+
64+
## Group Avatars
65+
66+
Group avatars have two breaking changes.
67+
68+
**1. Size is no longer forced to `xs`.**
69+
70+
Previously, setting the `group` prop silently overrode the `size` prop and rendered the avatar at `xs` regardless of what you passed. That override is removed. Group avatars now render at whatever `size` you provide — or the default `300` if none is set.
71+
72+
If your group avatars were relying on the forced-`xs` behavior, you'll need to explicitly set `:size="100"` to preserve the previous appearance.
73+
74+
```html
75+
<!-- Before: rendered at xs even though size="lg" was set -->
76+
<dt-avatar full-name="Dialpad" :group="14" size="lg" />
77+
78+
<!-- After: renders at 500 — set size="100" to match old xs behavior -->
79+
<dt-avatar full-name="Dialpad" :group="14" :size="100" />
80+
```
81+
82+
**2. Count badge capping is now size-aware.**
83+
84+
Small avatars (sizes 100–250) cap the displayed count at `9+`. Larger avatars (sizes 300+) cap at `99+`. Previously the cap was always `99+` regardless of size.
85+
86+
## `clickable``interactive`
87+
88+
The `clickable` prop has been renamed to `interactive` to more accurately describe its effect: the avatar renders as a `<button>`, becomes keyboard-focusable, and participates in the page's tab order.
89+
90+
```html
91+
<!-- Before -->
92+
<dt-avatar full-name="Jane Doe" clickable @click="openProfile" />
93+
94+
<!-- After -->
95+
<dt-avatar full-name="Jane Doe" interactive @click="openProfile" />
96+
```
97+
98+
The [migration script](/guides/migration/component-props/#migration-script) (`dialtone-migrate-props`) handles this rename automatically.
99+
100+
---
101+
102+
## `iconSize` Removed
103+
104+
The `iconSize` prop has been removed. Icon size is now computed automatically based on the `size` prop and does not need to be specified.
105+
106+
```html
107+
<!-- Before -->
108+
<dt-avatar icon="person" icon-size="300" :size="300" />
109+
110+
<!-- After -->
111+
<dt-avatar icon="person" :size="300" />
112+
```
113+
114+
## New Props
115+
116+
The following props have been added and are available immediately — no migration required.
117+
118+
| Prop | Type | Description |
119+
| --- | --- | --- |
120+
| `family` | Number (1–12) | Color family (hue). 1=Red, 2=Orange, 3=Amber, 4=Yellow-Green, 5=Green, 6=Teal, 7=Cyan, 8=Blue, 9=Indigo, 10=Purple, 11=Magenta, 12=Pink |
121+
| `variant` | Number (0–9) | Lightness/chroma variant within the family. 0=darkest, 9=lightest |
122+
| `iconOnly` | Boolean | Renders the avatar with a transparent background, icon only |
123+
| `deactivated` | Boolean | Renders the avatar in a desaturated/grayed-out state |
124+
125+
### Color prop (legacy)
126+
127+
The `color` prop remains supported for backward compatibility but is now considered legacy. It is converted internally to `family`/`variant` automatically — you do not need to migrate immediately, but we recommend moving to one of the new approaches.
128+
129+
**What the old `color` values meant**
130+
131+
The `color` prop accepted a numeric string in the format `family * 100 + variant * 10`. For example:
132+
133+
- `color="540"` → family `5` (Green), variant `4`
134+
- `color="1020"` → family `10` (Purple), variant `2`
135+
- `color="800"` → family `8` (Blue), variant `0` (darkest)
136+
137+
**What to use instead**
138+
139+
For most cases — user avatars where you want a consistent color tied to the person — use **`seed`**. Pass a unique identifier such as a user ID or email address. The same seed always produces the same family and variant, so the color is stable across renders without you needing to store or manage a color code.
140+
141+
```html
142+
<!-- Before: hardcoded color code -->
143+
<dt-avatar full-name="Dialpad" color="540" />
144+
145+
<!-- After: deterministic from user ID -->
146+
<dt-avatar full-name="Dialpad" seed="user-12345" />
147+
```
148+
149+
If you need explicit control over the exact color — for example, in a branded context or design system showcase — decode your old value and use `family`/`variant` directly:
150+
151+
```html
152+
<!-- color="540" decoded: family=5, variant=4 -->
153+
<dt-avatar full-name="Dialpad" :family="5" :variant="4" />
154+
```
155+
156+
## Presence Indicator
157+
158+
The `presence` prop only renders for sizes **100–500**. Sizes 600 and above do not display presence regardless of the `presence` prop value.
159+
160+
## How to Find Usages
161+
162+
No automated migration tool. To find deprecated t-shirt size usages:
163+
164+
```bash
165+
grep -rn 'size="xs\|size="sm\|size="md\|size="lg\|size="xl' src/
166+
```
167+
168+
To find `iconSize` usages:
169+
170+
```bash
171+
grep -rn 'icon-size\|iconSize' src/
172+
```

0 commit comments

Comments
 (0)