Repository navigation
[6.x] Move the control panel JavaScript to modules and off jQuery and Garnish - #20378
Conversation
CraftCopyAttribute, CraftGlobalSidebar, and CraftTooltip were never imported into the legacy cp bundle; @craftcms/ui and <cp-global-sidebar> replaced them. Craft.ImageUpload's only consumer was the rebrand script, whose asset bundle no longer registered it, so both go along with the generalsettings webpack package. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each module's index.ts now only defines its element and exports. Globals core still calls move to globals.ts, which index.ts imports. Globals only plugins call move to compat.ts, which only the yii2-adapter's cp-compat.ts imports. Moving a global to the adapter is now a one-line move between the two files. Adapter-only from this commit: Craft.AssetImageEditor, Craft.SortableCheckboxSelect, Craft.GroupedEntryTypeManager, Craft.RecoveryCodesSetup and Craft.TagSelectInput, which core no longer calls. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Uploads, highlighter, AuthChallengeForm, createElementSelectorModal and the element selector controller registry are now exports of the @craftcms/cp import-map module rather than Craft.* globals, so control panel plugin code imports them. The Yii2 adapter keeps Craft.createElementSelectorModal and Craft.highlighter for Craft 5 plugins. Pages outside the control panel still get Craft.Uploads from the standalone uploads entry, since they have no import map. SlideoutPanel no longer assumes window.Craft exists; it was relying on a module that happened to create it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Craft.commandPalette is new in 6.0, so it moves to a CommandPalette export of the @craftcms/cp import-map module instead of becoming a global the adapter has to carry. Craft.charts dates from Craft 5 and core's legacy New Users widget still calls it, so it gets the globals.ts split. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The class now lives in resources/js/common/utils/promise-queue.ts on @craftcms/garnish Base, without jQuery. The legacy bundle imports it and still assigns Craft.Queue and Craft.queue where Queue.js did, since Craft.cp uses the queue while that bundle evaluates. A failed job no longer leaves an unhandled rejection behind. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Craft.AssetsFieldSettings and Craft.ElementFieldSettings only serve the legacy relation field settings templates, which only the adapter's LegacyRelationFieldSettings renders; core builds those settings with settingsUi(). They now ship unchanged in the cpcompat bundle, loaded CP-wide by CpCompatAsset. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The trim/startsWith/remove* family, escapeRegex, escapeChars, upper/lowercaseFirst, uuid, randomString, formatInputId, namespaceInputName and namespaceId now live in resources/js/common/craft/. Craft.js assigns them, so Craft.trim() and the rest keep working for plugins, and the modern modules that reached through the global import them instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
findDeltaData, findModifiedDeltaNames, groupParams and the private _groupParamsByDeltaNames now live in resources/js/common/craft/delta.ts, with a jQuery-compatible param() serializer in params.ts that's tested against $.param itself. Craft.js assigns them for plugins, and the CP modal, CP screen slideout and inline editing import them directly. The inline editing test now runs the real delta logic instead of a stub that returned the expected result. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
getUrl, getCpUrl, getSiteUrl and getActionUrl now live in resources/js/common/craft/url.ts, read their base URLs from the CP config at call time, and encode params with the jQuery-compatible param(). The script-name and path-param branches are gone: Craft 6 never sends pathParam or scriptName, so they couldn't change the result. Output was checked against the legacy implementation. Craft.js assigns them for plugins, and the modern modules that called Craft.getCpUrl()/getActionUrl() import them. Their tests now set the base URLs rather than stubbing the helpers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Asset fields drew their upload progress with the legacy Craft.ProgressBar, whose stylesheet Craft 6 never loads, so the bar rendered unstyled and the shade over the field never appeared. They now use the <craft-progress-bar> element, which exposes a labelled progressbar to assistive tech, with a small stylesheet for the overlay. Progress is still announced every few seconds while an upload runs. Craft.ProgressBar stays in the legacy bundle for the legacy asset index. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
element-selector-modals/body returned the legacy ElementIndexHtml markup alongside the index props, but every modal now renders the Vue index from props, so the markup was rendered on each open and thrown away. The response is now just props, and the request params and status narrowing that only fed the markup are gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The elementIndex() Twig function and ElementIndexHtml rendered the legacy jQuery element index, and nothing in core used them. They now live in the adapter, next to craft\helpers\Cp::elementIndexHtml() and the nested element manager that call them. _layouts/elementindex only drew the legacy index when the shell wasn't collecting the screen, which nothing triggers any more, so the layout now always declares the Vue index. Its empty initJs block stays for child templates that extend it. craft.cp.screenCollecting() lost its only caller and is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Craft.BaseElementIndex, its views, the per-type indexes, the structure view and ProgressBar now ship in the adapter's cpcompat bundle as one element-index entry, along with Craft.createElementIndex() and Craft.registerElementIndexClass(). Core renders every element index with the Vue index, so none of it was used without the adapter. The legacy cp bundle drops from 406 KB to 265 KB. The globals only those classes used (ElementTableSorter, IntervalManager, PromptHandler and openCustomizeSourcesModal) move to compat.ts, and the Vue index's Customize Sources action imports the modal directly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only the legacy dashboard, which only the adapter loads, and plugins use the legacy admin table, so it now ships in the cpcompat bundle. The editable table imports DataTableSorter instead of reaching for Craft.DataTableSorter, leaving that global to the adapter as well. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Craft.t() assigned 'app' to its category argument instead of passing the caller's category through, so plugin translations were never found. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 151 Craft.t('app', …) calls in resources/js and the adapter's
nested element manager now use @craftcms/ui's t(). Each control panel
entry first seeds its translations from window.Craft, because custom
elements already on the page upgrade, and translate their labels, while
their modules are still loading, before the CP bootstrap runs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Core modules called Craft.sendActionRequest(), which only exists because the legacy bundle defines it. They now use actionClient, which sends the same registered-asset headers and resolves action paths, root-relative URLs and absolute URLs the same way. The CP modal and CP screen slideout still accept plugin-supplied axios options, so their screen loads go through sendLegacyRequest() with actionClient, and their form submissions post to the CP URL as before. Craft.sendActionRequest() stays for plugins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Core modules now import appendHeadHtml() and appendBodyHtml() from @craftcms/ui instead of calling the Craft.* versions, so head HTML they load lands above the control panel stylesheet like the Vue screens' does. The CP modal, which didn't wait between the two, now appends the body HTML once the head's scripts have loaded. Craft.appendHeadHtml() and appendBodyHtml() keep their queue and still append to the end of <head>, but use the same implementation. Their duplicate check reads the live DOM instead of a list captured on first use, so they no longer re-run a script something else added since. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
addActionsToChip, setElementAttributes, escapeHtml and hasMousePointerEvents now live in resources/js/common/craft/, without jQuery except for the disclosure menu fallback that old chip markup still needs. Core modules import them, and Craft.js assigns them so the Craft.* names keep working for plugins. setElementAttributes keeps the legacy behavior plugins may depend on: it accepts a selector or a collection, applies to every element in it, and adds px to bare numbers in a style object as jQuery's css() did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Core modules now read text direction, the page trigger, element type names and handle casing from ConfigService, and import cookie, focus, broadcast and elevated-session helpers directly. The Craft.* members stay in place for plugins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@craftcms/ui now exports a single create(tag, props, ...children) that types props from HTMLElementTagNameMap, so every component gets checked properties without a factory of its own. The per-component factories only translated the legacy Craft.ui config keys, so they move next to the Craft.ui patch in resources/js/modules/ui/legacy, which UI.js imports. createCopyTextPrompt opens a dialog rather than building a control, so it stays in @craftcms/ui as showCopyTextPrompt(). Core's button and copy prompt callers now use create() and showCopyTextPrompt(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The field error helpers (addErrorsToField, clearErrorsFromField, the error summary helpers and findTabAnchorForField) now live in common/craft/field-errors.ts without jQuery, and Craft.ui's methods call them. Core fetches icon SVGs through iconSvg(), which requests each name once, and builds the matrix default-columns select with create(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Core called Craft.cp.displayNotice(), displaySuccess(), displayError() and displayNotification() in 111 places. They now import showNotice(), showSuccess() and showError() from the messages module, which every message already went through for deduping. showMessage() returns the notification so callers can close it, and the functions are exported from @craftcms/cp for plugins. Craft.cp's methods are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Core's seven Craft.cp.runQueue() calls now call QueueService.getInstance().runQueue(), which Craft.cp.runQueue() already delegated to. Also drops test stubs for Craft.cp.display*() that nothing calls any more. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Core's Craft.cp.elementThumbLoader.load() calls use a shared loader from the element-thumb-loader module instead. Craft.cp.elementThumbLoader is unchanged for plugins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
modules/elements/clipboard owns copied elements: localStorage, the cross-tab broadcast, listeners and paste. Core and the @craftcms/cp exports call it directly; Craft.cp's clipboard methods delegate to it. The "copied" card is still the legacy ElementCopyNotification. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
common/announcer finds the live region when a message is announced: the top modal layer's, else the page's. This replaces CP.js's layer tracking. useAnnouncer() and Craft.cp.announce() both go through it, so Vue code inside a modal is heard and Craft.cp.announce() works on Inertia pages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lements Core's 18 Craft.initUiElements() calls now go through initLegacyUi(), which does nothing when the legacy bundle isn't loaded. A MutationObserver binds a FieldToggle to each .fieldtoggle as it's added, so inserted markup no longer needs the sweep for toggles. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
<craft-switch> updates aria-checked after its change event, so FieldToggle read the old state and showed a switch's targets when it was turned off. Now that every .fieldtoggle is bound, this affected switches on every page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Amp-Thread-ID: https://ampcode.com/threads/T-01a1a41f-35f1-75f6-a070-f628cc4e7276 Co-authored-by: Amp <amp@ampcode.com> # Conflicts: # resources/js/modules/auth/components/login/login-challenge.browser.test.ts
The deploy jobs restore build-assets' cache instead of installing, but `vp run` still checks the lockfile against the registry. Without the token that check fails for the Font Awesome packages. Amp-Thread-ID: https://ampcode.com/threads/T-01a1a41f-35f1-75f6-a070-f628cc4e7276 Co-authored-by: Amp <amp@ampcode.com>
There was a problem hiding this comment.
🟡 Changes recommended
The recovery-code action now returns an array while the Password screen still expects a URL string, causing an array-to-string error and leaving the download-confirmation contract inconsistent.
2 open issues
What changed in this PR
Consolidates the 6.x control-panel migration to TypeScript modules and custom elements, moves jQuery/Garnish compatibility into the Yii2 adapter, and exposes shared modules for plugins.
Changes:
- Separates core module exports from legacy compatibility globals and dependencies.
- Migrates templates, controls, notifications, and bootstrap hooks to shared helpers and native events.
- Updates plugin-facing exports, build configuration, assets, documentation, and regression tests.
This pull request requires changes.
The unresolved findings are:
- Critical · 1 vote: The recovery-code action descriptor breaks the Password screen’s existing view-model/client contract and needs coordinated download-confirmation handling.
- Moderate · 2 votes: Image-preview resizing still references the removed focal-point global, leaving the marker incorrectly positioned.
- Moderate · 1 vote: Authentication-method removal bypasses the CSRF-aware action client and can fail with HTTP 419.
- Moderate · 1 vote: Flashed broadcasts can fire before the asynchronously initialized relay exists, leaving other tabs stale.
- Nit · 2 votes: The published Factory documentation still imports removed builders and needs migration guidance.
- Nit · 1 vote: The copy-text prompt documentation still uses the removed factory export and old function name.
Project tests, builds, and interactive accessibility checks were not independently run during review.
| File | Description |
|---|---|
yii2-adapter/tests-laravel/Field/LegacyRelationFieldInputTest.php |
Expects custom-element relation inputs. |
yii2-adapter/src/Mixins/NestedElementManagerMixin.php |
Uses the adapter index renderer. |
yii2-adapter/src/Cp/Html/LegacyMenuHtml.php |
Preserves legacy menu rendering. |
yii2-adapter/resources/templates/_includes/forms/volume.twig |
Resolves volume URLs server-side. |
yii2-adapter/resources/templates/_includes/forms/customSelect.twig |
Guards legacy menu initialization. |
yii2-adapter/resources/templates/_components/fieldtypes/Assets/input.twig |
Delegates initialization to custom elements. |
yii2-adapter/resources/js/slide-picker-compat.browser.test.ts |
Loads relocated compatibility UI. |
yii2-adapter/resources/js/matrix/matrix-input.ts |
Uses the relocated button builder. |
yii2-adapter/resources/js/matrix/matrix-entry.ts |
Imports the CP URL helper. |
yii2-adapter/resources/js/element-select-input/index.ts |
Registers legacy input classes. |
yii2-adapter/resources/js/cp-compat.ts |
Collects adapter compatibility registrations. |
yii2-adapter/legacy/web/twig/Extension.php |
Exposes adapter element-index rendering. |
yii2-adapter/legacy/web/assets/focalpoint/FocalPointAsset.php |
Makes the obsolete bundle inert. |
yii2-adapter/legacy/web/assets/cp/CpAsset.php |
Loads adapter Craft JavaScript. |
yii2-adapter/legacy/base/WidgetTrait.php |
References the relocated widget image. |
vite.config.js |
Adds the shared Garnish entry. |
tests/Unit/Twig/Templates/CheckboxSelectTemplateTest.php |
Updates checkbox-select markup expectations. |
tests/Unit/Cp/Components/CheckboxSelectTest.php |
Drops the legacy host-class assertion. |
tests/Unit/Cp/Components/ActionMenuTest.php |
Checks elevated-session action metadata. |
tests/Feature/Image/RasterTest.php |
Uses a dedicated font fixture. |
tests/Feature/Http/Responses/CpScreenSlideoutTest.php |
Updates the initial asset expectation. |
tests/Feature/Http/Controllers/PluginStore/InstallControllerTest.php |
Expects declarative updater initialization. |
tests/Feature/Http/Controllers/Elements/ElementSelectorModalControllerTest.php |
Expects props without legacy HTML. |
tests/Feature/Cp/PreviewHtmlTest.php |
Checks declarative preview controls. |
src/View/LegacyAssets/UpdaterAsset.php |
Stops loading legacy updater JavaScript. |
src/View/LegacyAssets/MoneyAsset.php |
Declares its Garnish dependency. |
src/View/LegacyAssets/InputmaskAsset.php |
Declares its jQuery dependency. |
src/View/LegacyAssets/GeneralSettingsAsset.php |
Removes obsolete commented registrations. |
src/View/LegacyAssets/FocalPointAsset.php |
Deletes the obsolete asset bundle. |
src/View/LegacyAssets/CpAsset.php |
Removes core legacy dependencies. |
src/Twig/Variables/Cp.php |
Removes the fragment-collection accessor. |
src/Http/ViewModels/ContentIndexViewModel.php |
Removes an outdated documentation reference. |
src/Http/Mixins/SessionMixin.php |
Dispatches native broadcast events. |
src/Http/Controllers/PluginsController.php |
Removes legacy plugin asset registration. |
src/Http/Controllers/Elements/EditElementController.php |
Removes the obsolete Inertia editor branch. |
src/Http/Controllers/BaseUpdaterController.php |
Supplies declarative updater state. |
src/FieldLayout/LayoutElements/Assets/AltField.php |
Removes the legacy textarea class. |
src/Field/Number.php |
Filters numeric input without jQuery. |
src/Element/ElementIndexState.php |
Documents adapter ownership of legacy indexes. |
src/Cp/Html/PreviewHtml.php |
Emits declarative preview controls. |
src/Cp/Cp.php |
Publishes the shared Garnish module. |
src/Cp/Components/CheckboxSelect.php |
Removes the legacy host class. |
src/Auth/Methods/RecoveryCodes.php |
Defines an elevated POST download descriptor. |
scripts/ensure-built.mjs |
Updates the legacy-build sentinel. |
resources/translations/en/app.php |
Adds the upload-progress label. |
resources/templates/users/_auth-methods.twig |
Uses modern action menus. |
resources/templates/assets/_previews/image.twig |
Declares focal-point initialization attributes. |
resources/templates/_special/updater.twig |
Embeds updater configuration. |
resources/templates/_special/setup-2fa.twig |
Replaces jQuery DOM operations. |
resources/templates/_layouts/cp.twig |
Guards adapter-only update checks. |
resources/templates/_layouts/components/crumbs.twig |
Passes the menu invoker explicitly. |
resources/templates/_layouts/components/alerts.twig |
Guards legacy alert loading. |
resources/templates/_layouts/base.twig |
Resolves relocated icon assets. |
resources/templates/_components/fieldtypes/PlainText/input.twig |
Removes the legacy text class. |
resources/templates/_components/auth/methods/TOTP/setup.twig |
Dispatches native message events. |
resources/js/uploads.ts |
Documents standalone upload usage. |
resources/js/pages/users/Passkeys.vue |
Uses module error reporting. |
resources/js/pages/assets/Index.vue |
Uses the configured pagination helper. |
resources/js/pages/assets/AssetUploadButton.test.ts |
Mocks the module queue dependency. |
resources/js/modules/uploader/uploader.ts |
Uses module error reporting. |
resources/js/modules/uploader/uploader.test.ts |
Removes legacy message stubs. |
resources/js/modules/uploader/upload-queue.ts |
Reports errors through the message module. |
resources/js/modules/uploader/upload-notification.ts |
Uses native notification controls. |
resources/js/modules/uploader/picker.test.ts |
Mocks module error reporting. |
resources/js/modules/uploader/index.ts |
Separates uploader global registration. |
resources/js/modules/uploader/globals.ts |
Registers uploader compatibility globals. |
resources/js/modules/uploader/asset-upload-queue.ts |
Calls queue and message modules. |
resources/js/modules/ui/useUiForm.ts |
Uses module error reporting. |
resources/js/modules/ui/useInertiaTable.ts |
Reads the configured pagination key. |
resources/js/modules/ui/UiModal.vue |
Uses module notice reporting. |
resources/js/modules/ui/UiModal.browser.test.ts |
Removes legacy message stubs. |
resources/js/modules/ui/README.md |
Documents adapter compatibility loading. |
resources/js/modules/ui/nested-elements/useNestedElementsQuery.ts |
Uses the pagination helper. |
resources/js/modules/ui/nested-elements/useNestedElementsQuery.test.ts |
Removes legacy pagination configuration. |
resources/js/modules/ui/nested-elements/NestedElements.test.ts |
Removes the legacy notice stub. |
resources/js/modules/ui/nested-elements/nested-elements.ts |
Uses configured element names. |
resources/js/modules/ui/nested-elements/nested-elements-control-host.ts |
Serializes forms without jQuery. |
resources/js/modules/ui/nested-elements/nested-elements-control-host.test.ts |
Simplifies compatibility stubs. |
resources/js/modules/ui/legacy/switch.ts |
Corrects the component type import. |
resources/js/modules/ui/legacy/slide-picker.ts |
Corrects the component type import. |
resources/js/modules/ui/legacy/input-password.ts |
Uses relocated builder imports. |
resources/js/modules/ui/legacy/input-color.ts |
Uses relocated builder imports. |
resources/js/modules/ui/legacy/index.ts |
Exports relocated legacy builders. |
resources/js/modules/ui/layout-component-settings-ui-host.ts |
Calls the shared action client. |
resources/js/modules/ui/ElementSitesControl.vue |
Uses module error reporting. |
resources/js/modules/ui/element-select/usePasteableElements.ts |
Uses clipboard and naming modules. |
resources/js/modules/ui/dashboard-widget-settings-ui-host.ts |
Calls the shared action client. |
resources/js/modules/ui/compat.test.ts |
Tests the explicit compatibility entry. |
resources/js/modules/tabs/index.ts |
Removes implicit global registration. |
resources/js/modules/tabs/compat.ts |
Registers adapter tab compatibility. |
resources/js/modules/sortable-checkbox-select/compat.ts |
Registers legacy sorting compatibility. |
resources/js/modules/slideout/globals.ts |
Registers the compatified slideout constructor. |
resources/js/modules/slideout/compat.ts |
Registers adapter slideout classes. |
resources/js/modules/queue/index.ts |
Separates queue global registration. |
resources/js/modules/queue/globals.ts |
Registers the queue compatibility global. |
resources/js/modules/prompt-handler/index.ts |
Removes implicit global registration. |
resources/js/modules/prompt-handler/compat.ts |
Registers adapter prompt compatibility. |
resources/js/modules/preview-file-modal/index.ts |
Separates preview global registration. |
resources/js/modules/preview-file-modal/globals.ts |
Registers preview compatibility. |
resources/js/modules/notifications/store.ts |
Uses module error reporting. |
resources/js/modules/notifications/store.test.ts |
Checks module error reporting. |
resources/js/modules/navigation/components/cp-queue-indicator.ts |
Imports the CP URL helper. |
resources/js/modules/navigation/components/cp-global-sidebar.ts |
Imports cookie helpers. |
resources/js/modules/messages/useMessages.ts |
Reuses shared message functions. |
resources/js/modules/link-field/link-field.ts |
Tracks controllers without jQuery. |
resources/js/modules/link-field/index.ts |
Separates link-field global registration. |
resources/js/modules/link-field/globals.ts |
Registers link-field compatibility globals. |
resources/js/modules/interval-manager/interval-manager.ts |
Clarifies compatibility ownership in comments. |
resources/js/modules/interval-manager/index.ts |
Removes implicit global registration. |
resources/js/modules/interval-manager/compat.ts |
Registers adapter interval compatibility. |
resources/js/modules/input-generators/index.ts |
Separates generator global registration. |
resources/js/modules/input-generators/handle-generator.ts |
Reads the shared configuration service. |
resources/js/modules/input-generators/globals.ts |
Registers generator compatibility globals. |
resources/js/modules/image-editor/index.ts |
Separates image-editor global registration. |
resources/js/modules/image-editor/globals.ts |
Registers the image-editor opener. |
resources/js/modules/image-editor/compat.ts |
Registers the legacy editor name. |
resources/js/modules/highlight/compat.ts |
Keeps adapter registration without an export. |
resources/js/modules/grouped-entry-type-manager/README.md |
Updates documented legacy dependencies. |
resources/js/modules/grouped-entry-type-manager/compat.ts |
Registers the legacy manager API. |
resources/js/modules/grid/index.ts |
Separates grid global registration. |
resources/js/modules/grid/grid.test.ts |
Checks native item management. |
resources/js/modules/grid/globals.ts |
Registers grid compatibility. |
resources/js/modules/form-observer/index.ts |
Separates observer global registration. |
resources/js/modules/form-observer/globals.ts |
Registers observer compatibility. |
resources/js/modules/focal-point/focal.scss |
Supplies focal-point marker styles. |
resources/js/modules/field-toggle/index.ts |
Separates toggle global registration. |
resources/js/modules/field-toggle/globals.ts |
Registers toggle compatibility. |
resources/js/modules/field-toggle/field-toggle.test.ts |
Checks immediate switch-state reading. |
resources/js/modules/field-layout-designer/README.md |
Updates documented legacy dependencies. |
resources/js/modules/field-layout-designer/LayoutComponentSettings.vue |
Calls the shared action client. |
resources/js/modules/field-layout-designer/index.ts |
Separates designer global registration. |
resources/js/modules/field-layout-designer/globals.ts |
Registers designer compatibility classes. |
resources/js/modules/field-layout-designer/field-layout-designer.ce.ts |
Calls the scoped legacy initializer. |
resources/js/modules/field-layout-designer/drags.test.ts |
Removes the jQuery test dependency. |
resources/js/modules/entry-mover/index.ts |
Separates mover global registration. |
resources/js/modules/entry-mover/globals.ts |
Registers entry-mover compatibility. |
resources/js/modules/elements/live-preview/useLivePreview.ts |
Removes obsolete global typings. |
resources/js/modules/elements/live-preview/PreviewLayout.vue |
Imports iframe-resizer directly. |
resources/js/modules/elements/index/save-inline-elements.ts |
Uses module error reporting. |
resources/js/modules/elements/index/element-actions.ts |
Uses module message reporting. |
resources/js/modules/elements/index/copy-elements.ts |
Calls the shared clipboard module. |
resources/js/modules/elements/index/composables/useElementIndexVisits.ts |
Uses configured pagination. |
resources/js/modules/elements/index/composables/useElementIndexSort.test.ts |
Removes legacy pagination configuration. |
resources/js/modules/elements/index/composables/useCustomizeSources.ts |
Imports the modal opener directly. |
resources/js/modules/elements/index/composables/useCustomizeSources.test.ts |
Mocks the imported modal opener. |
resources/js/modules/elements/index/components/ElementIndexPage.filters.test.ts |
Initializes pagination configuration explicitly. |
resources/js/modules/elements/index/components/ElementIndex.test.ts |
Removes legacy pagination configuration. |
resources/js/modules/elements/index/components/ElementBulkActionsBar.vue |
Uses module error reporting. |
resources/js/modules/elements/html-nested-owner.ts |
Isolates optional legacy editor lookup. |
resources/js/modules/elements/element-action-events.ts |
Dispatches server-rendered element actions. |
resources/js/modules/elements/composables/useBulkActionSelection.ts |
Updates clipboard documentation. |
resources/js/modules/element-thumb-loader/index.ts |
Re-exports relocated thumbnail helpers. |
resources/js/modules/element-thumb-loader/element-thumb-loader.test.ts |
Imports relocated compatibility CP code. |
resources/js/modules/element-table-sorter/compat.ts |
Keeps adapter registration without an export. |
resources/js/modules/element-selector-modal/volume-folder-selector-modal.test.ts |
Uses props-only response fixtures. |
resources/js/modules/element-selector-modal/useModalElementIndex.test.ts |
Removes legacy pagination configuration. |
resources/js/modules/element-selector-modal/useElementSelectorController.test.ts |
Uses a props-only response fixture. |
resources/js/modules/element-selector-modal/index.test.ts |
Checks adapter-only factory registration. |
resources/js/modules/element-selector-modal/globals.ts |
Registers folder-selector compatibility. |
resources/js/modules/element-selector-modal/ElementSelectorModal.test.ts |
Uses props-only response fixtures. |
resources/js/modules/element-selector-modal/compat.ts |
Registers the adapter modal factory. |
resources/js/modules/element-select-input/README.md |
Documents core/adapter input separation. |
resources/js/modules/element-select-input/index.ts |
Keeps core custom-element registration. |
resources/js/modules/element-deletion-manager/index.ts |
Separates deletion global registration. |
resources/js/modules/element-deletion-manager/globals.ts |
Registers deletion compatibility. |
resources/js/modules/element-action-trigger/compat.ts |
Keeps adapter registration without an export. |
resources/js/modules/editable-table/index.ts |
Removes implicit compatibility registration. |
resources/js/modules/editable-table/compat.ts |
Registers compatified adapter table classes. |
resources/js/modules/data-table-sorter/index.ts |
Removes the obsolete global entry. |
resources/js/modules/data-table-sorter/data-table-sorter.ts |
Clarifies module consumers in comments. |
resources/js/modules/data-table-sorter/compat.ts |
Registers adapter sorter compatibility. |
resources/js/modules/dashboard/useDashboard.ts |
Refreshes the grid through native elements. |
resources/js/modules/dashboard/NewUsers.vue |
Passes a native chart container. |
resources/js/modules/customize-sources/index.ts |
Removes implicit global registration. |
resources/js/modules/customize-sources/compat.ts |
Registers the adapter modal opener. |
resources/js/modules/cp-modal/index.ts |
Separates modal global registration. |
resources/js/modules/cp-modal/globals.ts |
Registers modal compatibility. |
resources/js/modules/component-select/README.md |
Updates documented legacy dependencies. |
resources/js/modules/command-palette/run.ts |
Uses module message reporting. |
resources/js/modules/command-palette/registry.ts |
Updates the API example. |
resources/js/modules/command-palette/index.ts |
Removes the command-palette global API. |
resources/js/modules/command-palette/components/UiFormView.test.ts |
Removes legacy message stubs. |
resources/js/modules/command-palette/components/CommandPalette.vue |
Uses module message reporting. |
resources/js/modules/chart/index.ts |
Separates chart global registration. |
resources/js/modules/chart/globals.ts |
Registers chart compatibility APIs. |
resources/js/modules/auth/elevated-session/index.test.ts |
Checks the action elevation event bridge. |
resources/js/modules/auth/components/auth-challenge-form.ts |
Documents shared-module subclassing. |
resources/js/modules/auth-method-setup/index.ts |
Separates setup global registration. |
resources/js/modules/auth-method-setup/globals.ts |
Registers authentication setup globals. |
resources/js/modules/auth-method-setup/compat.ts |
Registers recovery-code compatibility. |
resources/js/modules/assets/replaceAssetFile.ts |
Uses broadcast and message modules. |
resources/js/modules/assets/composables/useAssetIndexItemBehavior.ts |
Uses configured pagination. |
resources/js/modules/assets/composables/useAssetIndexItemBehavior.test.ts |
Removes legacy pagination configuration. |
resources/js/modules/assets/composables/useAssetFolderActions.test.ts |
Removes legacy message stubs. |
resources/js/modules/asset-select-input/index.ts |
Removes core input global registration. |
resources/js/modules/asset-select-input/asset-select-input.css |
Styles the upload progress overlay. |
resources/js/modules/asset-mover/index.ts |
Separates mover global registration. |
resources/js/modules/asset-mover/globals.ts |
Registers asset-mover compatibility. |
resources/js/modules/ai/skills/AiSkills.vue |
Uses module error reporting. |
resources/js/modules/ai/assistant/AssistantConversationMenu.vue |
Uses module error reporting. |
resources/js/modules/admin-table/legacy-admin-table.test.ts |
Removes the unused request stub. |
resources/js/garnish.ts |
Publishes shared Garnish exports. |
resources/js/common/web-components/ControllerElement.ts |
Preserves controllers during DOM moves. |
resources/js/common/utils/dom.ts |
Adds native content-box measurement. |
resources/js/common/types/iframe-resizer.d.ts |
Declares the imported resizer API. |
resources/js/common/table/useServerSort.ts |
Uses configured pagination. |
resources/js/common/table/useServerPagination.ts |
Uses configured pagination. |
resources/js/common/table/server-query.test.ts |
Removes legacy pagination configuration. |
resources/js/common/table/craftTable.test.ts |
Removes legacy pagination configuration. |
resources/js/common/slideouts/SlideoutPanel.vue |
Guards optional Craft configuration. |
resources/js/common/slideouts/index.ts |
Leaves editor globals to the adapter. |
resources/js/common/craft/pointer.ts |
Adds native pointer detection. |
resources/js/common/craft/namespace.ts |
Adds input namespacing helpers. |
resources/js/common/craft/legacy-ui.ts |
Isolates optional legacy initialization. |
resources/js/common/craft/icon-svg.ts |
Fetches and caches icon SVGs. |
resources/js/common/craft/element-types.ts |
Reads configured element names. |
resources/js/common/craft/direction.ts |
Adds text-direction helpers. |
resources/js/common/composables/useAsyncIcon.ts |
Uses the module icon loader. |
resources/js/common/components/HtmlFragmentRenderer.vue |
Uses the scoped legacy initializer. |
resources/js/bootstrap/seed-translations.ts |
Seeds translations before component upgrades. |
resources/js/bootstrap/seed-translations.test.ts |
Checks early translation availability. |
resources/js/bootstrap/cp.ts |
Initializes migrated core services. |
resources/css/fld.css |
Updates stylesheet provenance comments. |
packages/craftcms-ui/vitest.config.ts |
Removes the factory test project. |
packages/craftcms-ui/src/utilities/copy-text-prompt.ts |
Renames the prompt-opening utility. |
packages/craftcms-ui/src/index.ts |
Exports the copy-text prompt utility. |
packages/craftcms-ui/src/factory/index.ts |
Removes the public factory entry. |
packages/craftcms-ui/src/core/element-selector/volume-folder-selector-controller.test.ts |
Uses a props-only response fixture. |
packages/craftcms-ui/src/core/element-selector/types.ts |
Removes the legacy response HTML contract. |
packages/craftcms-ui/src/core/element-selector/element-selector-controller.test.ts |
Uses a props-only response fixture. |
packages/craftcms-ui/src/core/element-selector/asset-selector-controller.test.ts |
Uses a props-only response fixture. |
packages/craftcms-ui/src/components/thumbnail-loader/README.md |
Removes an obsolete consumer reference. |
packages/craftcms-ui/src/components/switch/switch.ts |
Updates toggle-ownership comments. |
packages/craftcms-ui/src/components/element-selector-modal/element-selector-modal.test.ts |
Uses a props-only modal fixture. |
packages/craftcms-ui/src/components/element-selector-modal/element-selector-modal.browser.test.ts |
Uses a props-only browser fixture. |
packages/craftcms-ui/scripts/build.js |
Stops building factory entries. |
packages/craftcms-ui/package.json |
Removes factory package exports. |
packages/craftcms-legacy/package.json |
Removes the font-conversion dependency. |
packages/craftcms-legacy/generalsettings/webpack.config.js |
Deletes the obsolete rebranding build. |
packages/craftcms-legacy/generalsettings/src/rebrand.scss |
Deletes obsolete rebranding styles. |
packages/craftcms-legacy/generalsettings/src/rebrand.js |
Deletes obsolete rebranding behavior. |
packages/craftcms-legacy/focalpoint/webpack.config.js |
Deletes the standalone focal-point build. |
packages/craftcms-legacy/dashboard/src/Dashboard.js |
Uses native grid properties. |
packages/craftcms-legacy/cpcompat/src/element-index/ThumbsElementIndexView.js |
Preserves the legacy thumbnail index view. |
packages/craftcms-legacy/cpcompat/src/element-index/index.js |
Assembles adapter index compatibility. |
packages/craftcms-legacy/cpcompat/src/element-field-settings.js |
Documents adapter ownership in comments. |
packages/craftcms-legacy/cpcompat/src/craft/Queue.js |
Initializes legacy queue compatibility. |
packages/craftcms-legacy/cpcompat/src/craft/index.js |
Assembles the relocated Craft compatibility entry. |
packages/craftcms-legacy/cpcompat/src/assets-field-settings.js |
Documents adapter ownership in comments. |
packages/craftcms-legacy/cpcompat/src/admin-table.js |
Documents adapter ownership in comments. |
packages/craftcms-legacy/cp/webpack.config.js |
Deletes the old CP bundle build. |
packages/craftcms-legacy/cp/Ttf2Woff2Plugin.js |
Deletes the obsolete font converter. |
packages/craftcms-legacy/cp/src/images/view-modes/cards.svg |
Removes the old bundle illustration. |
packages/craftcms-legacy/cp/src/images/preview/icon-phone.svg |
Removes the old preview icon. |
packages/craftcms-legacy/cp/src/images/preview/chrome-tablet-top.svg |
Removes old tablet artwork. |
packages/craftcms-legacy/cp/src/images/preview/chrome-tablet-bottom.svg |
Removes old tablet artwork. |
packages/craftcms-legacy/cp/src/images/preview/chrome-phone-top.svg |
Removes old phone artwork. |
packages/craftcms-legacy/cp/src/images/preview/chrome-phone-bottom.svg |
Removes old phone artwork. |
packages/craftcms-legacy/cp/src/images/image-editor/filters.svg |
Removes the old editor icon. |
packages/craftcms-legacy/cp/src/images/image-editor/crop.svg |
Removes the old editor icon. |
packages/craftcms-legacy/cp/src/images/dev-mode.svg |
Removes old development-mode artwork. |
packages/craftcms-legacy/cp/src/css/craft.scss |
Deletes the old CP stylesheet entry. |
packages/craftcms-legacy/cp/src/css/_shame.scss |
Deletes obsolete browser workarounds. |
packages/craftcms-legacy/cp/src/css/_entry-type-select.scss |
Deletes old entry-type styles. |
packages/craftcms-legacy/cp/src/css/_debug_toolbar.scss |
Deletes old debug-toolbar styles. |
packages/craftcms-legacy/cp/src/css/_craft-spinner.scss |
Deletes old spinner styles. |
packages/craftcms-legacy/cp/src/Craft.js |
Deletes the monolithic CP entry. |
package.json |
Adds the module iframe-resizer dependency. |
docs/messages.md |
Documents the modern notification renderer. |
.github/workflows/sync-cms-assets.yml |
Checks replacement build artifacts. |
.github/instructions/a11y.instructions.md |
Updates screen-reader-only class guidance. |
Review effort: Balanced
Recovery codes' Download action is now a descriptor array, which the Password view model cast to a string, so the page failed with an array to string conversion for anyone with recovery codes. Take the URL, download type and elevation flag from the descriptor, keeping the Vue screen's contract. Amp-Thread-ID: https://ampcode.com/threads/T-01a1a41f-35f1-75f6-a070-f628cc4e7276 Co-authored-by: Amp <amp@ampcode.com>
The preview template no longer sets window.imageFocalPoint, so the preview modal's resize and teardown hooks did nothing. Call the focal point module's current editor instead. Amp-Thread-ID: https://ampcode.com/threads/T-01a1a41f-35f1-75f6-a070-f628cc4e7276 Co-authored-by: Amp <amp@ampcode.com>
The Factory and Utilities docs still showed the per-component factories and button builders that create() replaced, so their imports no longer resolved. Amp-Thread-ID: https://ampcode.com/threads/T-01a1a41f-35f1-75f6-a070-f628cc4e7276 Co-authored-by: Amp <amp@ampcode.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Removing jQuery leaves the field layout designer waiting indefinitely for $ on core-only installations, preventing its tab controls, field library, and drag handlers from initializing.
No open issues 🎉
Review effort: Balanced
It waited for Craft.Grid and a global $ before initializing, though it now builds its grids with the native Grid module. Without the Yii2 adapter neither global appears, so its tabs, drag handlers and field library never initialized. Wait only for the field search input. Amp-Thread-ID: https://ampcode.com/threads/T-01a1a41f-35f1-75f6-a070-f628cc4e7276 Co-authored-by: Amp <amp@ampcode.com>
There was a problem hiding this comment.
🔵 Needs a closer look
The cross-stack bootstrap and adapter migration requires browser validation of initial loads, legacy plugin compatibility, and accessibility behavior that could not be exercised in this review environment.
No open issues 🎉
Review effort: Balanced


This PR combines three earlier pull requests (#20276, #20320, #20359) into one branch, rebased onto 6.x. It's the same work, but reviewers only have to look at one thing, and nothing has to be kept in sync between branches.
What it does, in three steps
Move old control panel code to modern modules. The old jQuery-based JavaScript for the control panel (about 24 files, 20,000+ lines) is gone. Each file was either rewritten as a TypeScript module, copied unchanged into a compatibility layer (the "adapter") so plugins keep working, or deleted. The old
Craft.*functions now exist only in that adapter, for backwards compatibility. Core code now calls simpler functions instead, likeshowError(message)ort('Save')in place ofCraft.cp.displayError(message)orCraft.t('app', 'Save').Stop loading jQuery and Garnish in core. The control panel no longer loads these two older libraries on its own. Core now uses plain browser features and custom elements (for things like element select inputs, menus and tabs). The adapter still loads jQuery and Garnish, so plugins that depend on them continue to work. Plugins that extend the old element select classes keep working too.
Share control panel modules with plugins. Plugins can now import
vue,@craftcms/cpand@craftcms/garnishfrom the control panel itself, instead of bundling their own copies or relying on old global objects.@craftcms/cpgains helpers for translation, HTTP requests, URLs, config, slideouts, element editors, the image editor, uploads and more.Bugs fixed along the way
Testing
Related notes
HtmlSanitizerManager::config()) is included as a cherry-pick but is tracked separately in [6.x] Add HtmlSanitizerManager::config() #20328.