Skip to content

Commit 2e2b440

Browse files
authored
fix: apply clsx logic to custom element class attributes (#14907)
Fixes #14902
1 parent c4e9faa commit 2e2b440

File tree

4 files changed

+28
-5
lines changed

4 files changed

+28
-5
lines changed

.changeset/happy-candles-clean.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: apply `clsx` logic to custom element `class` attributes

packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,9 @@ function build_element_attribute_update_assignment(
571571
is_svg ? '$.set_svg_class' : is_mathml ? '$.set_mathml_class' : '$.set_class',
572572
node_id,
573573
value,
574-
attribute.metadata.needs_clsx ? b.literal(context.state.analysis.css.hash) : undefined
574+
attribute.metadata.needs_clsx && context.state.analysis.css.hash
575+
? b.literal(context.state.analysis.css.hash)
576+
: undefined
575577
)
576578
);
577579
} else if (name === 'value') {
@@ -648,6 +650,14 @@ function build_custom_element_attribute_update_assignment(node_id, attribute, co
648650
const name = attribute.name; // don't lowercase, as we set the element's property, which might be case sensitive
649651
let { has_call, value } = build_attribute_value(attribute.value, context);
650652

653+
// We assume that noone's going to redefine the semantics of the class attribute on custom elements, i.e. it's still used for CSS classes
654+
if (name === 'class' && attribute.metadata.needs_clsx) {
655+
if (context.state.analysis.css.hash) {
656+
value = b.array([value, b.literal(context.state.analysis.css.hash)]);
657+
}
658+
value = b.call('$.clsx', value);
659+
}
660+
651661
const update = b.stmt(b.call('$.set_custom_element_data', node_id, b.literal(name), value));
652662

653663
if (attribute.metadata.expression.has_state) {

packages/svelte/tests/runtime-runes/samples/clsx/_config.js

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { flushSync } from 'svelte';
12
import { test } from '../../test';
23

34
export default test({
@@ -14,27 +15,32 @@ export default test({
1415
<div class="foo">child</div>
1516
<div class="foo">child</div>
1617
18+
<applied-to-custom-element class="foo svelte-owbekl"></applied-to-custom-element>
19+
1720
<button>update</button>
1821
`,
1922
test({ assert, target }) {
2023
const button = target.querySelector('button');
2124

2225
button?.click();
26+
flushSync();
2327

2428
assert.htmlEqual(
2529
target.innerHTML,
2630
`
2731
<div class="foo svelte-owbekl"></div>
2832
<div class="foo svelte-owbekl"></div>
29-
<div class="foo svelte-owbekl"></div>
30-
<div class="foo svelte-owbekl"></div>
33+
<div class="bar svelte-owbekl"></div>
34+
<div class="bar svelte-owbekl"></div>
3135
<div class="foo svelte-owbekl"></div>
3236
3337
<div class="foo">child</div>
3438
<div class="foo">child</div>
39+
<div class="bar">child</div>
40+
<div class="bar">child</div>
3541
<div class="foo">child</div>
36-
<div class="foo">child</div>
37-
<div class="foo">child</div>
42+
43+
<applied-to-custom-element class="bar svelte-owbekl"></applied-to-custom-element>
3844
3945
<button>update</button>
4046
`

packages/svelte/tests/runtime-runes/samples/clsx/main.svelte

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
<Child class={[ foo, bar ]} />
1919
<Child {...spread} />
2020

21+
<applied-to-custom-element class={{ foo, bar }}></applied-to-custom-element>
22+
2123
<button onclick={() => {
2224
foo = null;
2325
bar = 'bar';

0 commit comments

Comments
 (0)