| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
`craft-chip` decided whether to render its prefix and suffix slots with one-shot `querySelector()` calls during `render()`, so anything slotted in after the chip mounted never appeared — most visibly the action menu `Craft.addActionsToChip()` injects into `[slot="suffix"]` once it has the element's actions. A `MutationObserver` on the light DOM now bumps a `@state`, so those checks run again. Deliberately not `slotchange`: an unrendered `<slot>` can't report a change, which is the bug. The observer watches the `slot` attribute as well as childList and subtree, since content moves between slots by having that attribute set rather than by being added or removed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`addActionsToChip()` builds a jQuery `Garnish.DisclosureMenu` from scratch when a chip has no recognized action container, and did so silently — a surface stuck on the deprecated shape looks fine until someone compares it against a `craft-action-menu`. Name the chip and point at the `<div slot="suffix">` that gets it the modern menu instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`ElementSelectControl.vue` renders the chips itself, but their Replace and Remove actions still arrived the legacy way: `addElements()` handed every chip to `Craft.addActionsToChip()`, which injected a menu into `[slot="suffix"]` after Vue had rendered — so the control's own markup and a jQuery-built menu were both writing into the same slot. The chip's action menu is now part of the component's template, and `showActionMenu: false` turns the injection off. `_includes/forms/elementSelect.twig` is unchanged and still gets the injected menu; `settings.showActionMenu` previously only reached the `app/render-elements` payload, so it now gates the client side too and the chips fetched after a selection stay menu-less until Vue re-renders them. The two behaviors the menu items need come out of `defineElementActions()` into public methods, `showReplaceModal()` and `removeElementOrSelection()`, so the Twig-injected menu and the Vue one run the same code — including Remove's long-standing habit of taking the whole multi-selection when the chip is part of it. Vue reaches them through passthroughs on `<craft-element-select-input>` that resolve the chip by `data-id`, because `ControllerElement.instance` is protected. Naming had to dodge two collisions on the way: the controller's `replaceElement()` is the server-render swap (`elementId`, `replacementId`), and a bare `remove()` on the custom element shadows `Element.remove()`, which vue-tsc rejects for a `CustomElementConstructor`. Replace is gated on an element type as well as `editable`, matching `defineElementActions()`; move forward/backward are left out because the control isn't sortable. One `FormRenderer` assertion now reads the chip's own text nodes rather than `textContent`, since the suffix menu's item labels count towards the latter. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
📚 Storybook previews@craftcms/ui — open Storybook No changed components detected in this Storybook. resources/js — open Storybook No changed components detected in this Storybook. |
Sorry, something went wrong.
…-chip-actions # Conflicts: # resources/js/modules/forms/ElementSelectControl.vue
|
This PR had conflicts with 6.x. Claude attempted an automatic resolution and pushed a merge commit. Please review the merge commit carefully before approving/merging. Claude's response
|
Sorry, something went wrong.
…lect-chip-actions
| Back | FazBrowse Home | New Git URL |
Description
Chips in the Inertia element editor’s element-select control were getting their action menu from Craft.addActionsToChip(). Finding no action container in the hand-rolled Vue chip, it fell all the way back to building a legacy jQuery disclosure menu and appending it to the chip’s body slot. ElementSelectControl.vue now renders craft-action-menu in the chip’s suffix slot from its own props — Replace gated on editable and the control’s element type, Remove on editable.
The two behaviors moved to public methods on BaseElementSelectInput (showReplaceModal() and removeElementOrSelection()), so the Vue menu and the menu the Twig stack still injects share one implementation. settings.showActionMenu now also gates the client-side injection in addElements(), not just the app/render-elements payload; without that, both menus would render into the same chip.
Replace also completes now, which it never did in this control. onModalSelect() dropped the chip being replaced before awaiting app/render-elements, and since ElementSelectControl.vue keys <craft-element-select-input> on its value, that intermediate one-element-short value tore the custom element down mid-flight — the rest of the method, including the selectElements() that inserts the replacement, then wrote into a detached DOM. The removal now happens once the replacement markup is in hand and ahead of any further await, so hosts observe a single combined change and re-render once with the replacement already in place; it still lands before the limit math, which needs the outgoing chip’s slot freed. addElements() additionally guards elementSelect with ?. to match elementSort — selectStructuredElements() still awaits after the chip is dropped, so a host that destroys the controller in that window would otherwise throw.
Two supporting fixes: