Add ADR for extracting shared UI code

ADR 2 now only covers how the apps consume shared code, so its notes
on the extraction strategy move here. All three root ADRs are accepted
with this patch.
This commit is contained in:
Rūdolfs Ošiņš
2026-10-29 16:06:13 +01:00
parent d81d8c10b3
commit 84995442a5
3 changed files with 60 additions and 9 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ Date: 2026-10-21
## Status
Proposed
Accepted
## Context
+3 -8
View File
@@ -4,13 +4,13 @@ Date: 2026-10-21
## Status
Proposed
Accepted
## Context
Desktop and explorer have copied a lot of front-end code from each other.
Desktop is the most developed of the two and already on Svelte 5, so it is the
source we extract shared code from.
This ADR decides how both apps consume shared code; ADR 3 decides what moves
into it and in which shape.
We also considered consuming `shared/ui` as a plain source folder and as a
local `file:` dependency. Both need workarounds in each app's Vite and
@@ -29,9 +29,6 @@ Shared stylesheets and fonts live in `shared/ui/public`. A Vite plugin from the
package serves them next to each app's public directory in dev and adds them
to the build, so the apps keep their `<link>` tags, marked `vite-ignore`.
Shared code must not import `@tauri-apps/*`, `@bindings` or `@http-client`.
It takes plain props, and each app adapts its own data to them.
## Consequences
- The apps share one dependency tree. Shared code gets a single copy of
@@ -42,5 +39,3 @@ It takes plain props, and each app adapts its own data to them.
- Installs and builds start from the repository root. Working on one app means
installing it with `-w`, and Nix, Docker and CI have to use the root
lockfile.
- Shared components are written with runes. Explorer can render them while it
still uses legacy syntax, at the cost of some friction where the two meet.
+56
View File
@@ -0,0 +1,56 @@
# 3. Extracting shared front-end code
Date: 2026-10-27
## Status
Accepted
## Context
ADR 2 decides how the apps consume shared code: through the `@radicle-gui/ui`
package in a root npm workspace. It doesn't decide what goes into the package,
in what order, or in which shape. Desktop and explorer share a lot of UI, but
they serve different use cases. Explorer is a public web interface: anyone can
open it in a browser and browse repositories across many nodes, and it only
reads for now. Desktop is a personal app that works with one person's own node,
and both reads and writes.
## Decision
- New functionality that is meant to be reused lands in `shared/ui` first and
is then used in both apps.
- Existing features move over gradually, one patch per feature, so that the
related components of a feature move together.
- Functionality specific to one app stays in that app.
- Existing code is extracted from desktop and reused in explorer. When the two
apps' copies differ, desktop's version is the starting point and explorer
adapts to it.
- Svelte 5 is the goal. Shared components use runes, and explorer moves its
code that uses them to runes as it adopts them, instead of in one big
migration.
- Shared components don't know where their data comes from: they import
nothing from either app, and each app adapts its own data to their props.
They can offer both reading and writing; explorer uses only the reading
side for now. Data comes in as props and changes go out through callbacks,
following the API guidelines in `shared/ui/AGENTS.md`.
- Shared prop types stay narrow and use heartwood's field names and meanings,
so that the apps' own types can converge on heartwood without churning the
components. Their shapes can differ where the components need it. Generating
both apps' types from heartwood's Rust types is the long-term path, and part
of the later decision on a shared core.
- Design tokens, stylesheets and fonts are shared through `shared/ui/public`,
and the apps stop keeping their own copies.
- Unit tests for shared code live in `shared/ui/tests`, and every change to
`shared/ui` runs the checks of both apps.
- Extraction starts with visual components that both apps can use as they are.
How to share larger pieces such as whole views is not decided yet; one
option is to extract their business logic into a shared core later.
## Consequences
- Explorer mixes legacy and runes components until its migration is done.
- Every extraction touches both apps, so it needs both apps checked.
- Shared components can carry write paths that explorer doesn't use yet.
- Views stay duplicated between the apps until a later ADR decides how to
share them.