Skip to content

Commit 1d26a4e

Browse files
refactor(components,recipes): DLT-3043 DLT-3046 logical start/end naming with deprecated backward-compatible fallbacks (#1079)
1 parent 42dc418 commit 1d26a4e

133 files changed

Lines changed: 3642 additions & 1087 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.

.claude/rules/logical-naming.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Logical Naming Convention
2+
3+
## Direction Names
4+
5+
Use logical names in all new component code, e.g.:
6+
7+
- `start` / `end` (inline axis — replaces `left` / `right`)
8+
- `blockStart` / `blockEnd` (block axis — replaces `top` / `bottom`)
9+
- `startIcon` / `endIcon` (replaces `leftIcon` / `rightIcon` or `alphaIcon` / `omegaIcon`)
10+
11+
## Deprecated Slot Backward Compatibility
12+
13+
Use the `v-if`/`v-else` pattern (NOT nested slots) for deprecated slot fallbacks:
14+
15+
```vue
16+
<!-- @slot Slot for start content -->
17+
<slot v-if="$slots.start" name="start" />
18+
<!-- @slot @deprecated Use start -->
19+
<slot v-else name="left" />
20+
```
21+
22+
For scoped slots, pass the same bindings to both:
23+
24+
```vue
25+
<slot v-if="$slots.startIcon" name="startIcon" :icon-size="iconSize" />
26+
<slot v-else name="leftIcon" :icon-size="iconSize" />
27+
```
28+
29+
Use `$slots.xxx` for the inner choice (matches nested-slot behavior: an empty `#start` still suppresses `#left`). Use `hasSlotContent($slots.xxx)` for outer visibility guards that control wrapper element rendering.
30+
31+
## Deprecated Props
32+
33+
Use sentinel defaults with nullish coalescing:
34+
35+
- **String** deprecated props: `default: undefined`, resolve with `??`
36+
- **Boolean** deprecated props: `default: null`, resolve with `??`
37+
38+
```js
39+
// In props:
40+
startClass: { type: String, default: '' },
41+
/** @deprecated Use startClass */
42+
leftClass: { type: String, default: undefined },
43+
44+
// In computed:
45+
resolvedStartClass () {
46+
return this.leftClass ?? this.startClass;
47+
}
48+
```
49+
50+
## Deprecated Events
51+
52+
Emit both new and old event names:
53+
54+
```js
55+
onStartClick () {
56+
this.$emit('start-clicked');
57+
this.$emit('alpha-clicked');
58+
},
59+
```

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
root-class="d-w332"
1010
@keydown.escape="handleEscapeKey"
1111
>
12-
<template #leftIcon="{ iconSize }">
12+
<template #startIcon="{ iconSize }">
1313
<dt-icon name="search" :size="iconSize" />
1414
</template>
15-
<template v-if="inputSearchValue.length !== 0" #rightIcon>
15+
<template v-if="inputSearchValue.length !== 0" #endIcon>
1616
<dt-stack class="d-pr1">
1717
<dt-button
1818
v-dt-tooltip="`Clear`"
@@ -22,7 +22,7 @@
2222
aria-label="Clear search"
2323
@click="clearSearch"
2424
>
25-
<template #icon>
25+
<template #startIcon>
2626
<dt-icon name="close" size="100" />
2727
</template>
2828
</dt-button>
@@ -58,12 +58,11 @@
5858
class="dialtone-doc-table-clamped__more-btn d-bgc-secondary d-bs-sm"
5959
kind="muted"
6060
importance="outlined"
61-
icon-position="right"
6261
size="sm"
6362
@click="() => handleExpand(scrollRef)"
6463
>
6564
{{ buttonLabel }}
66-
<template #icon="{ iconSize }">
65+
<template #endIcon="{ iconSize }">
6766
<dt-icon :name="iconName" :size="iconSize" />
6867
</template>
6968
</dt-button>

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,11 @@
6363
class="code-example-tab-group__more-btn d-bgc-secondary d-bs-sm"
6464
kind="muted"
6565
importance="outlined"
66-
icon-position="right"
6766
size="sm"
6867
@click="expandCodeBlocks"
6968
>
7069
Show all
71-
<template #icon="{ iconSize }">
70+
<template #endIcon="{ iconSize }">
7271
<dt-icon name="arrow-down" :size="iconSize" />
7372
</template>
7473
</dt-button>

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

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,36 +79,59 @@ const highlightedImport = computed(() => {
7979
return Prism.highlight(importStatement.value, Prism.languages.javascript, 'javascript');
8080
});
8181
82+
const isDeprecated = (item) => {
83+
return item.tags?.deprecated?.length > 0 ||
84+
/(@deprecated|deprecated[,)])/i.test(item.description || '');
85+
};
86+
87+
const deprecationMessage = (item) => {
88+
const tag = item.tags?.deprecated?.[0]?.description;
89+
if (tag) return tag;
90+
const desc = item.description || '';
91+
const match = desc.match(/deprecated,?\s*use\s+([\w.]+)/i) ||
92+
desc.match(/@deprecated\s+Use\s+([\w.]+)/i);
93+
return match ? `Use ${match[1]}` : null;
94+
};
95+
8296
const docSlots = componentDocs.find(f => isSameComponentName(f.displayName))
8397
?.slots?.map((item) => {
8498
return {
8599
name: item.name,
86-
description: item.description,
100+
description: isDeprecated(item) ? undefined : item.description,
101+
deprecated: isDeprecated(item),
102+
deprecatedMessage: deprecationMessage(item),
87103
};
88104
});
89105
106+
const resolveConstantRef = (rawDefault, values) => {
107+
const match = rawDefault.match(/^[A-Z][A-Z_]*\.[A-Z][A-Z_]*$/);
108+
if (!match) return rawDefault;
109+
const key = rawDefault.split('.')[1].toLowerCase().replace(/_/g, '-');
110+
const found = values.find(v => v === key || v === key.replace(/-/g, '_'));
111+
if (found) return found;
112+
if (key === 'none' && values.includes('null')) return 'null';
113+
return rawDefault;
114+
};
115+
90116
const resolveDefaultValue = (rawDefault, values) => {
91117
if (!rawDefault) return rawDefault;
92118
if (rawDefault === 'undefined') return null;
93119
if (/getUniqueString\(\)/.test(rawDefault)) return 'generated unique ID';
94120
if (!values?.length) return rawDefault;
95-
// Match constant references like DT_MODE_ISLAND_TYPES.INVERTED
96-
const match = rawDefault.match(/^[A-Z][A-Z_]*\.[A-Z][A-Z_]*$/);
97-
if (!match) return rawDefault;
98-
const key = rawDefault.split('.')[1].toLowerCase().replace(/_/g, '-');
99-
return values.find(v => v === key || v === key.replace(/-/g, '_'))
100-
?? (key === 'none' && values.includes('null') ? 'null' : rawDefault);
121+
return resolveConstantRef(rawDefault, values);
101122
};
102123
103124
const docProps = componentDocs.find(f => isSameComponentName(f.displayName))
104125
?.props?.map((item) => {
105126
return {
106-
name: item?.name,
107-
description: item?.description,
108-
type: item?.type?.name,
109-
defaultValue: resolveDefaultValue(item?.defaultValue?.value, item?.values),
110-
values: item?.values,
111-
required: item?.required,
127+
name: item.name,
128+
description: item.description,
129+
type: item.type?.name,
130+
defaultValue: resolveDefaultValue(item.defaultValue?.value, item.values),
131+
values: item.values,
132+
required: item.required,
133+
deprecated: isDeprecated(item),
134+
deprecatedMessage: deprecationMessage(item),
112135
};
113136
});
114137
@@ -118,6 +141,8 @@ const docEvents = componentDocs.find(f => isSameComponentName(f.displayName))
118141
name: item.name,
119142
description: item.description,
120143
type: item.type?.names.join(' '),
144+
deprecated: isDeprecated(item),
145+
deprecatedMessage: deprecationMessage(item),
121146
};
122147
});
123148
</script>

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

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,67 +40,83 @@
4040
</thead>
4141
<tbody>
4242
<tr
43-
v-for="({ name, description, type, defaultValue, values, required }) in sortedTableDataByName"
44-
:key="name"
43+
v-for="item in sortedTableDataByName"
44+
:key="item.name"
4545
class="d-va-baseline"
4646
>
4747
<th scope="row">
4848
<dt-stack gap="300">
4949
<span>
5050
<code class="d-code--sm d-docsite-code">
51-
{{ name }}
51+
{{ item.name }}
5252
</code>
5353
</span>
5454
<div
55-
v-if="required"
55+
v-if="item.required"
5656
class="d-fc-critical d-fw-normal"
5757
>
5858
required
5959
</div>
60+
<span v-if="item.deprecated">
61+
<dt-badge
62+
type="critical"
63+
kind="label"
64+
text="Deprecated"
65+
/>
66+
</span>
6067
</dt-stack>
6168
</th>
6269

