Skip to content

feat!: Migrate dashboard to frappe-ui v1 (and Vite 8)#272

Merged
harshtandiya merged 13 commits into
developfrom
feat/frappe-ui-v1
Jul 23, 2026
Merged

feat!: Migrate dashboard to frappe-ui v1 (and Vite 8)#272
harshtandiya merged 13 commits into
developfrom
feat/frappe-ui-v1

Conversation

@harshtandiya

Copy link
Copy Markdown
Collaborator

Moves the dashboard from frappe-ui@0.1.257 to 1.0.0-beta.25, then upgrades the build toolchain to Vite 8.

Why this is more than a version bump

Component and JS APIs in frappe-ui v1 are backward compatible — deprecated paths still work and just warn. The design-token layer and the theme system are hard breaks, and they are what actually broke the running app: token names were renamed (surface-whitesurface-base, ink scales went to 1–10, typography classes merged), and v1 tokens are theme-aware (darkMode: ['selector', '[data-theme="dark"]']) where v0 ignored data-theme entirely. With the default dark theme, light ink text was landing on an unstyled white layout — invisible.

What's in here

Commit Change
5cd520c Bump to v1, drop the dev-only dashboard/frappe-ui submodule, simplify vite.config.js
0ffd66e Pre-bundle nested feather-icons so the dev app mounts
d0cc4ff Adopt v1 Dialog props + lucide icons (14 dialogs, 4 icon sites)
d0ea5c2 Restore Zoom button hover color
becb2b8 Drop unused legacy Input global registration
8e78e75 tokens-v2 codemod (38 files) + theme-aware Layout background
830d736 Proposal editor: TextEditor → headless Editor + RichTextKit
4a90e41 Vite 5 → 8, @vitejs/plugin-vue 6, vue-tsc 3.3; drop dead unplugin-auto-import

The submodule removal makes npm the single source of truth — it was a redundant local patch plus ~30k lines of format churn and a second version to keep in sync.

Notes for review

