From e4ad69ea76ec96add0cd0580d8da02803fb66397 Mon Sep 17 00:00:00 2001 From: Mathias Picker <48158184+MathiasWP@users.noreply.github.com> Date: Tue, 5 May 2026 12:36:20 +0200 Subject: [PATCH 01/10] feat: allow style attribute to be an object or array Mirrors the clsx-style ergonomics that `class` has had since 5.16. The `style` attribute now accepts an object, array, or any nested combination, normalised by a small runtime helper alongside the existing `to_style`. Object keys are emitted verbatim (no camelCase conversion), falsy entries are dropped, and existing `style:` directive precedence is unchanged. --- .changeset/style-attribute-objects.md | 5 + .../docs/03-template-syntax/17-style.md | 98 +++++++++++- packages/svelte/elements.d.ts | 6 +- .../svelte/src/internal/shared/attributes.js | 40 +++++ .../samples/style-object/_config.js | 145 ++++++++++++++++++ .../samples/style-object/main.svelte | 82 ++++++++++ 6 files changed, 372 insertions(+), 4 deletions(-) create mode 100644 .changeset/style-attribute-objects.md create mode 100644 packages/svelte/tests/runtime-runes/samples/style-object/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/style-object/main.svelte diff --git a/.changeset/style-attribute-objects.md b/.changeset/style-attribute-objects.md new file mode 100644 index 0000000000..63a65575a6 --- /dev/null +++ b/.changeset/style-attribute-objects.md @@ -0,0 +1,5 @@ +--- +'svelte': minor +--- + +feat: allow `style` attribute to be an object or array, mirroring the `class` attribute diff --git a/documentation/docs/03-template-syntax/17-style.md b/documentation/docs/03-template-syntax/17-style.md index 6ddb128f4a..940bec5f34 100644 --- a/documentation/docs/03-template-syntax/17-style.md +++ b/documentation/docs/03-template-syntax/17-style.md @@ -1,8 +1,99 @@ --- -title: style: +title: style tags: template-style --- +There are two ways to set inline styles on elements: the `style` attribute, and the `style:` directive. + +## Attributes + +Primitive values are treated like any other attribute: + +```svelte +
...
+
...
+``` + +### Objects and arrays + +Since Svelte 5.56, `style` can be an object or array, and is converted to a CSS declaration string using the same rules as the [`class` attribute](class). + +If the value is an object, each entry becomes a declaration: + +```svelte + +
...
+``` + +> [!NOTE] +> Object keys are written as the literal CSS property name — `'background-color'`, not `backgroundColor`. Svelte does not convert between `camelCase` and `kebab-case`. + +Entries whose value is `false`, `null`, `undefined` or the empty string are skipped, which is useful for conditional styles: + +```svelte + +
...
+``` + +If the value is an array, the truthy entries are combined: + +```svelte + +
...
+``` + +Arrays can contain arrays, objects and strings, which Svelte flattens. This is useful for combining local styles with props, for example: + +```svelte + + + + +``` + +The user of this component has the same flexibility to use a mixture of objects, arrays and strings: + +```svelte + + + + +``` + +CSS custom properties work the same way: + +```svelte +
...
+``` + +Since Svelte 5.56, Svelte also exposes the `StyleValue` type, which is the type of value that the `style` attribute on elements accepts. This is useful if you want to use a type-safe style value in component props: + +```svelte + + +
...
+``` + +## The `style:` directive + The `style:` directive provides a shorthand for setting multiple styles on an element. ```svelte @@ -35,12 +126,13 @@ To mark a style as important, use the `|important` modifier:
...
``` -When `style:` directives are combined with `style` attributes, the directives will take precedence, -even over `!important` properties: +When `style:` directives are combined with the `style` attribute, the directives take precedence, +even over `!important` properties, and regardless of whether the attribute is a string or an object: ```svelte
This will be red
This will still be red
+
This will be red
``` You can set CSS custom properties: diff --git a/packages/svelte/elements.d.ts b/packages/svelte/elements.d.ts index f18b7dea98..d67890f3fc 100644 --- a/packages/svelte/elements.d.ts +++ b/packages/svelte/elements.d.ts @@ -1547,7 +1547,7 @@ export interface SVGAttributes extends AriaAttributes, DO method?: 'align' | 'stretch' | undefined | null; min?: number | string | undefined | null; name?: string | undefined | null; - style?: string | undefined | null; + style?: StyleValue | undefined | null; target?: string | undefined | null; type?: string | undefined | null; width?: number | string | undefined | null; @@ -2076,3 +2076,7 @@ export interface SvelteHTMLElements { } export type ClassValue = string | import('clsx').ClassArray | import('clsx').ClassDictionary; + +export type StyleDictionary = Record; +export type StyleArray = Array; +export type StyleValue = string | number | StyleDictionary | StyleArray | false | null | undefined; diff --git a/packages/svelte/src/internal/shared/attributes.js b/packages/svelte/src/internal/shared/attributes.js index 487a40baf3..da54b897e1 100644 --- a/packages/svelte/src/internal/shared/attributes.js +++ b/packages/svelte/src/internal/shared/attributes.js @@ -108,6 +108,39 @@ function append_styles(styles, important = false) { return css; } +/** + * Convert a style attribute value (string | object | array | falsy) into a CSS + * declaration string. Mirrors clsx's behaviour for `class`: arrays are flattened, + * falsy entries are dropped, object keys are emitted verbatim (no camelCase ↔ + * kebab-case transform), and pre-formatted strings pass through unchanged. + * @param {any} value + * @returns {string} + */ +function style_value_to_string(value) { + if (value == null || value === false || value === '') return ''; + if (typeof value === 'string') return value; + if (Array.isArray(value)) { + var array_result = ''; + for (var i = 0; i < value.length; i++) { + // Strip trailing `;` so concatenating user-authored strings (which often end + // with one) doesn't produce `;;` which can confuse strict CSS parsers. + var part = style_value_to_string(value[i]).replace(/\s*;\s*$/, ''); + if (part) array_result += (array_result ? '; ' : '') + part; + } + return array_result; + } + if (typeof value === 'object') { + var object_result = ''; + for (var key of Object.keys(value)) { + var v = value[key]; + if (v == null || v === false || v === '') continue; + object_result += (object_result ? '; ' : '') + key + ': ' + v; + } + return object_result; + } + return String(value); +} + /** * @param {string} name * @returns {string} @@ -125,6 +158,13 @@ function to_css_name(name) { * @returns {string | null} */ export function to_style(value, styles) { + // `class` accepts strings, objects and arrays via clsx; mirror that for `style` + // by normalising non-string values into a CSS declaration string upfront so the + // existing parser (which expects a string) handles directive merging unchanged. + if (value != null && typeof value !== 'string') { + value = style_value_to_string(value); + } + if (styles) { var new_style = ''; diff --git a/packages/svelte/tests/runtime-runes/samples/style-object/_config.js b/packages/svelte/tests/runtime-runes/samples/style-object/_config.js new file mode 100644 index 0000000000..19d4ecf8cb --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/style-object/_config.js @@ -0,0 +1,145 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + mode: ['client', 'hydrate', 'server'], + + async test({ assert, target }) { + const get = (/** @type {string} */ id) => + /** @type {HTMLElement} */ (target.querySelector('#' + id)); + + // --- inline literal cases --- + + // inline object literal + assert.equal(get('inline-object').style.color, 'red'); + assert.equal(get('inline-object').style.backgroundColor, 'blue'); + + // inline array of strings + assert.equal(get('inline-array-strings').style.color, 'red'); + assert.equal(get('inline-array-strings').style.backgroundColor, 'blue'); + + // inline array mixing strings and objects (and stray trailing semicolons) + assert.equal(get('inline-array-mixed').style.color, 'red'); + assert.equal(get('inline-array-mixed').style.padding, '4px'); + assert.equal(get('inline-array-mixed').style.margin, '2px'); + + // numeric values, including 0 + assert.equal(get('numeric').style.zIndex, '0'); + assert.equal(get('numeric').style.opacity, '1'); + assert.equal(get('numeric').style.lineHeight, '1.5'); + + // nested arrays are flattened + assert.equal(get('nested').style.color, 'red'); + assert.equal(get('nested').style.padding, '4px'); + assert.equal(get('nested').style.margin, '2px'); + + // all entries falsy → attribute absent (or empty) + assert.notOk(get('all-falsy').getAttribute('style')); + + // empty object → empty style attribute (parallels clsx({}) === '') + const empty_attr = get('empty-object').getAttribute('style'); + assert.ok(empty_attr === '' || empty_attr === null); + + // conditional inline object: dropped when the gate is false + assert.equal(get('conditional').style.padding, '4px'); + assert.equal(get('conditional').style.color, ''); + + // `false`/null/undefined values inside an object are skipped per-property + assert.equal(get('falsy-property').style.color, 'red'); + assert.equal(get('falsy-property').style.backgroundColor, ''); + assert.equal(get('falsy-property').style.padding, ''); + assert.equal(get('falsy-property').style.margin, ''); + + // reactive cases via direct $state reads: initial render + assert.equal(get('reactive-object').style.color, 'red'); + assert.equal(get('reactive-object').style.backgroundColor, ''); + assert.equal(get('reactive-array').style.padding, '2px'); + assert.equal(get('reactive-array').style.color, 'red'); + assert.equal(get('reactive-array').style.borderColor, ''); + + // CSS custom properties are emitted verbatim + assert.equal(get('custom-prop').style.getPropertyValue('--my-color'), 'red'); + assert.equal(get('custom-prop').style.getPropertyValue('--scale'), '1'); + + // style: directive wins on overlapping property + assert.equal(get('directive-precedence').style.color, 'blue'); + assert.equal(get('directive-precedence').style.padding, '4px'); + + // spread + assert.equal(get('spread').style.color, 'red'); + assert.equal(get('spread').style.padding, '1px'); + + // --- $derived cases --- + + // $derived returning an object + assert.equal(get('derived-object').style.color, 'red'); + assert.equal(get('derived-object').style.padding, '2px'); + + // $derived returning a mixed array + assert.equal(get('derived-array').style.margin, '2px'); + assert.equal(get('derived-array').style.color, 'red'); + assert.equal(get('derived-array').style.borderWidth, '2px'); + + // $derived returning a string + assert.equal(get('derived-string').style.color, 'red'); + assert.equal(get('derived-string').style.opacity, '1'); + + // $derived nested inside an inline array, alongside a literal + assert.equal(get('derived-in-array').style.outline, '1px solid red'); + assert.equal(get('derived-in-array').style.color, 'red'); + assert.equal(get('derived-in-array').style.padding, '2px'); + + // $derived gated by a condition: when falsy, no attribute should be emitted + assert.notOk(get('derived-conditional').getAttribute('style')); + + // $derived combined with style: directive — directive wins + assert.equal(get('derived-directive').style.color, 'blue'); + assert.equal(get('derived-directive').style.padding, '2px'); + + // $derived inside spread + assert.equal(get('derived-spread').style.color, 'red'); + assert.equal(get('derived-spread').style.padding, '2px'); + + // $derived object with conditional falsy values + assert.equal(get('derived-falsy').style.color, 'red'); + assert.equal(get('derived-falsy').style.backgroundColor, ''); + assert.equal(get('derived-falsy').style.borderColor, 'black'); + + // --- reactivity --- + + const button = /** @type {HTMLButtonElement} */ (target.querySelector('button')); + button.click(); + flushSync(); + + // inline reactive: $state reads recompute + assert.equal(get('reactive-object').style.color, 'green'); + assert.equal(get('reactive-object').style.backgroundColor, 'yellow'); + assert.equal(get('reactive-array').style.color, 'green'); + assert.equal(get('reactive-array').style.borderColor, 'green'); + assert.equal(get('conditional').style.color, 'green'); + assert.equal(get('custom-prop').style.getPropertyValue('--my-color'), 'green'); + assert.equal(get('directive-precedence').style.color, 'blue'); // still wins + assert.equal(get('spread').style.color, 'green'); + + // $derived cases recompute + assert.equal(get('derived-object').style.color, 'green'); + assert.equal(get('derived-object').style.padding, '8px'); + assert.equal(get('derived-array').style.color, 'green'); + assert.equal(get('derived-array').style.borderWidth, '8px'); + assert.equal(get('derived-string').style.color, 'green'); + assert.equal(get('derived-string').style.opacity, '0.5'); + assert.equal(get('derived-in-array').style.color, 'green'); + assert.equal(get('derived-in-array').style.padding, '8px'); + // derived-conditional now resolves to a real object + assert.equal(get('derived-conditional').style.backgroundColor, 'yellow'); + // derived-directive: directive still wins, but padding tracks the derived + assert.equal(get('derived-directive').style.color, 'blue'); + assert.equal(get('derived-directive').style.padding, '8px'); + assert.equal(get('derived-spread').style.color, 'green'); + assert.equal(get('derived-spread').style.padding, '8px'); + // derived-falsy: now `background-color` shows up and `border-color` drops + assert.equal(get('derived-falsy').style.color, 'green'); + assert.equal(get('derived-falsy').style.backgroundColor, 'yellow'); + assert.equal(get('derived-falsy').style.borderColor, ''); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/style-object/main.svelte b/packages/svelte/tests/runtime-runes/samples/style-object/main.svelte new file mode 100644 index 0000000000..79c3d98b28 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/style-object/main.svelte @@ -0,0 +1,82 @@ + + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + From 3e2d1a89c3ae4adb5c18d8e410431a5c6adcf29c Mon Sep 17 00:00:00 2001 From: Mathias Picker <48158184+MathiasWP@users.noreply.github.com> Date: Tue, 5 May 2026 12:42:40 +0200 Subject: [PATCH 02/10] chore: drop redundant '' check in style_value_to_string The empty string already falls through to the `typeof value === 'string'` branch which returns it as-is, so the explicit check was redundant. --- packages/svelte/src/internal/shared/attributes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte/src/internal/shared/attributes.js b/packages/svelte/src/internal/shared/attributes.js index da54b897e1..99a0b13d92 100644 --- a/packages/svelte/src/internal/shared/attributes.js +++ b/packages/svelte/src/internal/shared/attributes.js @@ -117,7 +117,7 @@ function append_styles(styles, important = false) { * @returns {string} */ function style_value_to_string(value) { - if (value == null || value === false || value === '') return ''; + if (value == null || value === false) return ''; if (typeof value === 'string') return value; if (Array.isArray(value)) { var array_result = ''; From cd5b9add374449ccb39cd436225813ae753894b8 Mon Sep 17 00:00:00 2001 From: Mathias Picker <48158184+MathiasWP@users.noreply.github.com> Date: Tue, 5 May 2026 13:04:20 +0200 Subject: [PATCH 03/10] fix: also widen HTMLAttributes['style'] to StyleValue I only updated SVGAttributes['style'] in the previous commit and missed the HTMLAttributes one, which left object/array styles failing the type check on regular HTML elements. --- packages/svelte/elements.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte/elements.d.ts b/packages/svelte/elements.d.ts index d67890f3fc..f19f36eb1d 100644 --- a/packages/svelte/elements.d.ts +++ b/packages/svelte/elements.d.ts @@ -776,7 +776,7 @@ export interface HTMLAttributes extends AriaAttributes, D placeholder?: string | undefined | null; slot?: string | undefined | null; spellcheck?: Booleanish | undefined | null; - style?: string | undefined | null; + style?: StyleValue | undefined | null; tabindex?: number | undefined | null; title?: string | undefined | null; translate?: 'yes' | 'no' | '' | undefined | null; From b6b6d0386901cac3dd0f927b438b4a4359840df9 Mon Sep 17 00:00:00 2001 From: Mathias Picker <48158184+MathiasWP@users.noreply.github.com> Date: Tue, 5 May 2026 13:52:23 +0200 Subject: [PATCH 04/10] fix: drop style attribute when value normalises to empty Previously the client kept an empty `style=""` for empty-string values while SSR dropped the attribute, which is a hydration mismatch and now also affects every object/array input that filters down to nothing (`style={false}`, `style={{}}`, `style={[null, false]}`). Coerce empty to `null` in `to_style` so client and SSR agree, matching what the directive path already did and what `to_class` does for `class={''}`. Two existing tests asserted `
` for `component.style = ''` as an incidental side effect; updated to expect the attribute dropped. --- packages/svelte/src/internal/shared/attributes.js | 4 +++- .../samples/async-fork-attributes/_config.js | 8 ++++---- .../runtime-runes/samples/style-update/_config.js | 10 ++++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/svelte/src/internal/shared/attributes.js b/packages/svelte/src/internal/shared/attributes.js index 99a0b13d92..cb45af1839 100644 --- a/packages/svelte/src/internal/shared/attributes.js +++ b/packages/svelte/src/internal/shared/attributes.js @@ -261,5 +261,7 @@ export function to_style(value, styles) { return new_style === '' ? null : new_style; } - return value == null ? null : String(value); + // Empty results drop the attribute entirely so that client and SSR agree + // (the directive path above already returns `null` for empty output). + return value == null || value === '' ? null : String(value); } diff --git a/packages/svelte/tests/runtime-runes/samples/async-fork-attributes/_config.js b/packages/svelte/tests/runtime-runes/samples/async-fork-attributes/_config.js index 59bcdeb7f5..7c64866995 100644 --- a/packages/svelte/tests/runtime-runes/samples/async-fork-attributes/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/async-fork-attributes/_config.js @@ -12,8 +12,8 @@ export default test({ ` -

