nextcloud / nextcloud/mail

Vue3 migration organization

Open
#13,622 0 comments 2 reactions 2 assignees View on GitHub

@GretaD is already working on this.

Since Sep 2, 2026.

  • #13589 by @GVodyanov — closed without merging
discussion
Dominant language
JavaScript
Stars
1k
Forks
348
Avg merge
12h 28m
Merged PRs (30d)
91

Description

Related to https://github.com/nextcloud/groupware/issues/64

Wave A — preparation, merged to main, shipped on Vue 2.7

Wave A ships as three PRs, one per section below. Each section is a single theme, is
independently releasable, and is independently revertible. The item IDs (A1A18) are stable and
still index the per-item detail in §3; only the packaging changed.

Merge order is A-1 → A-2 → A-3, because A-3 contains A11, which rewrites the import line of nearly
every component and will conflict with anything still in flight.

A-1 — Template API alignment (@nextcloud/vue prop, event and slot renames) https://github.com/nextcloud/mail/pull/13589

Everything the v8.40 forward-compatible aliases already accept: props renamed, events renamed, slots
renamed, booleans inverted. Mechanical, template-only, no behaviour change on Vue 2.7. Land the items
in the listed order and rebase between them — they touch overlapping component files.

  • A4:checked / @update:checkedv-model / @update:model-value on NcCheckboxRadioSwitch, NcActionCheckbox, NcActionRadio (13 files)
  • A5:value / @update:value / @inputv-model / @update:model-value on the 13 other input components (32 files)
  • A6type="primary|secondary|…"variant=, and native-typetype on NcButton / NcActions / NcDialogButton

A7 #default#icon slot on NcInputField / NcTextField / NcPasswordField

A-2 — Retire the Vue-2-only dependencies and component APIs https://github.com/nextcloud/mail/pull/13626

Everything that has to stop being a Vue-2-only package or a removed-in-v9 component API. Few files,
but the only hand-written UI in Wave A, so this is the section that needs manual testing. Give each
replacement its own commit and its own QA pass — see §8.

  • A2 — Drop the unused v-tooltip plugin from src/main.js (imported, registered, never used in a template)
  • A8isMobile mixin → useIsMobile() composable (src/components/MailboxThread.vue, the only user)
  • A10FilePickerVue component → getFilePickerBuilder() function (4 files)
  • A13 — Replace vue-autosize (Vue-2-only, no successor)
  • A14 — Replace @riophae/vue-treeselect in MailboxInlinePicker.vue (Vue-2-only, unmaintained) — revives #13412
  • A15 — Replace vue-tabs-component in AccountForm.vue (Vue-2-only) — revives #13411
  • A16 — Replace vue-dndrop in quickActions/Settings.vue (Vue-2-only) — revives #13413
  • A17 — Verify emojiSearch / emojiAddRecent import path for v9 (TextEditor.vue)
A-3 — Module boundaries and the v9 audit

Everything that changes how modules are imported rather than how components are used, plus the
written-down audit of what Wave B will have to repair. A11 is the whole reason this section is last.

  • A1import { translate as t }import { t } (18 sites); same for translatePlural as n: https://github.com/nextcloud/mail/pull/13492
    - [ ] A3 — Replace Vue.set/Vue.delete with a local set/del shim (55 call sites, 3 files): https://github.com/nextcloud/mail/pull/13392 MOVED TO WAVE B
  • A11 — Barrel imports from '@nextcloud/vue' → per-component subpath imports (~50 files) — last item in the wave
  • A18 — Deep-selector and internal-class-name audit (105 hits) — write down what will break, fix what can be fixed early

The three are close in size for different reasons: A-1 is the most files but one changed line per
site; A-2 is the fewest files but the only real new code; A-3 is ~50 mechanical files plus a
document. If A-2's replacements turn out larger than estimated, split A14–A16 out rather than
letting the PR grow past a few thousand lines.

Wave B — https://github.com/nextcloud/mail/pull/13666

Nothing here works on Vue 2. Land these onto vue3, then merge vue3main once.

  • B1 — Dependency bump (#13407, rebase)
  • B2patch-package: fix or drop patches/splitpanes+2.4.1.patch (v9 ships splitpanes 4.x)
  • B3 — Entry points → createApp (#13405/#13408, pick one, rebase)
  • B4 — Router → createRouter / createWebHistory (folded into B3)
  • B5.syncv-model:prop (#13410, rebase — 13 sites, 10 files)
  • B6 — CKEditor → @ckeditor/ckeditor5-vue (#13414, rebase)
  • B7vue-shortkeyvue3-shortkey
  • B8 — Remove vue-frag (NavigationAccount.vue) — Vue 3 has native fragments
  • B9 — Remove .native modifiers (4 sites) and add the corresponding emits declarations
  • B10<template functional> → plain SFC (src/components/icons/JunkIcon.vue)
  • B11<transition> class renames: v-enterv-enter-from, v-leavev-leave-from (3 components)
  • B12 — Collapse the set/del shim from A3 into plain assignment (one-file diff)
  • B13 — Unit tests: @vue/test-utils v1 → v2 (#13415, rebase)
  • B14vitest.config.js: @vitejs/plugin-vue2@vitejs/plugin-vue
  • B15eslint.config.mjs: recommendedVue2recommended, then npm run lint:fix
  • B16 — Pinia 2 → 3, @pinia/testing bump, drop PiniaVuePlugin
  • B17 — Add explicit emits: declarations across components (ESLint vue/require-explicit-emits)
  • B18 — Drop the Nextcloud.js mixin in favour of app.config.globalProperties or per-file imports
  • B19 — CSS repair pass: box-sizing: border-box on modals/popovers, vs__* (vue-select 4), @vuepic/vue-datepicker replacing mx-datepicker
  • B20npm run build clean, npm run lint clean, npm run stylelint clean, npm run test:unit green
  • B21 — Replace Vue.set/Vue.delete with a local set/del shim (55 call sites, 3 files): https://github.com/nextcloud/mail/pull/13392
Wave C — after the flip
  • C1 — Full manual QA pass against the §8 matrix
  • C2 — Playwright e2e suite green (npm run test:e2e)
  • C3 — Design review, then follow-up styling PRs (calendar did exactly this — do not block the merge on pixel polish)
  • C4 — File upstream bugs against @nextcloud/vue for anything broken in the library itself
  • C5 — Bump appinfo/info.xml if the Nextcloud minimum has to move
  • C6 — Optional follow-ups: Options API → Composition API, <script setup>, TypeScript

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.