Skip to content

Upgrading to frappe-ui 1.0.0 #718

Description

@netchampfaris

frappe-ui is heading to a 1.0.0 tag. The breaking changes land as separate PRs. This issue is the single place that tracks all of them for Builder.

  • Work top to bottom. Each section names the exact sites in this repo, with before/after.
  • More sections get appended as more breaks land before the tag.
  • Do not start until you bump the frappe-ui pin. Today it is 1.0.0-beta.21 in frontend/package.json.
  • Full list of changes: migration guide.
# Change PR Fails at build?
1 $socket is no longer set by the plugin frappe/frappe-ui#948 No — throws at runtime
2 Popover v0 API removed; Tooltip placement and #body renamed (14 Popover, 9 Tooltip) frappe/frappe-ui#956 No — every break is silent
3 Dropdown placement, { group, items } and component: rows removed (11 sites) frappe/frappe-ui#957 No — silent; vue-tsc flags them

1. $socket is no longer set by the plugin

PR: frappe/frappe-ui#948

frappe-ui 1.0.0 removes initSocket and the FrappeUI plugin's socketio option. The plugin no longer creates a socket.io connection.

Builder is the only app that used the plugin's socket instead of building its own.

1.1 What breaks

frontend/src/utils/realtimeHandler.ts:10:

this.socket = getCurrentInstance()!.appContext.config.globalProperties.$socket;

frontend/src/main.ts:17 calls app.use(FrappeUI) with no options. socketio used to default to true, so the plugin set $socket for you. It no longer does.

This is not a build failure. Reading $socket throws at runtime with a message naming the fix, so it will surface on the first page that opens a realtime connection rather than as undefined crashing somewhere else.

1.2 Fix

Create the connection in frontend/src/main.ts and assign it before app.mount():

import { io } from 'socket.io-client'

const host = window.location.hostname
const port = window.location.port ? ':9000' : ''
const protocol = port ? 'http' : 'https'
const siteName = import.meta.env.DEV ? host : window.site_name

app.config.globalProperties.$socket = io(
  `${protocol}://${host}${port}/${siteName}`,
  { withCredentials: true },
)

That is exactly what initSocket did. Assigning your own replaces the guard, so nothing else changes.

Every other Frappe app already does this in its own src/socket.js, which is why Builder is the only one affected. Putting it in a frontend/src/socket.ts would match them.


Replaces #717.


2. Popover and Tooltip: the v0 API is gone

PR: frappe/frappe-ui#956

frappe-ui 1.0.0 removes the v0 Popover API and renames two things on Tooltip. Builder has 23 affected sites.

Nothing warns. Vue drops an unknown prop or slot in silence, so a missed site renders a popover with no trigger, an empty one, or a tooltip on the wrong edge — and the build stays green. Work the list.

Line numbers are against develop at eef1132.

Popover

v0 v1
#target slot #trigger — it wires its own click, so drop the handler
#body slot #default slot plus the bare prop — #body rendered outside the panel shell
#body-main slot #default slot
togglePopover slot prop toggle
isOpen slot prop open
placement="bottom-end" side="bottom" + align="end" (a bare placement="bottom" is align="center")
trigger="hover" the HoverCard component
<!-- before -->
<Popover placement="bottom-end">
  <template #target="{ togglePopover }">
    <Button label="Filter" @click="togglePopover" />
  </template>
  <template #body-main="{ close }">
    <FilterPanel @done="close" />
  </template>
</Popover>

<!-- after -->
<Popover side="bottom" align="end">
  <template #trigger>
    <Button label="Filter" />
  </template>
  <template #default="{ close }">
    <FilterPanel @done="close" />
  </template>
</Popover>

The leftover click handler is the one that bites. #trigger already toggles, so keeping your own @click toggles twice and the popover never opens.

#body and #body-main are not the same slot. #body-main rendered inside the panel, so it is plain #default. #body replaced the panel, so it needs bare as well — without it your content lands inside a second panel.

<!-- before -->
<Popover>
  <template #body><EmojiPicker /></template>
</Popover>

<!-- after -->
<Popover bare>
  <EmojiPicker />
</Popover>

