Repository navigation
feat(ui): light redesign — Overview, Tokens, DAR Manager, and live metrics - #300
Merged
Merged
Conversation
…kens)
Integrates the UX redesign for two surfaces, built on the existing Carbon
Slate token system (W.* CSS vars) so both light and dark themes come for
free — the app already defaults to light.
Tokens screen:
- The four KPI cards become one hairline-split figure-strip that reads as
a single object, with the mockup's sub-labels ('minted, less burns',
'parties with a balance', ...). The declared-supply note and the
'Mint N remaining' CTA are preserved.
- Action row: Transfer is the primary; Mint/Faucet/Accept follow; Burn is
set apart last behind a divider as the destructive action. Allocate
moves off the row (still reachable via the Allocations tab).
- The split 'Holder distribution' + 'Holdings' tables merge into one
nested Holders card: each party expands to its holding-contract UTXOs
with a locked badge. CLI-hint footers on the list and the Holders card.
- Fix: expanding a holder crashed when the contracts response was
undefined (empty/204) — guarded (contracts ?? []).
Instance Overview:
- Rebuilt into a single 'wire your app' hub (new InstanceOverview.tsx,
folding in the old InstanceDetail + ContainerHealth + DeveloperSetup):
header + action bar, Overview/Activity/Snapshots tabs, a throughput
sparkline, an Endpoints|Containers pair in fixed-height scroll boxes,
and JWT + App-config panels.
- Two states: with observability on, the throughput chart shows; without
it, that region is gone and a strip offers 'Enable monitoring'. Only
data that exists is shown — throughput is gated on monitoring, and the
unpopulated p99/ACS/CPU/memory tiles are omitted (TODO to wire later)
rather than rendered blank. Endpoint reachability is shown only for the
probed http UIs; other services render a neutral '—', never a fabricated
'reachable'.
- Per-container restart is kept (the CLI has 'container restart', so the
Web UI must too) as a per-row action in the redesigned panel; the
Metrics nav row shows an 'off' tag when observability is off.
…pshots tab Addresses redesign follow-ups + a reported render bug: - Per-container restart is kept in the redesigned Containers panel (the CLI has 'container restart', so the Web UI must too): a per-row action column with confirm + busy state + error line. - Metrics nav row shows an 'off' tag when the instance was started without the observability profile (a shell-level fetchMetricsSummary probe). - Snapshots tab rebuilt to the mockup's two-card layout (Take a snapshot | Restore). Removes the stray empty bordered box (the old component's self-separator borderTop/marginTop, left over from the standalone layout) and the redundant Panel wrapper; success now uses the semantic ok pair instead of the accent.
…emory) The redesigned Overview showed only the throughput chart — the mockup's KPI rail was omitted because CPU/mem/p99 had no data source. This wires real data instead of leaving it blank. Backend: a docker-stats collector (internal/localnet/containers/stats.go) runs 'docker stats --no-stream' for the project's containers and parses CPUPerc + MemUsage; the containers handler sums them onto ContainersResponse as cpu_percent / mem_used_bytes / mem_limit_bytes (pointers — best-effort, short timeout, nil when unsampled so the UI shows an em-dash, never a fabricated zero). CPU/memory come from docker, so they're available whenever the instance is running — no observability profile needed. Frontend: reinstate the throughput | rail two-column grid. The rail shows Latency avg (real; p99 is nil on 0.6.x so we fetch the avg-latency series), CPU %, and Memory 'X.X / Y.Y GB'. Active contracts is omitted — no honest ACS-count metric exists. The monitoring-off strip now also shows the real CPU/Memory (docker-sourced), replacing the earlier 'intentionally absent'. Parser unit-tested (parseSize/parsePercent/parseStats); live docker-stats verification pending (Docker down locally) — verified end-to-end against the mock.
…views DAR Manager restyled to the redesign mockup (DARScreen.tsx + a DARPackageTree onLoaded callback so the drawer's Structure summary + size reuse one inspect fetch): 'Packages' heading + census, segmented role switcher, single upload bar with inline vet-on-upload, App-DARs/All-packages tabs, accent-active package rows, watch mode in the table footer, and a detail drawer that opens only on selection (Package id / Vetting / Structure / Compare). Net-new: name/id search, refresh, drawer close (X) + Escape, drawer .dalf size. All existing logic preserved; clickable rows now role=button + keyboard-operable. Two items deferred as needs-backend (not fabricated): an 'Uploaded' relative-time column and a drawer Download button — no upload_at field / no Web UI download route today (the CLI has 'dar download'; parity gap noted). Fix: creating an instance rendered BOTH the bring-up progress panel AND the full running Overview (throughput / tabs / KPI rail) stacked below it. While an instance is 'creating', show only the bring-up panel — the Overview takes over once the status flips. Regression test added.
zheli
marked this pull request as ready for review
August 7, 2026 09:27
Restore the frontend/mock Vite mock API removed in 9589e77 and update it to the redesigned surface. The mock was deleted in the same commit that added the token V2 workflows, so it never caught up: the identity switcher, allocations, and pending-offers tabs were silently empty or 404, the demo/create responses were stale shapes, and the metrics summary fixture predated the real KPI rail. - Re-add dev:mock/mock:seed scripts and the conditional mock plugin. - Restore the mock data docs section in CONTRIBUTING.md. - Add GET /api/tokens/identity, /allocations, /transfers routes and POST /{symbol}/allocate + allocations/{id}/withdraw|cancel, wired to new store fixtures so seeded data is served. - Fix POST /api/tokens (full TokenRef) and /demo (DemoResult) shapes; fix /transfer to return transfer_instruction_id + settled. - Update metrics-summary fixture to the current MetricsSummary contract. - Extend mock:seed targets with the V2 token endpoints and cover the new routes in router/seed tests.
TCP RST from a slammed-shut connection surfaces as ECONNRESET rather than io.EOF depending on close timing, causing TestDefaultUIProbe_EmptyReplyIsUnreachable to flake on Linux CI.
- stats.go: parseSize returns 0 for unknown unit suffixes instead of silently mis-scaling them as bytes. - instances.go: extract the docker-stats sum/nil-vs-set logic into a pure aggregateContainerStats helper and unit-test the "never a fabricated zero" contract directly. - ui_reachability_test.go: pin the ECONNRESET/EOF -> "empty reply" classification with a direct test, independent of the OS-timing race that made TestDefaultUIProbe_EmptyReplyIsUnreachable flake. - InstanceOverview.test.tsx: port 3 behaviors dropped when InstanceDetail.test.tsx was deleted during the redesign consolidation (fetch-error line, re-fetch on name change, neutral error banner for non-stop action failures).
zheli
added a commit
that referenced
this pull request
Aug 10, 2026
…trics (#300) * feat(ui): redesign Tokens + instance Overview (light-first, shared tokens) Integrates the UX redesign for two surfaces, built on the existing Carbon Slate token system (W.* CSS vars) so both light and dark themes come for free — the app already defaults to light. Tokens screen: - The four KPI cards become one hairline-split figure-strip that reads as a single object, with the mockup's sub-labels ('minted, less burns', 'parties with a balance', ...). The declared-supply note and the 'Mint N remaining' CTA are preserved. - Action row: Transfer is the primary; Mint/Faucet/Accept follow; Burn is set apart last behind a divider as the destructive action. Allocate moves off the row (still reachable via the Allocations tab). - The split 'Holder distribution' + 'Holdings' tables merge into one nested Holders card: each party expands to its holding-contract UTXOs with a locked badge. CLI-hint footers on the list and the Holders card. - Fix: expanding a holder crashed when the contracts response was undefined (empty/204) — guarded (contracts ?? []). Instance Overview: - Rebuilt into a single 'wire your app' hub (new InstanceOverview.tsx, folding in the old InstanceDetail + ContainerHealth + DeveloperSetup): header + action bar, Overview/Activity/Snapshots tabs, a throughput sparkline, an Endpoints|Containers pair in fixed-height scroll boxes, and JWT + App-config panels. - Two states: with observability on, the throughput chart shows; without it, that region is gone and a strip offers 'Enable monitoring'. Only data that exists is shown — throughput is gated on monitoring, and the unpopulated p99/ACS/CPU/memory tiles are omitted (TODO to wire later) rather than rendered blank. Endpoint reachability is shown only for the probed http UIs; other services render a neutral '—', never a fabricated 'reachable'. - Per-container restart is kept (the CLI has 'container restart', so the Web UI must too) as a per-row action in the redesigned panel; the Metrics nav row shows an 'off' tag when observability is off. * fix(ui): restore per-container restart + metrics off-tag; rebuild Snapshots tab Addresses redesign follow-ups + a reported render bug: - Per-container restart is kept in the redesigned Containers panel (the CLI has 'container restart', so the Web UI must too): a per-row action column with confirm + busy state + error line. - Metrics nav row shows an 'off' tag when the instance was started without the observability profile (a shell-level fetchMetricsSummary probe). - Snapshots tab rebuilt to the mockup's two-card layout (Take a snapshot | Restore). Removes the stray empty bordered box (the old component's self-separator borderTop/marginTop, left over from the standalone layout) and the redundant Panel wrapper; success now uses the semantic ok pair instead of the accent. * feat(overview): real KPI rail via docker stats (Latency avg / CPU / Memory) The redesigned Overview showed only the throughput chart — the mockup's KPI rail was omitted because CPU/mem/p99 had no data source. This wires real data instead of leaving it blank. Backend: a docker-stats collector (internal/localnet/containers/stats.go) runs 'docker stats --no-stream' for the project's containers and parses CPUPerc + MemUsage; the containers handler sums them onto ContainersResponse as cpu_percent / mem_used_bytes / mem_limit_bytes (pointers — best-effort, short timeout, nil when unsampled so the UI shows an em-dash, never a fabricated zero). CPU/memory come from docker, so they're available whenever the instance is running — no observability profile needed. Frontend: reinstate the throughput | rail two-column grid. The rail shows Latency avg (real; p99 is nil on 0.6.x so we fetch the avg-latency series), CPU %, and Memory 'X.X / Y.Y GB'. Active contracts is omitted — no honest ACS-count metric exists. The monitoring-off strip now also shows the real CPU/Memory (docker-sourced), replacing the earlier 'intentionally absent'. Parser unit-tested (parseSize/parsePercent/parseStats); live docker-stats verification pending (Docker down locally) — verified end-to-end against the mock. * feat(ui): DAR Manager re-style; fix creating instance showing merged views DAR Manager restyled to the redesign mockup (DARScreen.tsx + a DARPackageTree onLoaded callback so the drawer's Structure summary + size reuse one inspect fetch): 'Packages' heading + census, segmented role switcher, single upload bar with inline vet-on-upload, App-DARs/All-packages tabs, accent-active package rows, watch mode in the table footer, and a detail drawer that opens only on selection (Package id / Vetting / Structure / Compare). Net-new: name/id search, refresh, drawer close (X) + Escape, drawer .dalf size. All existing logic preserved; clickable rows now role=button + keyboard-operable. Two items deferred as needs-backend (not fabricated): an 'Uploaded' relative-time column and a drawer Download button — no upload_at field / no Web UI download route today (the CLI has 'dar download'; parity gap noted). Fix: creating an instance rendered BOTH the bring-up progress panel AND the full running Overview (throughput / tabs / KPI rail) stacked below it. While an instance is 'creating', show only the bring-up panel — the Overview takes over once the status flips. Regression test added. * feat(ui): complete light redesign and token V2 workflows * fix(ui): remove instance volumes on deletion * fix(ui): wire live instance summaries * feat(frontend): restore mock server and bring it in sync with token V2 Restore the frontend/mock Vite mock API removed in 9589e77 and update it to the redesigned surface. The mock was deleted in the same commit that added the token V2 workflows, so it never caught up: the identity switcher, allocations, and pending-offers tabs were silently empty or 404, the demo/create responses were stale shapes, and the metrics summary fixture predated the real KPI rail. - Re-add dev:mock/mock:seed scripts and the conditional mock plugin. - Restore the mock data docs section in CONTRIBUTING.md. - Add GET /api/tokens/identity, /allocations, /transfers routes and POST /{symbol}/allocate + allocations/{id}/withdraw|cancel, wired to new store fixtures so seeded data is served. - Fix POST /api/tokens (full TokenRef) and /demo (DemoResult) shapes; fix /transfer to return transfer_instruction_id + settled. - Update metrics-summary fixture to the current MetricsSummary contract. - Extend mock:seed targets with the V2 token endpoints and cover the new routes in router/seed tests. * fix(localnet): classify ECONNRESET as empty-reply in UI probe TCP RST from a slammed-shut connection surfaces as ECONNRESET rather than io.EOF depending on close timing, causing TestDefaultUIProbe_EmptyReplyIsUnreachable to flake on Linux CI. * fix(ui): address code review — parser guard + missing test coverage - stats.go: parseSize returns 0 for unknown unit suffixes instead of silently mis-scaling them as bytes. - instances.go: extract the docker-stats sum/nil-vs-set logic into a pure aggregateContainerStats helper and unit-test the "never a fabricated zero" contract directly. - ui_reachability_test.go: pin the ECONNRESET/EOF -> "empty reply" classification with a direct test, independent of the OS-timing race that made TestDefaultUIProbe_EmptyReplyIsUnreachable flake. - InstanceOverview.test.tsx: port 3 behaviors dropped when InstanceDetail.test.tsx was deleted during the redesign consolidation (fetch-error line, re-fetch on name change, neutral error banner for non-stop action failures). --------- Co-authored-by: srikanth-bitdynamics <259878899+srikanth-bitdynamics@users.noreply.github.com>
zheli
added a commit
that referenced
this pull request
Aug 19, 2026
…trics (#300) * feat(ui): redesign Tokens + instance Overview (light-first, shared tokens) Integrates the UX redesign for two surfaces, built on the existing Carbon Slate token system (W.* CSS vars) so both light and dark themes come for free — the app already defaults to light. Tokens screen: - The four KPI cards become one hairline-split figure-strip that reads as a single object, with the mockup's sub-labels ('minted, less burns', 'parties with a balance', ...). The declared-supply note and the 'Mint N remaining' CTA are preserved. - Action row: Transfer is the primary; Mint/Faucet/Accept follow; Burn is set apart last behind a divider as the destructive action. Allocate moves off the row (still reachable via the Allocations tab). - The split 'Holder distribution' + 'Holdings' tables merge into one nested Holders card: each party expands to its holding-contract UTXOs with a locked badge. CLI-hint footers on the list and the Holders card. - Fix: expanding a holder crashed when the contracts response was undefined (empty/204) — guarded (contracts ?? []). Instance Overview: - Rebuilt into a single 'wire your app' hub (new InstanceOverview.tsx, folding in the old InstanceDetail + ContainerHealth + DeveloperSetup): header + action bar, Overview/Activity/Snapshots tabs, a throughput sparkline, an Endpoints|Containers pair in fixed-height scroll boxes, and JWT + App-config panels. - Two states: with observability on, the throughput chart shows; without it, that region is gone and a strip offers 'Enable monitoring'. Only data that exists is shown — throughput is gated on monitoring, and the unpopulated p99/ACS/CPU/memory tiles are omitted (TODO to wire later) rather than rendered blank. Endpoint reachability is shown only for the probed http UIs; other services render a neutral '—', never a fabricated 'reachable'. - Per-container restart is kept (the CLI has 'container restart', so the Web UI must too) as a per-row action in the redesigned panel; the Metrics nav row shows an 'off' tag when observability is off. * fix(ui): restore per-container restart + metrics off-tag; rebuild Snapshots tab Addresses redesign follow-ups + a reported render bug: - Per-container restart is kept in the redesigned Containers panel (the CLI has 'container restart', so the Web UI must too): a per-row action column with confirm + busy state + error line. - Metrics nav row shows an 'off' tag when the instance was started without the observability profile (a shell-level fetchMetricsSummary probe). - Snapshots tab rebuilt to the mockup's two-card layout (Take a snapshot | Restore). Removes the stray empty bordered box (the old component's self-separator borderTop/marginTop, left over from the standalone layout) and the redundant Panel wrapper; success now uses the semantic ok pair instead of the accent. * feat(overview): real KPI rail via docker stats (Latency avg / CPU / Memory) The redesigned Overview showed only the throughput chart — the mockup's KPI rail was omitted because CPU/mem/p99 had no data source. This wires real data instead of leaving it blank. Backend: a docker-stats collector (internal/localnet/containers/stats.go) runs 'docker stats --no-stream' for the project's containers and parses CPUPerc + MemUsage; the containers handler sums them onto ContainersResponse as cpu_percent / mem_used_bytes / mem_limit_bytes (pointers — best-effort, short timeout, nil when unsampled so the UI shows an em-dash, never a fabricated zero). CPU/memory come from docker, so they're available whenever the instance is running — no observability profile needed. Frontend: reinstate the throughput | rail two-column grid. The rail shows Latency avg (real; p99 is nil on 0.6.x so we fetch the avg-latency series), CPU %, and Memory 'X.X / Y.Y GB'. Active contracts is omitted — no honest ACS-count metric exists. The monitoring-off strip now also shows the real CPU/Memory (docker-sourced), replacing the earlier 'intentionally absent'. Parser unit-tested (parseSize/parsePercent/parseStats); live docker-stats verification pending (Docker down locally) — verified end-to-end against the mock. * feat(ui): DAR Manager re-style; fix creating instance showing merged views DAR Manager restyled to the redesign mockup (DARScreen.tsx + a DARPackageTree onLoaded callback so the drawer's Structure summary + size reuse one inspect fetch): 'Packages' heading + census, segmented role switcher, single upload bar with inline vet-on-upload, App-DARs/All-packages tabs, accent-active package rows, watch mode in the table footer, and a detail drawer that opens only on selection (Package id / Vetting / Structure / Compare). Net-new: name/id search, refresh, drawer close (X) + Escape, drawer .dalf size. All existing logic preserved; clickable rows now role=button + keyboard-operable. Two items deferred as needs-backend (not fabricated): an 'Uploaded' relative-time column and a drawer Download button — no upload_at field / no Web UI download route today (the CLI has 'dar download'; parity gap noted). Fix: creating an instance rendered BOTH the bring-up progress panel AND the full running Overview (throughput / tabs / KPI rail) stacked below it. While an instance is 'creating', show only the bring-up panel — the Overview takes over once the status flips. Regression test added. * feat(ui): complete light redesign and token V2 workflows * fix(ui): remove instance volumes on deletion * fix(ui): wire live instance summaries * feat(frontend): restore mock server and bring it in sync with token V2 Restore the frontend/mock Vite mock API removed in 9589e77 and update it to the redesigned surface. The mock was deleted in the same commit that added the token V2 workflows, so it never caught up: the identity switcher, allocations, and pending-offers tabs were silently empty or 404, the demo/create responses were stale shapes, and the metrics summary fixture predated the real KPI rail. - Re-add dev:mock/mock:seed scripts and the conditional mock plugin. - Restore the mock data docs section in CONTRIBUTING.md. - Add GET /api/tokens/identity, /allocations, /transfers routes and POST /{symbol}/allocate + allocations/{id}/withdraw|cancel, wired to new store fixtures so seeded data is served. - Fix POST /api/tokens (full TokenRef) and /demo (DemoResult) shapes; fix /transfer to return transfer_instruction_id + settled. - Update metrics-summary fixture to the current MetricsSummary contract. - Extend mock:seed targets with the V2 token endpoints and cover the new routes in router/seed tests. * fix(localnet): classify ECONNRESET as empty-reply in UI probe TCP RST from a slammed-shut connection surfaces as ECONNRESET rather than io.EOF depending on close timing, causing TestDefaultUIProbe_EmptyReplyIsUnreachable to flake on Linux CI. * fix(ui): address code review — parser guard + missing test coverage - stats.go: parseSize returns 0 for unknown unit suffixes instead of silently mis-scaling them as bytes. - instances.go: extract the docker-stats sum/nil-vs-set logic into a pure aggregateContainerStats helper and unit-test the "never a fabricated zero" contract directly. - ui_reachability_test.go: pin the ECONNRESET/EOF -> "empty reply" classification with a direct test, independent of the OS-timing race that made TestDefaultUIProbe_EmptyReplyIsUnreachable flake. - InstanceOverview.test.tsx: port 3 behaviors dropped when InstanceDetail.test.tsx was deleted during the redesign consolidation (fetch-error line, re-fetch on name change, neutral error banner for non-stop action failures). --------- Co-authored-by: srikanth-bitdynamics <259878899+srikanth-bitdynamics@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Completes the light-first Web UI redesign for instance Overview, Tokens, and DAR Manager, and wires real docker-stats KPIs plus live instance summaries. Also tightens token V2 workflows and instance lifecycle behavior (creating view, volume cleanup on delete), and restores the
frontend/mockVite mock API to parity with the redesigned surface.Changes
docker stats(CPU / Memory) plus latency avg; restore per-container restart and Snapshots two-card layoutfrontend/mockmock server +dev:mock/mock:seedscripts removed in9589e77; bring it in sync with the token V2 surface (identity / allocations / pending-offers / allocate routes,DemoResultandTokenRefshapes, currentMetricsSummaryfixture, extendedmock:seedtargets)Test plan
make test— pass (go test ./..., all packages ok)make lint— pass (golangci-lint, 0 issues)28files /248tests, incl. new mock router/seed coverage)scripts/e2e/run-all.sh— blocked in this agent host: LocalNet compose fails with cgroupv2threadedmode (cannot enter cgroupv2 "/sys/fs/cgroup/docker" with domain controllers). Preflight-only cases passed (M1-INST-003,M1-DOC-001,M1-DOC-002); lifecycle cases (M1-UP-*and dependents) could not start containers. Not attributable to this PR’s code. CI on this branch is green for Build/test, Frontend, Lint.Dashboard.test.tsx(“shows only the bring-up panel while an instance is creating”)TokensScreen.test.tsx+DARScreen.test.tsxunit coverageremove_instance_test.go(removeVolumes=true)stats_test.goChecklist
make test,make lint, frontend Vitest); CI green on this PRinternal/localnet/containers0.0% → 19.2% (newstats.go+ tests);handlers52.0% → 51.7%;localnet78.2% → 78.3%;token56.4% → 56.0%;splice78.8% → 79.0%docs/faq.md,docs/tokens.md,docs/troubleshooting.md,docs/versions.md. Website pages are generated fromdocs/viawebsite/scripts/sync-docs.mjs(npm run docs:syncverified; generated pages are not committed)upload_atfor an Uploaded column; CLI hasdar download). NoTODO(#issue)filed yet for those backend-dependent itemsVerification notes
make lintmake testcd frontend && npm testscripts/e2e/run-all.shwebsitedocs syncdocs/ui-redesign-light)