frappe / frappe/builder

Upgrading to frappe-ui 1.0.0

Open
#718 7 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
2.4k
Forks
534
Avg merge
1d 2h
Merged PRs (30d)
45

Description

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](https://github.com/frappe/frappe-ui/blob/main/docs/content/docs/migration.md).

| # | 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`:

```ts
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()`:

```ts
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 |

```vue











```

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.

```vue

```

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](https://github.com/frappe/frappe-ui/blob/main/docs/content/docs/migration.md#popover--hovercard--tooltip).

---

# 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`.

## `placement` → `align`

| 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:62` — `right`.
- `frontend/src/components/MainMenu.vue:2` — `left — just delete it`.
- `frontend/src/components/PageClientScriptManager.vue:43` — `right`.
- `frontend/src/components/Settings/GlobalDomains.vue:23` — `right`.

## `{ group, items }` → `{ group, options }`

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

```js
// 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](https://github.com/frappe/frappe-ui/blob/main/docs/content/docs/migration.md#dropdown-and-contextmenu).

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by bumping the frappe-ui pin in frontend/package.json, then read the migration guide and work through the listed files under frontend/src. Use frontend/src/main.ts and frontend/src/utils/realtimeHandler.ts for the socket change, then run vue-tsc to find remaining Popover, Tooltip, and Dropdown API uses. Done means all listed sites use the frappe-ui 1.0.0 APIs without silent runtime changes.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
56/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.