You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(hub): add dock grouping (groupId + type:'group')
Let a hub collapse related dock entries under a single dock-bar button
when many integrations share one UI. Grouping only makes sense once a hub
combines tools, so the data model and host validation land here while the
hub continues to ship no UI — downstream kits derive the visual collapse
from the existing 'devframe:docks' shared state.
- Add an optional `groupId` pointer to every dock entry (membership, not
containment) and a new `type:'group'` entry (`DevframeViewGroup`) with an
optional `defaultChildId`. This is a flat pointer model: members stay
independently-registered top-level entries, so register/update/values,
the views map, settings, and shared-state sync all keep working unchanged.
- Validate in the host: reject self-grouping (DF8103) and nested groups
(DF8104, one level only). Orphan members whose group is unregistered are
tolerated and render as normal top-level entries, keeping registration
order-independent.
> Dock entry "`{id}`" cannot set groupId to its own id
10
+
11
+
## Cause
12
+
13
+
A dock entry registered with `groupId` pointing at its own `id`. `groupId` is a pointer to a *different* group entry the entry belongs to, so a self-reference would describe an entry that collapses under itself.
14
+
15
+
## Fix
16
+
17
+
- Point `groupId` at the `id` of a `type: 'group'` entry, such as `groupId: 'nuxt'`.
18
+
- Omit `groupId` entirely to keep the entry as a normal top-level dock entry.
19
+
20
+
## Source
21
+
22
+
-[`packages/hub/src/node/host-docks.ts`](https://github.com/devframes/devframe/blob/main/packages/hub/src/node/host-docks.ts) — `DevframeDocksHost.register()` and `update()` throw this when `view.groupId === view.id`.
> Dock group "`{id}`" cannot itself belong to a group (nested groups are unsupported)
10
+
11
+
## Cause
12
+
13
+
A `type: 'group'` entry was registered with `groupId` set. Dock grouping is one level deep: a group collects member entries, but a group cannot itself be a member of another group.
14
+
15
+
## Fix
16
+
17
+
- Remove `groupId` from the group entry so it stays a top-level dock-bar button.
18
+
- Keep members one level under their group; place each member's `groupId` on the leaf entry, not on another group.
19
+
20
+
## Source
21
+
22
+
-[`packages/hub/src/node/host-docks.ts`](https://github.com/devframes/devframe/blob/main/packages/hub/src/node/host-docks.ts) — `DevframeDocksHost.register()` and `update()` throw this when `view.type === 'group'` and `view.groupId` is set.
|`ctx.docks`|`register / update / values`| Multi-tool dock entries (iframes, launchers, json-render, custom-render) and groups that collapse them under one button. |
19
19
|`ctx.terminals`|`register / startChildProcess`| Aggregate terminal sessions, stream output over a well-known channel. |
Framework kits typically wrap this in a plugin shell. `@vitejs/devtools-kit`'s `createPluginFromDevframe` returns a Vite `Plugin` whose `devtools.setup` calls into `mountDevframe`.
45
45
46
+
## Grouping dock entries
47
+
48
+
When a hub combines many integrations, related dock entries can collapse under a single dock-bar button. A `type: 'group'` entry is that button; any entry pointing its `groupId` at the group's `id` becomes a member.
49
+
50
+
```ts
51
+
ctx.docks.register({
52
+
type: 'group',
53
+
id: 'nuxt',
54
+
title: 'Nuxt',
55
+
icon: 'logos:nuxt-icon',
56
+
category: 'framework',
57
+
defaultChildId: 'nuxt:overview', // optional; popover-only when omitted
58
+
})
59
+
60
+
ctx.docks.register({
61
+
type: 'iframe',
62
+
id: 'nuxt:overview',
63
+
title: 'Overview',
64
+
icon: 'ph:gauge-duotone',
65
+
url: '/__nuxt-overview/',
66
+
groupId: 'nuxt', // joins the group above
67
+
})
68
+
```
69
+
70
+
`groupId` lives on every entry kind, so iframes, launchers, json-render panels, and custom-render views all join groups the same way. The group and its members stay independent top-level entries in `devframe:docks`; a downstream UI derives the visual collapse by matching each member's `groupId` to the group's `id` and renders members in a popover or sub-navigation. `defaultChildId` names the member opened when the group button is activated.
71
+
72
+
Grouping is one level deep: members join a group, and a group is always a top-level button. A member whose group is never registered renders as a normal top-level entry, so registration order is free.
73
+
46
74
## The protocol — what the UI sees
47
75
48
76
A hub-aware UI doesn't import any hub classes; it reads three shared-state keys and one RPC method:
0 commit comments