Two dev-only traps that are runtime-only — they pass typecheck and build, and only show up when you load the page:

  1. Excluding frappe-ui from pre-bundling (needed for its ~icons/lucide/* virtuals) kills CJS interop for its nested feather-icons, so the app never mounts — blank page. Hence the optimizeDeps.include entry.
  2. Token rename + theme-aware data-theme="dark" default meant light ink text on an unstyled white layout. Hence the codemod plus bg-surface-base on the Layout root.

ProseMirror is pinned via resolutions. yarn had hoisted a stale set (state@1.4.2, view@1.30.2, model@1.19.0, transform@1.7.1) alongside the versions tiptap resolves, so the editor stack was being bundled twice. Pinning cut the ProposalDetails chunk from 1295 kB to 935 kB.

optimizeDeps.exclude: ["frappe-ui"] has to stay on Vite 8, but for a new reason. Rolldown resolves the extensionless #molecules/* specifiers that esbuild could not, so the original justification is gone — but frappe-ui and frappe-ui/editor pre-bundle as two separate entries that each inline their own ProseMirror copy, which gives two selection-JSON-ID registries and the editor dies on Duplicate use of selection JSON ID gapcursor. Neither resolve.dedupe nor pre-bundling ProseMirror explicitly merges the entries. The comment in vite.config.js records this.

Default theme stays dark (Navbar.vue, useStorage("user-theme", "dark")) — now functional in both modes.

Known cosmetic gap, not fixed: frappe-ui's MenuItems evaluates command availability during render, before EditorContent mounts the ProseMirror view, and only recomputes on an editor transaction. Editor toolbar buttons therefore render disabled until the first click into the editor, then stay enabled. Deliberately left alone rather than worked around — the first interaction is clicking into the editor anyway.

Verification

Typecheck and build clean. Vite 8 build is 5.98s → 2.25s with better chunking (index 728 kB → 411 kB).

Exercised in a browser on both the dev server and the production build: account pages (bookings, tickets, proposals, sponsorships), check-in, home — all render with no console errors. Proposal editor round-tripped end to end (typed, bolded via the toolbar, saved, confirmed <p><strong>…</strong></p> persisted), test record reset afterward.

Not covered: a full logged-in click-through of the booking and payment flows. Those use the same tokens and dark: variants so they should follow, but they have not been exercised against real data.

Deferred: TextEditor elsewhere is untouched; only the proposal editor moved to the new Editor.

🤖 Generated with Claude Code

harshtandiya and others added 8 commits July 22, 2026 17:06
Bump frappe-ui 0.1.257 -> 1.0.0-beta.25 and remove the dashboard/frappe-ui
git submodule; the npm package is now the single source. Simplify
vite.config.js to a static config that always uses the published plugin,
and exclude frappe-ui from esbuild pre-bundling since it ships as source
importing ~icons/lucide/* virtuals that only the Vite plugin resolves.

Fix four type errors surfaced by v1's stricter types (nullable length
guard, Combobox string|null emit, FileUploader error slot prop).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Convert all Dialog usages from the deprecated `options` blob and
`#body-content`/`#body-title`/`#body` slots to flat top-level props and
the default/`#title` slots (`#body` -> `bare` prop). Flatten the withdraw
dialog's icon to `theme` and rename its lucide icon to `triangle-alert`.
Replace remaining feather icon strings with `lucide-` names.
The v1 ink-blue scale defines shades 1-3 only, so `hover:bg-ink-blue-4`
resolved to nothing and the Join Zoom button no longer darkened on hover.
Use the raw blue-700 palette shade (one step darker than ink-blue-3) to
restore the hover feedback.
The Input component is deprecated in frappe-ui v1 and was registered
globally but never used in any template. Remove its import and
registration; TextInput and FormControl remain.
Excluding frappe-ui from esbuild pre-bundling (needed for its ~icons/lucide
virtuals) left its bundled CJS feather-icons without ESM interop, so the
FeatherIcon default import failed and the app never mounted (blank page).
Pre-bundle feather-icons, including frappe-ui's nested copy via the `>`
dep path, to restore the default export.
v1 renamed the design tokens (surface-white -> surface-base, expanded the
ink accent scales, merged text size+weight into single classes). The old
class names resolved to undefined CSS variables under v1, so text and
surface colors rendered blank. Run the official tokens-v2 codemod across
the dashboard to adopt the new names.

Also give the app Layout a theme-aware background (bg-surface-base) and
base text color. Previously the root had no background, so with the
default dark theme the light ink text sat on an unstyled white page and
was invisible. Both light and dark themes now render coherently.
Replace the deprecated TextEditor with the headless Editor from
frappe-ui/editor, composed with EditorFixedMenu and EditorContent. The
kit runs without the media extensions since proposals have no upload
handler wired.

Pin the ProseMirror packages via resolutions: the tree carried both a
stale hoisted copy and the one tiptap resolves, which bundled the editor
stack twice.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Vite 8 replaces esbuild with rolldown for bundling. @vitejs/plugin-vue 6
is the first release listing Vite 8 in its peer range. vue-tsc moves with
it; nothing else is Vite-coupled.

Drop unplugin-auto-import: it was never wired into vite.config.js, and
pinning it at the root only forced frappe-ui to nest the 19.x its
lucideIcons plugin actually imports.

frappe-ui stays out of pre-bundling, but for a new reason — rolldown
resolves the extensionless `#molecules/*` specifiers esbuild could not,
so the note about esbuild no longer applies.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@harshtandiya harshtandiya changed the title Migrate dashboard to frappe-ui v1 (and Vite 8) feat!: Migrate dashboard to frappe-ui v1 (and Vite 8) Jul 22, 2026
@greptile-apps

greptile-apps Bot commented Jul 22, 2026

Copy link
Copy Markdown

Greptile Summary

This PR migrates the dashboard to frappe-ui v1 and Vite 8. The main changes are:

  • Updates design tokens, typography, icons, dialogs, and theme-aware layout colors.
  • Replaces the proposal TextEditor with the headless Editor and RichTextKit.
  • Upgrades Vite, its Vue plugin, and vue-tsc.
  • Pins ProseMirror packages and adjusts dependency optimization.
  • Removes the local frappe-ui submodule and unused auto-import setup.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues were established in the updated code.
  • The build, theme, dialog, and editor migrations preserve their existing application paths.

Important Files Changed

Filename Overview
dashboard/package.json Upgrades frappe-ui and the Vite toolchain, pins ProseMirror packages, and removes an unused development dependency.
dashboard/vite.config.js Updates dependency optimization and module resolution for Vite 8 and frappe-ui v1.
dashboard/tailwind.config.js Uses the frappe-ui v1 Tailwind preset and includes its component and editor source paths.
dashboard/src/layouts/Layout.vue Adds theme-aware background and foreground tokens to the dashboard layout.
dashboard/src/components/ProposalEditDialog.vue Migrates proposal editing to the headless frappe-ui editor and RichTextKit.
dashboard/src/components/AddOnPreferenceDialog.vue Migrates the add-on preferences dialog to frappe-ui v1 props and slots.

Reviews (3): Last reviewed commit: "fix(dashboard): inline add-on dialog pro..." | Re-trigger Greptile

harshtandiya and others added 3 commits July 22, 2026 17:19
frappe-ui v1 renders a select as a combobox button that opens a listbox
instead of a native `select`, so the old locator matched nothing and
`selectOption` had nothing to act on. Pick the option by clicking it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The add-on dialog was the only one still passing its title and size
through a `v-bind` object; inline them like the other dialogs, and
translate the title while it moves.

Building the combobox matcher with `new RegExp(label)` broke on any
label containing regex metacharacters. A plain string already matches
case-insensitively on a substring.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@harshtandiya harshtandiya linked an issue Jul 23, 2026 that may be closed by this pull request

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

harshtandiya has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

harshtandiya has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@harshtandiya harshtandiya added the backport main backport to main branch label Jul 23, 2026
@harshtandiya
harshtandiya merged commit feafea0 into develop Jul 23, 2026
8 checks passed
@harshtandiya
harshtandiya deleted the feat/frappe-ui-v1 branch July 23, 2026 19:59
@github-actions

Copy link
Copy Markdown
Contributor

Successfully created backport PR for main:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport main backport to main branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Frappe v1.0.0-beta migration

1 participant