Skip to content

fix: align @attr boolean mode with native HTML boolean attribute semantics#7514

Open
janechu wants to merge 2 commits into
releases/fast-element-v3from
users/janechu/remove-false-string-as-false-boolean-converter
Open

fix: align @attr boolean mode with native HTML boolean attribute semantics#7514
janechu wants to merge 2 commits into
releases/fast-element-v3from
users/janechu/remove-false-string-as-false-boolean-converter

Conversation

@janechu
Copy link
Copy Markdown
Collaborator

@janechu janechu commented May 12, 2026

Pull Request

📖 Description

Aligns @attr({ mode: "boolean" }) and booleanConverter with native HTML boolean attribute semantics (e.g., disabled, required):

  • Attribute → property is presence-based: setAttribute(name, anyString) (including "" and "false") sets the property to true; only removeAttribute(name) makes it false.
  • Property → attribute uses Boolean() coercion: any truthy value adds the attribute (with value ""); any falsy value removes it.

The headline behavior change is that <my-element my-bool="false"> now resolves to element.myBool === true, matching <input disabled="false"> still being disabled.

Changes

  • booleanConverter.fromView!!value (standard Boolean() coercion).
  • booleanConverter.toViewvalue ? "" : null (HTML-standard boolean-attribute output; previously "true"/"false").
  • AttributeDefinition.onAttributeChangedCallback special-cases mode: "boolean" to call setValue(element, value !== null), ensuring the attribute → property path is presence-based even when the converter would otherwise coerce "" to false.

This is a breaking change included in the 3.x release.

🎫 Issues

Closes #7511

👩‍💻 Reviewer Notes

  • The mode: "boolean" reflection path no longer routes through booleanConverter.toView() / booleanConverter.fromView(). These methods still apply to property assignment (el.bool = X runs fromView), explicit calls (booleanConverter.fromView(x)), and booleanConverter paired with mode: "reflect" (which calls toView).
  • Custom converters used with mode: "boolean" will receive a boolean (from value !== null) on the attribute → property path rather than the raw attribute string, since boolean mode now means "presence-based" regardless of the converter.
  • Migration guidance is documented in both packages/fast-element/MIGRATION.md and sites/website/src/docs/3.x/migration-guide.md.

📑 Test Plan

Added side-by-side parity tests in packages/fast-element/src/components/attributes.pw.spec.ts that exercise both a FAST mode: "boolean" custom element and a native <button disabled> for every false/true case, asserting they report identical state in both reflection directions.

  • 96/96 attribute parity tests pass across chromium, firefox, and webkit.
  • 176/176 broader @microsoft/fast-element chromium suite passes (no regressions).
  • npm run biome:check, npm run checkchange pass.

✅ Checklist

General

  • I have included a change request file using $ npm run change
  • I have added tests for my changes.
  • I have tested my changes.
  • I have updated the project documentation to reflect my changes.
  • I have read the CONTRIBUTING documentation and followed the standards for this project.

@janechu janechu force-pushed the users/janechu/remove-false-string-as-false-boolean-converter branch from 06780cc to b42ce21 Compare May 12, 2026 21:51
@janechu janechu changed the title Users/janechu/remove false string as false boolean converter fix: align @attr boolean mode with native HTML boolean attribute semantics May 12, 2026
@janechu janechu force-pushed the users/janechu/remove-false-string-as-false-boolean-converter branch from b42ce21 to 2c30ccf Compare May 12, 2026 22:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant