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
|
||||
> connector already projects native themes onto gpui-component's `Theme`, and
|
||||
> 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
|
||||
|
||||
@@ -42,6 +49,8 @@ graph LR
|
||||
components and moves all color reads onto gpui-component's `Theme`
|
||||
(`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.
|
||||
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
|
||||
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}` |
|
||||
| `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` |
|
||||
| `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` |
|
||||
| `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 |
|
||||
| `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` |
|
||||
| `tab/` | 385 | `tab::{Tab, TabBar, Tabs}` |
|
||||
| `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 |
|
||||
| `switch.rs` | 157 | `switch::Switch` |
|
||||
| `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` |
|
||||
| `scroll/` | ~124 | `scroll::{Scrollbar, Scrollable}` |
|
||||
| `resizable/` | 31 | `resizable::{h_resizable, v_resizable, resizable_panel}` |
|
||||
| `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` |
|
||||
|
||||
## 4. Phase A — GPUI-Kit migration
|
||||
@@ -102,6 +111,10 @@ crates.
|
||||
installs the framework `Root` (dialog, sheet, notification and tooltip
|
||||
layers). Delete `ui::Root` and its layers; `workspace::init` stays as the
|
||||
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
|
||||
(`CLIENT_SIDE_DECORATION_*`, `TABBAR_HEIGHT` move to `ui`).
|
||||
- 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
|
||||
framework Root.
|
||||
2. **Icons** — introduce the `ui::icon` shim so later slices see kit icons
|
||||
through the old call sites (see §4.3).
|
||||
2. **Icons** — rewrite every icon call site onto kit `Icon`/`IconName` and
|
||||
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,
|
||||
Indicator, Popover.
|
||||
Popover; Indicator → `Marker`/`Badge`.
|
||||
4. **Menu** — PopupMenu/DropdownMenu/ContextMenu (+ the popup-menu actions
|
||||
already imported from `gpui_base::actions`).
|
||||
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,
|
||||
import… dialogs; the custom footers move to the Dialog footer API.
|
||||
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.
|
||||
10. **Dock** — the biggest single item (805 + 205 lines, `dock::add`
|
||||
registry, `DockPlacement`). Port panels onto `DockArea`; do it last so
|
||||
the panels it hosts are already kit-based.
|
||||
11. **Message + Markdown** — TextView::markdown; Message/Bubble where they
|
||||
fit, otherwise keep `ui::message` as an app composite (it is domain
|
||||
layout, allowed by the guides' app-component layer).
|
||||
12. **Cleanup** — delete the replaced modules; decide what `crates/ui` still
|
||||
is (see §4.4).
|
||||
11. **Message + Markdown** — TextView::markdown; port chat rows onto
|
||||
`Message`/`Bubble`/`MessageGroup` + `MessageScroller`. Chat-specific
|
||||
composition (author grouping, date separators, receipts) is app code in
|
||||
`chat_ui`, built from kit elements — `crates/ui` keeps no message
|
||||
component.
|
||||
12. **Cleanup** — delete the replaced modules; `crates/ui` ends as a
|
||||
utilities-only crate (see §4.4).
|
||||
|
||||
### 4.3 Icons
|
||||
|
||||
coop's `IconName` has 128 variants backed by `assets/icons/*.svg`; the kit's
|
||||
`IconName` (Lucide) has 106. Keep `ui::icon` as a mapping module: a
|
||||
coop-`IconName` enum (same variant names) that resolves to the kit `IconName`
|
||||
where a Lucide equivalent exists, and to a custom asset path (coop's bundled
|
||||
SVGs) where it doesn't (brand marks, a few specials). Most `Icon::new(...)`
|
||||
call sites then keep compiling with import changes only. Delete
|
||||
`assets/icons` entries that get Lucide equivalents; keep `assets/brand`.
|
||||
No mapping shim and no coop `IconName` enum: every call site uses the kit's
|
||||
`Icon` + `IconName` (Lucide) directly. During slice 2, give each of coop's
|
||||
128 variants a Lucide target — exact equivalent where one exists, nearest
|
||||
match otherwise, accepting the visual difference. The only coop-owned SVGs
|
||||
that survive are true brand/product marks under `assets/brand`, rendered
|
||||
through the kit element with `Icon::path("brand/….svg")` (the kit `Icon`
|
||||
accepts any asset path). Delete `assets/icons` entirely once the last call
|
||||
site is mapped.
|
||||
|
||||
### 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`,
|
||||
`color.rs`, `syntax.rs`, `notification.rs`, `scrollbar_mode.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),
|
||||
`layout.rs` (spacing constants, radius accessors), `geometry.rs`
|
||||
(`Edges`/`Side`/`AxisExt`), and the three `CLIENT_SIDE_DECORATION_*`
|
||||
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
|
||||
`crates/settings`.
|
||||
- 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
|
||||
Hover/Always/Scrolling modes;
|
||||
- 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:
|
||||
- macOS: OS light/dark follows; pinned modes; accent changes picked up at
|
||||
next launch (documented limitation — no `watch` feature);
|
||||
@@ -276,11 +302,11 @@ to native targets; on web, apply the fallback preset (or extend
|
||||
|
||||
| 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 |
|
||||
| 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 |
|
||||
| Icon gaps (coop 128 vs Lucide 106) | Mapping shim keeps coop names; unmatched variants fall back to bundled SVGs |
|
||||
| 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) | 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 |
|
||||
| `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 |
|
||||
|
||||
Reference in New Issue
Block a user