update plan
This commit is contained in:
@@ -10,6 +10,13 @@ through its official `native-theme-gpui` connector.
|
|||||||
> mapping). Going through GPUI-Kit first makes that mapping unnecessary: the
|
> mapping). Going through GPUI-Kit first makes that mapping unnecessary: the
|
||||||
> connector already projects native themes onto gpui-component's `Theme`, and
|
> connector already projects native themes onto gpui-component's `Theme`, and
|
||||||
> every call site reads `cx.theme()` from gpui-component directly.
|
> every call site reads `cx.theme()` from gpui-component directly.
|
||||||
|
>
|
||||||
|
> **Revision 2.** Full replacement, no hybrids: no custom UI element is kept
|
||||||
|
> or maintained after Phase A. Earlier hybrid positions in this file (keep
|
||||||
|
> `ui::message` where it fits, possibly keep nav composites, keep an icon
|
||||||
|
> mapping shim) are dropped — kit elements are adopted outright, chat-specific
|
||||||
|
> composition moves into `chat_ui`, and the only coop-owned visuals left are
|
||||||
|
> brand SVG assets rendered through the kit `Icon`.
|
||||||
|
|
||||||
## 1. What the git history shows
|
## 1. What the git history shows
|
||||||
|
|
||||||
@@ -42,6 +49,8 @@ graph LR
|
|||||||
components and moves all color reads onto gpui-component's `Theme`
|
components and moves all color reads onto gpui-component's `Theme`
|
||||||
(`ThemeColor`, 139 semantic fields). The app runs on gpui-component's
|
(`ThemeColor`, 139 semantic fields). The app runs on gpui-component's
|
||||||
built-in light/dark palettes at the end of Phase A; `crates/theme` is gone.
|
built-in light/dark palettes at the end of Phase A; `crates/theme` is gone.
|
||||||
|
At the end of Phase A `crates/ui` contains no UI elements: every element
|
||||||
|
comes from the kit, and only app utilities survive there (§4.4).
|
||||||
|
|
||||||
**Phase B** adds `native-theme-gpui`, which installs native OS themes (or any
|
**Phase B** adds `native-theme-gpui`, which installs native OS themes (or any
|
||||||
of 16 bundled presets) into that same `Theme`. No call site changes — the
|
of 16 bundled presets) into that same `Theme`. No call site changes — the
|
||||||
@@ -69,15 +78,15 @@ crates.
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `menu/` (popup, dropdown, item) | 983 | `menu::{PopupMenu, PopupMenuItem, DropdownMenu, ContextMenu}` |
|
| `menu/` (popup, dropdown, item) | 983 | `menu::{PopupMenu, PopupMenuItem, DropdownMenu, ContextMenu}` |
|
||||||
| `dock/` (mod, panel) | 1,032 | `dock` (entity-backed DockArea / panels) |
|
| `dock/` (mod, panel) | 1,032 | `dock` (entity-backed DockArea / panels) |
|
||||||
| `motion.rs` | 668 | keep — app-level animation, no theme dependency |
|
| `motion.rs` | 668 | keep — animation utility, not an element; no theme dependency |
|
||||||
| `notification.rs` | 594 | `notification::Notification` + `WindowExt::push_notification`; placement via `Theme.notification` |
|
| `notification.rs` | 594 | `notification::Notification` + `WindowExt::push_notification`; placement via `Theme.notification` |
|
||||||
| `button.rs` | 581 | `button::{Button, ButtonGroup, Toggle, DropdownButton}` |
|
| `button.rs` | 581 | `button::{Button, ButtonGroup, Toggle, DropdownButton}` |
|
||||||
| `message.rs` | 553 | evaluate `message::{Message, Bubble, Attachment, MessageScroller}`; keep as app composite where it fits better |
|
| `message.rs` | 553 | `message::{Message, Bubble, MessageGroup, MessageScroller}` (avatar/header/content/footer slots); author grouping, date separators and receipts move into `chat_ui` as app code |
|
||||||
| `avatar.rs` | 445 | `avatar::Avatar` |
|
| `avatar.rs` | 445 | `avatar::Avatar` |
|
||||||
| `root.rs` | 430 | framework `Root` via `gpui_kit::open_window` (owns dialogs, notifications, tooltip/menu layers, focus traps) |
|
| `root.rs` | 430 | framework `Root` via `gpui_kit::open_window` (owns dialogs, notifications, tooltip/menu layers, focus traps) |
|
||||||
| `dialog.rs` | 394 | `WindowExt::open_dialog` / `AlertDialog`; custom footer buttons → Dialog's footer API |
|
| `dialog.rs` | 394 | `WindowExt::open_dialog` / `AlertDialog`; custom footer buttons → Dialog's footer API |
|
||||||
| `input/` | ~290 | `input::{Input, InputState, Textarea, NumberInput}`; delete the custom styling (its `input_bg`/`selection`/`caret` reads die with it) |
|
| `input/` | ~290 | `input::{Input, InputState, Textarea, NumberInput}`; delete the custom styling (its `input_bg`/`selection`/`caret` reads die with it) |
|
||||||
| `icon.rs` | 274 | `Icon` + `IconName` (Lucide); keep `ui::icon` as a thin mapping shim (see §4.3) |
|
| `icon.rs` | 274 | kit `Icon` + `IconName` (Lucide) at every call site; the module and the coop enum are deleted (see §4.3) |
|
||||||
| `kbd.rs` | 270 | `Kbd` |
|
| `kbd.rs` | 270 | `Kbd` |
|
||||||
| `tab/` | 385 | `tab::{Tab, TabBar, Tabs}` |
|
| `tab/` | 385 | `tab::{Tab, TabBar, Tabs}` |
|
||||||
| `title_bar.rs` | 218 | `TitleBar` (keep the client-side-decoration constants) |
|
| `title_bar.rs` | 218 | `TitleBar` (keep the client-side-decoration constants) |
|
||||||
@@ -85,12 +94,12 @@ crates.
|
|||||||
| `styled.rs` | 161 | `h_flex`/`v_flex`/`StyledExt` from the kit; drop coop-specific helpers as their users migrate |
|
| `styled.rs` | 161 | `h_flex`/`v_flex`/`StyledExt` from the kit; drop coop-specific helpers as their users migrate |
|
||||||
| `switch.rs` | 157 | `switch::Switch` |
|
| `switch.rs` | 157 | `switch::Switch` |
|
||||||
| `markdown.rs` | 146 | `text::TextView::markdown` (code styling via `Theme.highlight_theme`) |
|
| `markdown.rs` | 146 | `text::TextView::markdown` (code styling via `Theme.highlight_theme`) |
|
||||||
| `nav.rs` + `nav_item.rs` | 268 | `sidebar::{Sidebar, SidebarMenu, …}`; if the coop layout doesn't fit, keep as an app composite on top of kit primitives — decide during the slice |
|
| `nav.rs` + `nav_item.rs` | 268 | `sidebar::{Sidebar, SidebarHeader, SidebarGroup, SidebarMenu, SidebarMenuItem, SidebarFooter}`; the nav layout is adapted to the kit structure, not preserved |
|
||||||
| `group_box.rs` | 126 | `group_box::GroupBox` |
|
| `group_box.rs` | 126 | `group_box::GroupBox` |
|
||||||
| `scroll/` | ~124 | `scroll::{Scrollbar, Scrollable}` |
|
| `scroll/` | ~124 | `scroll::{Scrollbar, Scrollable}` |
|
||||||
| `resizable/` | 31 | `resizable::{h_resizable, v_resizable, resizable_panel}` |
|
| `resizable/` | 31 | `resizable::{h_resizable, v_resizable, resizable_panel}` |
|
||||||
| `tooltip.rs` | 34 | `.tooltip()` |
|
| `tooltip.rs` | 34 | `.tooltip()` |
|
||||||
| `indicator.rs` | 59 | `Marker`/`Badge`, or keep if neither fits |
|
| `indicator.rs` | 59 | `marker::Marker` / `badge::Badge`; the custom module is deleted either way |
|
||||||
| `window_ext.rs` | 90 | `gpui_kit::component::WindowExt` |
|
| `window_ext.rs` | 90 | `gpui_kit::component::WindowExt` |
|
||||||
|
|
||||||
## 4. Phase A — GPUI-Kit migration
|
## 4. Phase A — GPUI-Kit migration
|
||||||
@@ -102,6 +111,10 @@ crates.
|
|||||||
installs the framework `Root` (dialog, sheet, notification and tooltip
|
installs the framework `Root` (dialog, sheet, notification and tooltip
|
||||||
layers). Delete `ui::Root` and its layers; `workspace::init` stays as the
|
layers). Delete `ui::Root` and its layers; `workspace::init` stays as the
|
||||||
window's content view.
|
window's content view.
|
||||||
|
- Register a combined `AssetSource` at app construction: coop's existing
|
||||||
|
per-platform source for `assets/brand` and images, with
|
||||||
|
`gpui_kit::assets::Assets` as the fallback for the component icon bundle
|
||||||
|
(embedded on desktop; CDN-on-demand on wasm).
|
||||||
- `TitlebarOptions` / client-side decoration setup stays coop's
|
- `TitlebarOptions` / client-side decoration setup stays coop's
|
||||||
(`CLIENT_SIDE_DECORATION_*`, `TABBAR_HEIGHT` move to `ui`).
|
(`CLIENT_SIDE_DECORATION_*`, `TABBAR_HEIGHT` move to `ui`).
|
||||||
- Keep `bind_keys` **before** `set_menus` (guide rule); coop already does.
|
- Keep `bind_keys` **before** `set_menus` (guide rule); coop already does.
|
||||||
@@ -112,10 +125,12 @@ Replace one family at a time; consumers update in the same PR:
|
|||||||
|
|
||||||
1. **Deps + bootstrap** (above). Custom components still work alongside the
|
1. **Deps + bootstrap** (above). Custom components still work alongside the
|
||||||
framework Root.
|
framework Root.
|
||||||
2. **Icons** — introduce the `ui::icon` shim so later slices see kit icons
|
2. **Icons** — rewrite every icon call site onto kit `Icon`/`IconName` and
|
||||||
through the old call sites (see §4.3).
|
delete `ui::icon` in the same PR (see §4.3). Mechanical churn: one Lucide
|
||||||
|
target per coop variant, `Icon::path` for brand marks; doing it early
|
||||||
|
settles the imports for all later slices.
|
||||||
3. **Small controls** — Button, Switch, Kbd, GroupBox, Avatar, Tooltip,
|
3. **Small controls** — Button, Switch, Kbd, GroupBox, Avatar, Tooltip,
|
||||||
Indicator, Popover.
|
Popover; Indicator → `Marker`/`Badge`.
|
||||||
4. **Menu** — PopupMenu/DropdownMenu/ContextMenu (+ the popup-menu actions
|
4. **Menu** — PopupMenu/DropdownMenu/ContextMenu (+ the popup-menu actions
|
||||||
already imported from `gpui_base::actions`).
|
already imported from `gpui_base::actions`).
|
||||||
5. **Input** — Input/InputState/Textarea; port the chat composer, dialog
|
5. **Input** — Input/InputState/Textarea; port the chat composer, dialog
|
||||||
@@ -124,26 +139,30 @@ Replace one family at a time; consumers update in the same PR:
|
|||||||
`push_notification`; port the settings, relays, profile, new-chat,
|
`push_notification`; port the settings, relays, profile, new-chat,
|
||||||
import… dialogs; the custom footers move to the Dialog footer API.
|
import… dialogs; the custom footers move to the Dialog footer API.
|
||||||
7. **Scroll + Resizable + Tab** — panels and the workspace tab strip.
|
7. **Scroll + Resizable + Tab** — panels and the workspace tab strip.
|
||||||
8. **Sidebar/Nav** — Sidebar family (or keep composites, per the table).
|
8. **Sidebar/Nav** — port the nav onto `sidebar::{Sidebar, SidebarGroup,
|
||||||
|
SidebarMenu, …}` and delete `nav.rs`/`nav_item.rs` in the same PR.
|
||||||
9. **Title bar** — kit `TitleBar` + traffic-light handling.
|
9. **Title bar** — kit `TitleBar` + traffic-light handling.
|
||||||
10. **Dock** — the biggest single item (805 + 205 lines, `dock::add`
|
10. **Dock** — the biggest single item (805 + 205 lines, `dock::add`
|
||||||
registry, `DockPlacement`). Port panels onto `DockArea`; do it last so
|
registry, `DockPlacement`). Port panels onto `DockArea`; do it last so
|
||||||
the panels it hosts are already kit-based.
|
the panels it hosts are already kit-based.
|
||||||
11. **Message + Markdown** — TextView::markdown; Message/Bubble where they
|
11. **Message + Markdown** — TextView::markdown; port chat rows onto
|
||||||
fit, otherwise keep `ui::message` as an app composite (it is domain
|
`Message`/`Bubble`/`MessageGroup` + `MessageScroller`. Chat-specific
|
||||||
layout, allowed by the guides' app-component layer).
|
composition (author grouping, date separators, receipts) is app code in
|
||||||
12. **Cleanup** — delete the replaced modules; decide what `crates/ui` still
|
`chat_ui`, built from kit elements — `crates/ui` keeps no message
|
||||||
is (see §4.4).
|
component.
|
||||||
|
12. **Cleanup** — delete the replaced modules; `crates/ui` ends as a
|
||||||
|
utilities-only crate (see §4.4).
|
||||||
|
|
||||||
### 4.3 Icons
|
### 4.3 Icons
|
||||||
|
|
||||||
coop's `IconName` has 128 variants backed by `assets/icons/*.svg`; the kit's
|
No mapping shim and no coop `IconName` enum: every call site uses the kit's
|
||||||
`IconName` (Lucide) has 106. Keep `ui::icon` as a mapping module: a
|
`Icon` + `IconName` (Lucide) directly. During slice 2, give each of coop's
|
||||||
coop-`IconName` enum (same variant names) that resolves to the kit `IconName`
|
128 variants a Lucide target — exact equivalent where one exists, nearest
|
||||||
where a Lucide equivalent exists, and to a custom asset path (coop's bundled
|
match otherwise, accepting the visual difference. The only coop-owned SVGs
|
||||||
SVGs) where it doesn't (brand marks, a few specials). Most `Icon::new(...)`
|
that survive are true brand/product marks under `assets/brand`, rendered
|
||||||
call sites then keep compiling with import changes only. Delete
|
through the kit element with `Icon::path("brand/….svg")` (the kit `Icon`
|
||||||
`assets/icons` entries that get Lucide equivalents; keep `assets/brand`.
|
accepts any asset path). Delete `assets/icons` entirely once the last call
|
||||||
|
site is mapped.
|
||||||
|
|
||||||
### 4.4 Theme removal
|
### 4.4 Theme removal
|
||||||
|
|
||||||
@@ -188,11 +207,14 @@ call sites then keep compiling with import changes only. Delete
|
|||||||
`colors.rs`, `palette.rs`, `brand.rs`, `appearance.rs`, `paint.rs`,
|
`colors.rs`, `palette.rs`, `brand.rs`, `appearance.rs`, `paint.rs`,
|
||||||
`color.rs`, `syntax.rs`, `notification.rs`, `scrollbar_mode.rs`,
|
`color.rs`, `syntax.rs`, `notification.rs`, `scrollbar_mode.rs`,
|
||||||
`platform_kind.rs`;
|
`platform_kind.rs`;
|
||||||
- move to `crates/ui` unchanged: `typography.rs` (`TextStyle`/`Typeset`,
|
move to `crates/ui` unchanged: `typography.rs` (`TextStyle`/`Typeset`,
|
||||||
~200 call sites — retained deliberately as coop's type ladder),
|
~200 call sites — retained deliberately as coop's type ladder),
|
||||||
`layout.rs` (spacing constants, radius accessors), `geometry.rs`
|
`layout.rs` (spacing constants, radius accessors), `geometry.rs`
|
||||||
(`Edges`/`Side`/`AxisExt`), and the three `CLIENT_SIDE_DECORATION_*`
|
(`Edges`/`Side`/`AxisExt`), and the three `CLIENT_SIDE_DECORATION_*`
|
||||||
constants;
|
constants;
|
||||||
|
- end state: `crates/ui` is utilities-only — `motion.rs`, `typography.rs`,
|
||||||
|
`layout.rs`, `geometry.rs`, the CSD constants and the combined asset
|
||||||
|
source. Every element module is deleted; nothing custom is maintained;
|
||||||
- `AppearanceMode` (System/Light/Dark, serde-persisted) moves into
|
- `AppearanceMode` (System/Light/Dark, serde-persisted) moves into
|
||||||
`crates/settings`.
|
`crates/settings`.
|
||||||
- The gpui-base projection coop did in `sync_base` is now the framework's job
|
- The gpui-base projection coop did in `sync_base` is now the framework's job
|
||||||
@@ -262,7 +284,11 @@ to native targets; on web, apply the fallback preset (or extend
|
|||||||
- dock panels move, split and zoom; sidebar resizes; scrollbars behave in
|
- dock panels move, split and zoom; sidebar resizes; scrollbars behave in
|
||||||
Hover/Always/Scrolling modes;
|
Hover/Always/Scrolling modes;
|
||||||
- markdown code blocks render through `TextView` with syntax colors from
|
- markdown code blocks render through `TextView` with syntax colors from
|
||||||
`Theme.highlight_theme`.
|
`Theme.highlight_theme`;
|
||||||
|
- every icon renders from the kit Lucide bundle, and brand marks render
|
||||||
|
via `Icon::path` on desktop and web (on wasm the kit bundle is fetched
|
||||||
|
from CDN on demand; coop brand assets still come from coop's own
|
||||||
|
source).
|
||||||
- End of Phase B:
|
- End of Phase B:
|
||||||
- macOS: OS light/dark follows; pinned modes; accent changes picked up at
|
- macOS: OS light/dark follows; pinned modes; accent changes picked up at
|
||||||
next launch (documented limitation — no `watch` feature);
|
next launch (documented limitation — no `watch` feature);
|
||||||
@@ -276,11 +302,11 @@ to native targets; on web, apply the fallback preset (or extend
|
|||||||
|
|
||||||
| Risk | Mitigation |
|
| Risk | Mitigation |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Scale: ~8.7k lines of custom UI, ~140 `ui::` imports, ~340 token reads | Slices in §4.2 each compile; `crates/ui` acts as the facade during the migration so consumer churn is incremental |
|
| Scale: ~8.7k lines of custom UI, ~140 `ui::` imports, ~340 token reads | Slices in §4.2 each compile; `crates/ui` acts as the facade during the migration so consumer churn is incremental, then shrinks to utilities (§4.4) |
|
||||||
| Dock port (largest, most stateful) | Scheduled last; panels are kit-based by then; DockArea owns layout state coop currently hand-rolls |
|
| Dock port (largest, most stateful) | Scheduled last; panels are kit-based by then; DockArea owns layout state coop currently hand-rolls |
|
||||||
| gpui-component on wasm | Spike in §6 before committing; fallback would be staying on 0.7.1 desktop-only and parking the web target |
|
| gpui-component on wasm | Spike in §6 before committing; fallback would be staying on 0.7.1 desktop-only and parking the web target |
|
||||||
| Visual identity changes (shadcn-style stock palette in Phase A) | Accepted — requirement says the current palette need not survive; Phase B replaces it with native themes anyway |
|
| Visual identity changes (shadcn-style stock palette in Phase A; kit Message/Sidebar look replacing coop's chat/nav styling) | Accepted — requirement says the current palette need not survive; Phase B replaces it with native themes anyway |
|
||||||
| Icon gaps (coop 128 vs Lucide 106) | Mapping shim keeps coop names; unmatched variants fall back to bundled SVGs |
|
| Icon gaps (coop 128 vs Lucide 106) | Nearest-Lucide target per variant in slice 2; only true brand marks stay as coop assets via `Icon::path` |
|
||||||
| API drift between coop's wrappers and the kit (e.g. `Sizable`, `Disableable`, callback shapes) | Per the coding guides: never invent APIs; verify each component page / source signature during its slice |
|
| API drift between coop's wrappers and the kit (e.g. `Sizable`, `Disableable`, callback shapes) | Per the coding guides: never invent APIs; verify each component page / source signature during its slice |
|
||||||
| `TextStyle` ladder is a deliberate holdout from rem-based text | Documented exception; sizes are absolute points and don't claim to zoom. Revisit only if the kit's text scale is adopted later |
|
| `TextStyle` ladder is a deliberate holdout from rem-based text | Documented exception; sizes are absolute points and don't claim to zoom. Revisit only if the kit's text scale is adopted later |
|
||||||
| native-theme-gpui version coupling | Pin `gpui-kit = "=0.7.1"`-era set (0.7.1, gpui-pre =0.3.8) matching the connector's verified table; bump all together |
|
| native-theme-gpui version coupling | Pin `gpui-kit = "=0.7.1"`-era set (0.7.1, gpui-pre =0.3.8) matching the connector's verified table; bump all together |
|
||||||
|
|||||||
Reference in New Issue
Block a user