6370
<td v-if="withDefault">
64-
<code v-if="defaultValue" class="d-code--sm d-docsite-code">
65-
{{ defaultValue }}
71+
<code v-if="item.defaultValue" class="d-code--sm d-docsite-code">
72+
{{ item.defaultValue }}
6673
</code>
6774
</td>
6875

6976
<td class="vue-api-table">
7077
<dt-stack gap="350">
7178
<dt-stack
72-
v-if="values"
79+
v-if="item.values"
7380
direction="row"
7481
align="baseline"
7582
class="d-fw-wrap"
7683
gap="350"
7784
>
7885
<template
79-
v-for="(value, index) in values"
80-
:key="`${name} ${value}`"
86+
v-for="(value, index) in item.values"
87+
:key="`${item.name} ${value}`"
8188
>
8289
<dt-text v-if="index > 0" tone="muted" as="span" kind="body" size="xs">
8390
|
8491
</dt-text>
8592
<code class="d-code--sm d-docsite-code">"{{ value }}"</code>
8693
</template>
8794
</dt-stack>
88-
<span v-else-if="type">
95+
<span v-else-if="item.type">
8996
<code class="d-code--sm d-docsite-code">
90-
{{ type }}
97+
{{ item.type }}
9198
</code>
9299
</span>
93100
<dt-text
94-
v-if="description"
101+
v-if="item.description"
95102
as="p"
96103
kind="body"
97104
size="sm"
98105
wrap="balance"
99106
>
100107
<markdown-render
101-
:markdown="description"
108+
:markdown="item.description"
102109
/>
103110
</dt-text>
111+
<dt-text
112+
v-if="item.deprecated && item.deprecatedMessage"
113+
as="p"
114+
kind="body"
115+
size="sm"
116+
class="d-fc-critical"
117+
>
118+
{{ item.deprecatedMessage }}
119+
</dt-text>
104120
</dt-stack>
105121
</td>
106122
</tr>
@@ -141,16 +157,14 @@ const sortDataByKey = (data, nameKey, requiredKey) => {
141157
return data.sort((a, b) => {
142158
const aIsRequired = !!a[requiredKey];
143159
const bIsRequired = !!b[requiredKey];
160+
const aIsDeprecated = !!a.deprecated;
161+
const bIsDeprecated = !!b.deprecated;
144162
145-
// always have required at top
146-
if (aIsRequired && !bIsRequired) {
147-
return -1;
148-
} else if (!aIsRequired && bIsRequired) {
149-
return 1;
150-
} else {
151-
if (a[nameKey] < b[nameKey]) return -1;
152-
if (a[nameKey] > b[nameKey]) return 1;
153-
}
163+
// Required first, deprecated last, then alphabetical
164+
if (aIsRequired !== bIsRequired) return aIsRequired ? -1 : 1;
165+
if (aIsDeprecated !== bIsDeprecated) return aIsDeprecated ? 1 : -1;
166+
if (a[nameKey] < b[nameKey]) return -1;
167+
if (a[nameKey] > b[nameKey]) return 1;
154168
return 0;
155169
});
156170
};

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
kind="muted"
1212
@click="copyToClipboard"
1313
>
14-
<template #icon="{ iconSize }">
14+
<template #startIcon="{ iconSize }">
1515
<dt-icon
1616
name="copy"
1717
:size="iconSize"

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@
1414
<dt-button
1515
class="dialtone-icon-grid__item d-gg8"
1616
label-class="d-fl-grow-unset"
17-
icon-position="top"
1817
importance="clear"
1918
kind="muted"
2019
:active="modelValue"
2120
>
22-
<template #icon>
21+
<template #blockStartIcon>
2322
<dt-icon
2423
:name="iconName"
2524
size="600"

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
autocomplete="off"
1212
@keyup="searchToken"
1313
>
14-
<template #leftIcon>
14+
<template #startIcon>
1515
<dt-icon name="search" size="300" />
1616
</template>
17-
<template #rightIcon>
17+
<template #endIcon>
1818
<dt-button
1919
v-if="hasSearchTerm"
2020
id="search-input-button-close"
@@ -25,7 +25,7 @@
2525
aria-label="Clear search"
2626
@click="resetSearch"
2727
>
28-
<template #icon>
28+
<template #startIcon>
2929
<dt-icon name="close" size="200" />
3030
</template>
3131
</dt-button>
@@ -60,12 +60,11 @@
6060
v-dt-tooltip:top-end="shareLinkTooltip"
6161
importance="clear"
6262
kind="muted"
63-
icon-position="left"
6463
class="d-ml-auto"
6564
@click="copyURLToClipboard"
6665
>
6766
Share Search Filter
68-
<template #icon="{ iconSize }">
67+
<template #startIcon="{ iconSize }">
6968
<dt-icon
7069
name="link-2"
7170
:size="iconSize"

apps/dialtone-documentation/docs/.vuepress/exampleComponents/ExampleProfileCard.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,19 @@
2828
</dt-stack>
2929
<dt-stack gap="400" direction="row" justify="between">
3030
<dt-button class="d-fl1" kind="muted" importance="outlined">
31-
<template #icon="{ iconSize }">
31+
<template #startIcon="{ iconSize }">
3232
<dt-icon-phone :size="iconSize" />
3333
</template>
3434
Call
3535
</dt-button>
3636
<dt-button class="d-fl1" kind="muted" importance="outlined">
37-
<template #icon="{ iconSize }">
37+
<template #startIcon="{ iconSize }">
3838
<dt-icon-quick-reply :size="iconSize" />
3939
</template>
4040
Message
4141
</dt-button>
4242
<dt-button class="d-fl1" kind="muted" importance="outlined">
43-
<template #icon="{ iconSize }">
43+
<template #startIcon="{ iconSize }">
4444
<dt-icon-video :size="iconSize" />
4545
</template>
4646
Meet

0 commit comments

Comments
 (0)