14 sites:

  • frontend/src/components/AIPageGeneratorModal.vue:76 — #target slot, #body-main slot, placement prop, togglePopover slot prop.
  • frontend/src/components/ArrayInput.vue:2 — #target slot, #body slot, placement prop.
  • frontend/src/components/BackgroundHandler.vue:2 — #target slot, #body slot, placement prop, togglePopover slot prop.
  • frontend/src/components/BuilderToolbar.vue:29 — #target slot, #body slot, placement prop, isOpen slot prop, togglePopover slot prop.
  • frontend/src/components/ComponentUpdates.vue:2 — #target slot, #body slot, placement prop, togglePopover slot prop.
  • frontend/src/components/Controls/ColorPicker.vue:2 — #target slot, #body slot, placement prop, isOpen slot prop, togglePopover slot prop.
  • frontend/src/components/Controls/GradientEditor.vue:27 — #target slot, #body slot, placement prop, togglePopover slot prop.
  • frontend/src/components/Controls/InputLabel.vue:4 — #target slot, #body slot, placement prop, trigger prop.
  • frontend/src/components/Controls/SearchBlock.vue:22 — #target slot, #body slot, isOpen slot prop, togglePopover slot prop.
  • frontend/src/components/ImageUploadInput.vue:12 — #target slot, #body slot, placement prop, togglePopover slot prop.
  • frontend/src/components/ObjectInput.vue:2 — #target slot, #body slot, placement prop.
  • frontend/src/components/PropsEditor.vue:7 — #target slot, #body slot, placement prop.
  • frontend/src/components/PropsEditor.vue:82 — #target slot, #body slot, placement prop.
  • frontend/src/components/ShadowHandler.vue:2 — #target slot, #body slot, placement prop, togglePopover slot prop.

Tooltip

v0 v1
placement="top" side="top"
arrowClass [data-slot="arrow"] in CSS, or offset to shift the bubble

#default stays the trigger. That inversion is deliberate and is not changing.

9 sites:

  • frontend/src/components/BuilderLeftPanel.vue:12 — placement prop.
  • frontend/src/components/BuilderToolbar.vue:77 — arrowClass.
  • frontend/src/components/BuilderToolbar.vue:107 — arrowClass.
  • frontend/src/components/BuilderToolbar.vue:114 — arrowClass.
  • frontend/src/components/BuilderToolbar.vue:126 — arrowClass.
  • frontend/src/components/BuilderToolbar.vue:130 — arrowClass.
  • frontend/src/components/ComponentUpdates.vue:4 — arrowClass.
  • frontend/src/components/Modals/TokenManager.vue:175 — placement prop.
  • frontend/src/components/Modals/TokenManager.vue:201 — placement prop.

Full before/after for all of it: migration guide.


3. Dropdown: placement, { group, items } and component: rows are gone

PR: frappe/frappe-ui#957

frappe-ui 1.0.0 removes three shapes from Dropdown (ContextMenu shares the option types). Builder has 11 affected sites.

Nothing fails the build. A placement prop is dropped and the menu shifts to the default alignment; a { group, items } group resolves to zero options and renders an empty menu; a component: row renders as a plain action row using its label, which for most of these rows is empty. Dev builds log a console warning for the last two, and the removed keys stay in the types as never, so vue-tsc names every site. Work the list.

Line numbers are against develop at 0c8a813.

placementalign

before after
placement="right" align="end"
placement="center" align="center"
placement="left" delete the prop — start is the default

4 sites:

  • frontend/src/components/DashboardSidebar.vue:62right.
  • frontend/src/components/MainMenu.vue:2left — just delete it.
  • frontend/src/components/PageClientScriptManager.vue:43right.
  • frontend/src/components/Settings/GlobalDomains.vue:23right.

{ group, items }{ group, options }

Same key, new name; nothing else about the group changes:

// before
{ group: __('Actions'), hideLabel: true, items: [...] }

// after
{ group: __('Actions'), hideLabel: true, options: [...] }

7 sites:

  • frontend/src/components/DashboardSidebar.vue:159.
  • frontend/src/components/DashboardSidebar.vue:170.
  • frontend/src/components/DashboardSidebar.vue:191.
  • frontend/src/components/MainMenu.vue:48.
  • frontend/src/components/MainMenu.vue:55.
  • frontend/src/components/MainMenu.vue:88.
  • frontend/src/components/PageActionsDropdown.vue:7 — inline in the template.

Full before/after: migration guide.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions