Skip to content

Commit ff72641

Browse files
authored
fix: DLT-2398 synchronize class attrs on vue 3 components (#688)
1 parent 8c10768 commit ff72641

File tree

18 files changed

+137
-28
lines changed

18 files changed

+137
-28
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export let configVue2StyleClassAttrs = false;
2+
3+
export function enableVue2StyleClassAttrs () {
4+
configVue2StyleClassAttrs = true;
5+
}

packages/dialtone-vue3/common/utils/index.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import {
33
DEFAULT_VALIDATION_MESSAGE_TYPE,
44
VALIDATION_MESSAGE_TYPES,
55
} from '../constants';
6+
import {
7+
configVue2StyleClassAttrs,
8+
} from '../config';
69
import {
710
h,
811
Comment,
@@ -219,6 +222,39 @@ export const returnFirstEl = (el) => {
219222
}
220223
};
221224

225+
/**
226+
Only will apply changes if the config option configVue2StyleClassAttrs is set to true. It is false by default.
227+
228+
Removes the class and style attributes from the $attrs. This is useful for vue 2 to vue 3 migration
229+
purposes so we don't cause breaking changes due to INSTANCE_ATTRS_CLASS_STYLE
230+
https://v3-migration.vuejs.org/breaking-changes/attrs-includes-class-style
231+
232+
Remove the class and style attributes from the v-bind like so so v-bind="removeClassStyleAttrs($attrs)",
233+
and then apply them to the root element manually via:
234+
235+
:class="$attrs.class"
236+
:style="$attrs.style"
237+
*/
238+
export function removeClassStyleAttrs (attrs) {
239+
if (!configVue2StyleClassAttrs) return attrs;
240+
const listeners = Object.entries(attrs)
241+
.filter(([key]) => !['class', 'style'].includes(key));
242+
return Object.fromEntries(listeners);
243+
}
244+
245+
/**
246+
This should be applied to the root element on components using inheritAttrs: false.
247+
This will add the class and style attributes back to the root element if configVue2StyleClassAttrs
248+
is enabled.
249+
*/
250+
export function addClassStyleAttrs (attrs) {
251+
if (!configVue2StyleClassAttrs) return {};
252+
return {
253+
class: attrs.class,
254+
style: attrs.style,
255+
};
256+
}
257+
222258
/*
223259
* Set's a global timer to debounce the execution of a function.
224260
* @param { object } func - the function that is going to be called after timeout
@@ -473,6 +509,8 @@ export default {
473509
flushPromises,
474510
kebabCaseToPascalCase,
475511
extractVueListeners,
512+
removeClassStyleAttrs,
513+
addClassStyleAttrs,
476514
returnFirstEl,
477515
debounce,
478516
isOutOfViewPort,

packages/dialtone-vue3/components/avatar/avatar.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
:is="clickable ? 'button' : 'div'"
44
:id="id"
55
:class="avatarClasses"
6+
:style="$attrs.style"
67
data-qa="dt-avatar"
78
@click="handleClick"
89
>
@@ -302,6 +303,7 @@ export default {
302303
avatarClasses () {
303304
return [
304305
'd-avatar',
306+
this.$attrs.class,
305307
AVATAR_SIZE_MODIFIERS[this.validatedSize],
306308
this.avatarClass,
307309
{

packages/dialtone-vue3/components/breadcrumbs/breadcrumb_item.vue

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
'd-breadcrumbs__item',
66
{ [BREADCRUMB_ITEM_SELECTED_MODIFIER]: selected },
77
]"
8+
v-bind="addClassStyleAttrs($attrs)"
89
>
910
<dt-link
1011
:kind="linkKind"
1112
:inverted="linkInverted"
1213
:aria-current="ariaCurrent"
1314
data-qa="breadcrumb-item"
14-
v-bind="$attrs"
15+
v-bind="removeClassStyleAttrs($attrs)"
1516
>
1617
<!-- @slot default slot for breadcrumb item's label -->
1718
<slot>
@@ -23,6 +24,7 @@
2324

2425
<script>
2526
import { BREADCRUMB_ITEM_SELECTED_MODIFIER } from './breadcrumbs_constants';
27+
import { removeClassStyleAttrs, addClassStyleAttrs } from '@/common/utils';
2628
import { DtLink } from '../link';
2729
import { MUTED } from '../link/link_constants';
2830
@@ -64,6 +66,7 @@ export default {
6466
data () {
6567
return {
6668
BREADCRUMB_ITEM_SELECTED_MODIFIER,
69+
6770
};
6871
},
6972
@@ -80,5 +83,10 @@ export default {
8083
return this.selected ? 'location' : undefined;
8184
},
8285
},
86+
87+
methods: {
88+
removeClassStyleAttrs,
89+
addClassStyleAttrs,
90+
},
8391
};
8492
</script>

packages/dialtone-vue3/components/checkbox/checkbox.vue

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<template>
2-
<div>
2+
<div
3+
v-bind="addClassStyleAttrs($attrs)"
4+
>
35
<label>
46
<div :class="['d-checkbox-group', { 'd-checkbox-group--disabled': internalDisabled }]">
57
<div class="d-checkbox__input">
@@ -10,7 +12,7 @@
1012
:value="value"
1113
:disabled="internalDisabled"
1214
:class="['d-checkbox', inputValidationClass, inputClass]"
13-
v-bind="$attrs"
15+
v-bind="removeClassStyleAttrs($attrs)"
1416
:indeterminate.prop="internalIndeterminate"
1517
v-on="inputListeners"
1618
>
@@ -59,6 +61,7 @@ import {
5961
GroupableMixin,
6062
MessagesMixin,
6163
} from '@/common/mixins/input';
64+
import { removeClassStyleAttrs, addClassStyleAttrs } from '@/common/utils';
6265
import { CHECKBOX_INPUT_VALIDATION_CLASSES } from './checkbox_constants';
6366
import { DtValidationMessages } from '../validation_messages';
6467
@@ -156,6 +159,9 @@ export default {
156159
},
157160
158161
methods: {
162+
removeClassStyleAttrs,
163+
addClassStyleAttrs,
164+
159165
emitValue (target) {
160166
let { value, checked } = target;
161167
// Expected: Indeterminate -> unchecked. We need to manually set DOM property `checked` to false

packages/dialtone-vue3/components/input/input.vue

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<div
33
ref="container"
44
:class="['d-input__root', { 'd-input--hidden': hidden }]"
5+
v-bind="addClassStyleAttrs($attrs)"
56
data-qa="dt-input"
67
>
78
<label
@@ -74,7 +75,7 @@
7475
:class="inputClasses()"
7576
:maxlength="shouldLimitMaxLength ? validationProps.length.max : null"
7677
data-qa="dt-input-input"
77-
v-bind="$attrs"
78+
v-bind="removeClassStyleAttrs($attrs)"
7879
v-on="inputListeners"
7980
/>
8081
<input
@@ -88,7 +89,7 @@
8889
:class="inputClasses()"
8990
:maxlength="shouldLimitMaxLength ? validationProps.length.max : null"
9091
data-qa="dt-input-input"
91-
v-bind="$attrs"
92+
v-bind="removeClassStyleAttrs($attrs)"
9293
v-on="inputListeners"
9394
>
9495
<span
@@ -131,6 +132,8 @@ import {
131132
getUniqueString,
132133
getValidationState,
133134
hasSlotContent,
135+
removeClassStyleAttrs,
136+
addClassStyleAttrs,
134137
} from '@/common/utils';
135138
import { DtValidationMessages } from '@/components/validation_messages';
136139
import { MessagesMixin } from '@/common/mixins/input';
@@ -531,6 +534,8 @@ export default {
531534
},
532535
533536
methods: {
537+
removeClassStyleAttrs,
538+
addClassStyleAttrs,
534539
inputClasses () {
535540
return [
536541
'd-input__input',

packages/dialtone-vue3/components/radio/radio.vue

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<template>
2-
<div>
2+
<div
3+
v-bind="addClassStyleAttrs($attrs)"
4+
>
35
<label>
46
<div :class="['d-radio-group', { 'd-radio-group--disabled': internalDisabled }]">
57
<div class="d-radio__input">
@@ -10,7 +12,7 @@
1012
:disabled="internalDisabled"
1113
type="radio"
1214
:class="['d-radio', inputValidationClass, inputClass]"
13-
v-bind="$attrs"
15+
v-bind="removeClassStyleAttrs($attrs)"
1416
v-on="inputListeners"
1517
>
1618
</div>
@@ -57,7 +59,7 @@ import {
5759
} from '@/common/mixins/input';
5860
import { RADIO_INPUT_VALIDATION_CLASSES } from './radio_constants';
5961
import { DtValidationMessages } from '../validation_messages';
60-
import { hasSlotContent } from '@/common/utils';
62+
import { hasSlotContent, removeClassStyleAttrs, addClassStyleAttrs } from '@/common/utils';
6163
6264
/**
6365
* Radios are control elements that allow the user to make a single selection.
@@ -169,6 +171,8 @@ export default {
169171
},
170172
171173
methods: {
174+
removeClassStyleAttrs,
175+
addClassStyleAttrs,
172176
emitValue (value) {
173177
if (value !== this.radioGroupValue) {
174178
// update provided value if injected

packages/dialtone-vue3/components/select_menu/select_menu.vue

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<template>
2-
<div>
2+
<div
3+
v-bind="addClassStyleAttrs($attrs)"
4+
>
35
<label>
46
<div
57
v-if="hasSlotContent($slots.label) || label"
@@ -44,7 +46,7 @@
4446
'd-select__input',
4547
SELECT_STATE_MODIFIERS[state],
4648
]"
47-
v-bind="$attrs"
49+
v-bind="removeClassStyleAttrs($attrs)"
4850
data-qa="dt-select"
4951
:disabled="disabled"
5052
v-on="selectListeners"
@@ -88,6 +90,8 @@ import {
8890
getUniqueString,
8991
getValidationState,
9092
hasSlotContent,
93+
removeClassStyleAttrs,
94+
addClassStyleAttrs,
9195
} from '@/common/utils';
9296
import { MessagesMixin } from '@/common/mixins/input';
9397
import { optionsValidator } from './select_menu_validators.js';
@@ -298,6 +302,8 @@ export default {
298302
},
299303
300304
methods: {
305+
removeClassStyleAttrs,
306+
addClassStyleAttrs,
301307
emitValue (value, event) {
302308
this.$emit('input', value, event);
303309
this.$emit('change', value, event);

packages/dialtone-vue3/components/split_button/split_button.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ export default {
295295
size: this.size,
296296
tooltipText: this.alphaTooltipText,
297297
class: this.$attrs.class,
298+
style: this.$attrs.style,
298299
};
299300
},
300301
@@ -309,6 +310,7 @@ export default {
309310
size: this.size,
310311
tooltipText: this.omegaTooltipText,
311312
class: this.$attrs.class,
313+
style: this.$attrs.style,
312314
};
313315
},
314316
},

packages/dialtone-vue3/components/toggle/toggle.vue

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<template>
2-
<div class="d-toggle-wrapper">
2+
<div
3+
class="d-toggle-wrapper"
4+
v-bind="addClassStyleAttrs($attrs)"
5+
>
36
<label
47
v-if="hasSlotContent($slots.default)"
58
:class="labelClass"
@@ -30,7 +33,7 @@
3033

3134
<script>
3235
import { warn } from 'vue';
33-
import { getUniqueString, hasSlotContent } from '@/common/utils';
36+
import { getUniqueString, hasSlotContent, removeClassStyleAttrs, addClassStyleAttrs } from '@/common/utils';
3437
import { TOGGLE_CHECKED_VALUES, TOGGLE_SIZE_MODIFIERS } from '@/components/toggle/toggle_constants';
3538
3639
/**
@@ -146,7 +149,7 @@ export default {
146149
computed: {
147150
inputListeners () {
148151
return {
149-
...this.$attrs,
152+
...removeClassStyleAttrs(this.$attrs),
150153
onClick: _ => this.toggleCheckedValue(),
151154
};
152155
},
@@ -183,6 +186,7 @@ export default {
183186
},
184187
185188
methods: {
189+
addClassStyleAttrs,
186190
toggleCheckedValue () {
187191
this.$emit('change', !this.internalChecked);
188192

0 commit comments

Comments
 (0)