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

Make Trix compatible with morphing #1227

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Make Trix compatible with morphing #1227

wants to merge 2 commits into from

Conversation

jorgemanrubia
Copy link
Member

@jorgemanrubia jorgemanrubia commented Mar 3, 2025

Morphing the trix editor will leave it in an unusuable state because morphing will replace the bootstrapping elements without triggering the connection logic.

The solution is based on adding an attribute to flag the editor as initialized and detect when that attribute is modified.

See hotwired/turbo-rails#533 (comment)

Pending:

  • Tests

@jorgemanrubia
Copy link
Member Author

jorgemanrubia commented Mar 3, 2025

@seanpdoyle I would love your eyes on the approach 🙏

@jorgemanrubia jorgemanrubia marked this pull request as draft March 3, 2025 16:48
Comment on lines +512 to +513
this.disconnectedCallback()
this.connectedCallback()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this approach work with an existing <trix-toolbar> element? What about a <trix-editor> element with a [toolbar] attribute that references another element elsewhere in the page? Are the toolbars re-initialized as expected without attaching a duplicate?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good points, I'll see how to make these cases work. You are right that it will lose bootstrapped toolbars. I'll make sure it works well with both scenarios (existing toolbar and bootstrapped).

Copy link
Member Author

Choose a reason for hiding this comment

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

I added some logic to (1) flag internal (bootstrapped) trix toolbars and (2) remove those when reconnecting. This works well in my test.s

@seanpdoyle
Copy link
Collaborator

I'd opened hotwired/turbo-rails#688 on the turbo-rails side to explore a different path toward support. I don't love it, and am skeptical that it's a complete solution. Having said that, sharing it here provides some additional context to the breadth of the problem.

@jorgemanrubia jorgemanrubia force-pushed the morphing branch 7 times, most recently from 989bf70 to 6ffd337 Compare March 5, 2025 14:31
@jorgemanrubia jorgemanrubia marked this pull request as ready for review March 5, 2025 14:34
@jorgemanrubia
Copy link
Member Author

I'd opened hotwired/turbo-rails#688 on the turbo-rails side to explore a different path toward support. I don't love it, and am skeptical that it's a complete solution. Having said that, sharing it here provides some additional context to the breadth of the problem.

Thanks for the exploration @seanpdoyle. I prefer trying to fix this as the Trix level and keep the turbo Rails gem ignorant about this, as much as possible.

@jorgemanrubia jorgemanrubia force-pushed the morphing branch 7 times, most recently from 6c6b54d to 98b4d0c Compare March 6, 2025 16:16
@@ -410,6 +412,7 @@ export default class TrixEditorElement extends HTMLElement {
} else if (this.parentNode) {
const toolbarId = `trix-toolbar-${this.trixId}`
this.setAttribute("toolbar", toolbarId)
this.toggleAttribute("internal-toolbar", true)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This line toggles the [internal-toolbar] attribute on the the <trix-editor> (since this references that element).

However, the removeInternalToolbar() function defined below checks this.toolbarElement (the <trix-toolbar> if the <trix-editor> element is using an "internal" toolbar).

Should this line set the attribute on the toolbar, or should the check be switched from this.toolbarElement to this?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Furthermore, is it important that the attribute be set? Could this same kind of internal state tracking be achieved by a JavaScript object property that isn't represented in the DOM?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ugh I think I messed that up when switching it to use toogleAttribute. I'll also make sure the tests catch this. Thanks 👍

Copy link
Member Author

@jorgemanrubia jorgemanrubia Mar 7, 2025

Choose a reason for hiding this comment

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

I fixed and used an internal attribute to grab the internal toolbar. That's better indeed. Also added another test for the case external toolbars.

@jorgemanrubia jorgemanrubia force-pushed the morphing branch 4 times, most recently from beb61e6 to 5241203 Compare March 7, 2025 14:14
@@ -348,6 +348,8 @@ class LegacyDelegate {
export default class TrixEditorElement extends HTMLElement {
static formAssociated = "ElementInternals" in window

static observedAttributes = [ "initialized" ]
Copy link
Collaborator

@seanpdoyle seanpdoyle Mar 7, 2025

Choose a reason for hiding this comment

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

While I think the naming of this attribute is ultimately an arbitrary implementation detail, I wonder if there are naming conventions that already exist that it could draw inspiration from.

For example, the <turbo-cable-stream-source> element that turbo-rails provides toggles an attribute named "connected" which mirrors the connectedCallback() hook and the Node.isConnected property.

Copy link
Member Author

@jorgemanrubia jorgemanrubia Mar 7, 2025

Choose a reason for hiding this comment

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

I like that. I renamed it to connected. It will also remove the attribute when disconnected. I also added a check to ensure the element is connected to the DOM before resetting the state when the attribute is removed.

Morphing the trix editor will leave it in an unusuable state because
morphing will replace the bootstrapping elements without triggering
the connection logic.

The solution is based on adding an attribute to flag the editor as
initialized and detect when that attribute is modified.

See hotwired/turbo-rails#533 (comment)
@jorgemanrubia jorgemanrubia force-pushed the morphing branch 11 times, most recently from 325a397 to 952690d Compare March 8, 2025 06:43
I have tried several things with no luck. Will fix separately.
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.

3 participants