Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate with ElementInternals #1188

Merged
merged 2 commits into from
Oct 1, 2024

Conversation

seanpdoyle
Copy link
Contributor

@seanpdoyle seanpdoyle commented Sep 28, 2024

Related to #1143
Closes #1023

Integrate with <form> elements directly through built-in support for ElementInternals.

According to the Form-associated custom elements section of More capable form controls, various behaviors that the <trix-editor> element was recreating are provided out of the box.

For example, the <label> element support can be achieved through ElementInternals.labels. Similarly, a formResetCallback() will fire whenever the associated <form> element resets.

For now, keep the changes minimal. Future changes will handle integrating with more parts of ElementInternals.

TODO after merging:

Closes [basecamp#1023][]

Integrate with `<form>` elements directly through built-in support for
[ElementInternals][].

According to the [Form-associated custom elements][] section of [More
capable form controls][], various behaviors that the `<trix-editor>`
element was recreating are provided out of the box.

For example, the `<label>` element support can be achieved through
[ElementInternals.labels][]. Similarly, a `formResetCallback()` will
fire whenever the associated `<form>` element resets.

For now, keep the changes minimal. Future changes will handle
integrating with more parts of `ElementInternals`.

TODO after merging:
---

- [ ] Integrate with [ElementInternals.willValidate](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/willValidate), [ElementInternals.validity](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/validity), [ElementInternals.validationMessage](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/validationMessage)
- [ ] [Form callbacks](https://web.dev/articles/more-capable-form-controls#lifecycle_callbacks) like `void formDisabledCallback(disabled)` to support `[disabled]`
- [ ] [Instance properties included from ARIA](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals#instance_properties_included_from_aria)

[basecamp#1023]: basecamp#1023
[ElementInternals]: https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals
[Form-associated custom elements]: https://web.dev/articles/more-capable-form-controls#form-associated_custom_elements
[More capable form controls]: https://web.dev/articles/more-capable-form-controls
[ElementInternals.setFormValue]: https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setFormValue
[ElementInternals.labels]: https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/labels
@seanpdoyle
Copy link
Contributor Author

@jorgemanrubia @brunoprietog are either of you able to review this?

Copy link
Member

@jorgemanrubia jorgemanrubia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a great change @seanpdoyle

@@ -238,6 +233,18 @@ export default class TrixEditorElement extends HTMLElement {
this.editor?.loadHTML(this.defaultValue)
}

get disabled() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "disabled" bit is separated from the "element internals" change, right? I like both, but are they related?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The integration with ElementInternals provides access to the formDisabledCallback(disabled) lifecycle hook. Through that integration the element is given an opportunity to disable or re-enable its associated <input>. The [disabled] attribute is a common attribute among form controls, and provides the server an opportunity to render the element with an initially disabled state. However, the [disabled] attribute is only one aspect of disabling an element. If it's rendered within a <fieldset disabled>, the formDisabledCallback(disabled) will fire (and the associated <input> will be disabled anyway if its a child of the <fieldset> whether ElementInternals is integrated or not). There is also a :disabled CSS pseudo-selector that incorporates both [disabled] on the element itself and :disabled of any ancestor <fieldset> element.

The .disabled property itself is an enhancement that's separate from the bare necessities.

I've included it here because applications that want to introspect whether or not the element is disabled are unlikely to get it right when incorporating [disabled] on the element, :disabled on its <fieldset> ancestors (or their HTMLFieldSetElement.disabled property).

Since the <input> element is built-in, it already accounts for all these permutations. The current formDisabledCallback(disabled) implementation already manages the HTMLInputElement.disabled property, so the <input> felt like a good delegate for the time being. If the <trix-editor> is ever changed to managed its own value in a way that makes the <input> no longer necessary, this property could be changed to handle the rest of the logic.

this.toggleAttribute("disabled")
}

get type() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this just for testing purposes? Could you replace with just instanceof in tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't solely for testing. I've added the property because it's mentioned in the Defining a form-associated custom element section of the More capable form controls article.

Having said that, it's implemented using Element.localName (and not hard-coded like I've done here). It also doesn't seem to be mentioned by the MDN documentation for ElementInternals, so it isn't clear how necessary it is to start.

Copy link
Member

@jorgemanrubia jorgemanrubia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @seanpdoyle

@jorgemanrubia jorgemanrubia merged commit 2f8c59d into basecamp:main Oct 1, 2024
1 check passed
@seanpdoyle seanpdoyle deleted the editor-element-internals branch October 1, 2024 11:32
@seanpdoyle
Copy link
Contributor Author

I've opened #1190 to add support for [required] and setCustomValidity(message).

@jorgemanrubia
Copy link
Member

@seanpdoyle I'm noticing that this change will make Trix require Safari 16.4+ because of attachInternals. That's a version of March of 2023. Safari users upgrade browsers much slower than Chrome ones and we still have a decent base of users using Safari 14,15 in Basecamp. In HEY, where we use attachInternals in some components, we upgraded the minimum version to 17, but with Basecamp we need to move more carefully. I'm sorry but I'll have to revert this 🙏.

I'd be happy to consider a version that uses attachInternals but that it doesn't break if the browser does not support it. I think this was a great change, as well as the constraints one based on this one.

@seanpdoyle
Copy link
Contributor Author

Originally, I had opened #1132 and #1128 (depends on #1132) to add conditional support.

#1128 was more ambitious, and replaced the <input type="hidden"> with directly reading from the <trix-editor> element's content.

I'm dissatisfied with all of the machinery involved in conditionally running the appropriate code in CI depending on the browser support, but if that's what is necessary to ship these features, we can take that approach.

Since #1188 is viable, I'll incorporate those changes into a new PR that progressively enhances toward ElementInternals based on a Trix.config value that will default to whether or not the browser supports `ElementInternals.

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.

Does Trix plan to support HTMLElement.attachInternals?
2 participants