foo

-

foo

+

foo

+

foo

foo

` ); @@ -51,8 +51,8 @@ export default test({ ` -

foo

-

foo

+

foo

+

foo

foo

` ); diff --git a/packages/svelte/tests/runtime-runes/samples/style-update/_config.js b/packages/svelte/tests/runtime-runes/samples/style-update/_config.js index 52690a431a..347ed46c36 100644 --- a/packages/svelte/tests/runtime-runes/samples/style-update/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/style-update/_config.js @@ -37,14 +37,16 @@ export default test({ component.style = ''; flushSync(); + // empty results drop the attribute on both client and SSR (was previously + // `
` on the client only — a hydration mismatch) assert.htmlEqual( target.innerHTML, ` -
-
+
+
- - + + ` ); From b87eb5a893372a65e3dadca295aca79ffc2f9e33 Mon Sep 17 00:00:00 2001 From: Mathias Picker <48158184+MathiasWP@users.noreply.github.com> Date: Tue, 5 May 2026 13:54:14 +0200 Subject: [PATCH 05/10] chore: drop redundant String() coercion in to_style After the new normalization step, `value` at the final return is always either null/undefined or a string, so `String(value)` is doing nothing. --- packages/svelte/src/internal/shared/attributes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte/src/internal/shared/attributes.js b/packages/svelte/src/internal/shared/attributes.js index cb45af1839..f2602055a1 100644 --- a/packages/svelte/src/internal/shared/attributes.js +++ b/packages/svelte/src/internal/shared/attributes.js @@ -263,5 +263,5 @@ export function to_style(value, styles) { // Empty results drop the attribute entirely so that client and SSR agree // (the directive path above already returns `null` for empty output). - return value == null || value === '' ? null : String(value); + return value == null || value === '' ? null : value; } From 88b1a2f4b470468eacb3b3dad59b8b567f6672a5 Mon Sep 17 00:00:00 2001 From: Mathias Picker <48158184+MathiasWP@users.noreply.github.com> Date: Tue, 5 May 2026 14:33:24 +0200 Subject: [PATCH 06/10] chore: drop redundant comment in style-update test --- .../svelte/tests/runtime-runes/samples/style-update/_config.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/svelte/tests/runtime-runes/samples/style-update/_config.js b/packages/svelte/tests/runtime-runes/samples/style-update/_config.js index 347ed46c36..f7ab5ab5ba 100644 --- a/packages/svelte/tests/runtime-runes/samples/style-update/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/style-update/_config.js @@ -37,8 +37,6 @@ export default test({ component.style = ''; flushSync(); - // empty results drop the attribute on both client and SSR (was previously - // `
` on the client only — a hydration mismatch) assert.htmlEqual( target.innerHTML, ` From f080b412eed0e2b846a3bdf12e1a623604fdeb4b Mon Sep 17 00:00:00 2001 From: Mathias Picker <48158184+MathiasWP@users.noreply.github.com> Date: Tue, 5 May 2026 17:29:33 +0200 Subject: [PATCH 07/10] Update packages/svelte/elements.d.ts Refactor StyleValue types Co-authored-by: 7nik --- packages/svelte/elements.d.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/svelte/elements.d.ts b/packages/svelte/elements.d.ts index f19f36eb1d..9d7386ed85 100644 --- a/packages/svelte/elements.d.ts +++ b/packages/svelte/elements.d.ts @@ -2077,6 +2077,5 @@ export interface SvelteHTMLElements { export type ClassValue = string | import('clsx').ClassArray | import('clsx').ClassDictionary; -export type StyleDictionary = Record; -export type StyleArray = Array; -export type StyleValue = string | number | StyleDictionary | StyleArray | false | null | undefined; +type StylePrimitive = string | number | false | null | undefined; +export type StyleValue = StylePrimitive | StyleValue[] | { [key: string]: StyleValue }; From c473713341b583bd1e0539352bb28c62fa22c8ee Mon Sep 17 00:00:00 2001 From: Mathias Picker <48158184+MathiasWP@users.noreply.github.com> Date: Tue, 5 May 2026 19:57:59 +0200 Subject: [PATCH 08/10] Update packages/svelte/elements.d.ts Co-authored-by: 7nik --- packages/svelte/elements.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte/elements.d.ts b/packages/svelte/elements.d.ts index 9d7386ed85..ad5815facd 100644 --- a/packages/svelte/elements.d.ts +++ b/packages/svelte/elements.d.ts @@ -2078,4 +2078,4 @@ export interface SvelteHTMLElements { export type ClassValue = string | import('clsx').ClassArray | import('clsx').ClassDictionary; type StylePrimitive = string | number | false | null | undefined; -export type StyleValue = StylePrimitive | StyleValue[] | { [key: string]: StyleValue }; +export type StyleValue = StylePrimitive | StyleValue[] | { [key: string]: StylePrimitive }; From b5045f93418d471ab0ca407cb0834179bf6c4fcb Mon Sep 17 00:00:00 2001 From: Mathias Picker <48158184+MathiasWP@users.noreply.github.com> Date: Wed, 6 May 2026 10:46:24 +0200 Subject: [PATCH 09/10] chore: drop redundant comment in to_style --- packages/svelte/src/internal/shared/attributes.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/svelte/src/internal/shared/attributes.js b/packages/svelte/src/internal/shared/attributes.js index f2602055a1..6f3b74e7a8 100644 --- a/packages/svelte/src/internal/shared/attributes.js +++ b/packages/svelte/src/internal/shared/attributes.js @@ -158,9 +158,6 @@ function to_css_name(name) { * @returns {string | null} */ export function to_style(value, styles) { - // `class` accepts strings, objects and arrays via clsx; mirror that for `style` - // by normalising non-string values into a CSS declaration string upfront so the - // existing parser (which expects a string) handles directive merging unchanged. if (value != null && typeof value !== 'string') { value = style_value_to_string(value); } From fc5a41a960867fd4c6f38f4e02acc07e11178e9f Mon Sep 17 00:00:00 2001 From: Mathias Picker <48158184+MathiasWP@users.noreply.github.com> Date: Thu, 7 May 2026 15:22:43 +0200 Subject: [PATCH 10/10] chore: tighten style-object test assertions Empty inputs (`[false, null]`, `{}`, etc.) now consistently drop the attribute, so the assertions that accommodated either `null` or `''` are tightened to expect `null` exactly. Stale commentary updated. --- .../runtime-runes/samples/style-object/_config.js | 11 +++++------ .../runtime-runes/samples/style-object/main.svelte | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/svelte/tests/runtime-runes/samples/style-object/_config.js b/packages/svelte/tests/runtime-runes/samples/style-object/_config.js index 19d4ecf8cb..b361fe7487 100644 --- a/packages/svelte/tests/runtime-runes/samples/style-object/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/style-object/_config.js @@ -33,12 +33,11 @@ export default test({ assert.equal(get('nested').style.padding, '4px'); assert.equal(get('nested').style.margin, '2px'); - // all entries falsy → attribute absent (or empty) - assert.notOk(get('all-falsy').getAttribute('style')); + // all entries falsy → attribute absent + assert.equal(get('all-falsy').getAttribute('style'), null); - // empty object → empty style attribute (parallels clsx({}) === '') - const empty_attr = get('empty-object').getAttribute('style'); - assert.ok(empty_attr === '' || empty_attr === null); + // empty object → attribute absent + assert.equal(get('empty-object').getAttribute('style'), null); // conditional inline object: dropped when the gate is false assert.equal(get('conditional').style.padding, '4px'); @@ -92,7 +91,7 @@ export default test({ // $derived gated by a condition: when falsy, no attribute should be emitted assert.notOk(get('derived-conditional').getAttribute('style')); - // $derived combined with style: directive — directive wins + // $derived combined with style: directive, directive wins assert.equal(get('derived-directive').style.color, 'blue'); assert.equal(get('derived-directive').style.padding, '2px'); diff --git a/packages/svelte/tests/runtime-runes/samples/style-object/main.svelte b/packages/svelte/tests/runtime-runes/samples/style-object/main.svelte index 79c3d98b28..e07cb63e18 100644 --- a/packages/svelte/tests/runtime-runes/samples/style-object/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/style-object/main.svelte @@ -33,7 +33,7 @@
- +
@@ -70,7 +70,7 @@
- +