Commit Graph

16 Commits

Author SHA1 Message Date
Josh Lehman a91f1202d9 fix(ui): keep Plugins hub navigation stable (#126061)
* fix(ui): keep Plugins hub navigation stable

* chore: format release validation skill
2026-08-18 16:08:41 -07:00
Peter Steinberger e6a427c493 perf(ui): defer offscreen plugin row rendering (#125585)
Amp-Thread-ID: https://ampcode.com/threads/T-01a01277-59ee-703a-b04d-927a3ba733a1

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 21:50:54 -07:00
Jesse Merhi 47442197a1 feat(ui): review install policy warnings (#120900)
* feat(ui): review install policy warnings

* fix(ui): keep install feedback on runtime plugin
2026-08-15 13:07:02 +10:00
Peter Steinberger f8bca11d77 chore(ui): add dead-CSS audit script and delete unreferenced stylesheet rules (#123178)
* chore(ui): add dead-CSS audit script and delete unreferenced stylesheet rules

* fix(scripts): type-safe AST walking in the dead-CSS audit

* fix(scripts): detect ternary-headed class stems and restore live wizard rules
2026-08-13 14:53:17 -07:00
Peter Steinberger 843017073c refactor(ui): route stylesheet colors through the token layer and gate hex literals (#123156)
Add semantic, presentation, brand, and shared highlight tokens in base.css.
Remove dead fallbacks and consolidate dark/light syntax colors behind tokens.
Enforce color-no-hex for CSS while exempting token definitions and sprite artwork.
2026-08-13 05:36:52 -07:00
Vyctor H. Brzezowski 32ced3053d fix(ui): scope the Control UI cursor convention to app-like display modes (#121258)
* fix(ui): scope the Control UI cursor convention to app-like display modes

The app-chrome cursor convention from #103357/#103411 was applied
unconditionally, so an ordinary browser tab lost the pointer hand on
buttons, menus, tabs, rails, selects and accordion summaries — the only
hover affordance a page owns. The convention is correct for the installed
window the manifest declares ("display": "standalone"), not for every
window the same bundle is served into.

base.css now owns one policy token, --cursor-action, selected by display
mode: pointer by default, the desktop arrow under standalone, minimal-ui
and window-controls-overlay. A low-specificity rule maps generic
actionable controls onto that token, restoring the affordance on the
surfaces #103411 stripped bare, while every component rule that owns a
semantic cursor (not-allowed, disabled, grab, resize, zoom-in, text,
wait) keeps winning without !important.

The 92 cursor: pointer declarations that had drifted back into ui/src
since July now consume the token instead of hardcoding the hand, so they
stop contradicting the policy in an installed window. Real hyperlinks
keep the pointer in every mode. The pre-boot mount fallback repeats the
policy locally because it must render when the bundle fails to load.

Closes #121242

* test(ui): run the cursor policy browser test in the node-driven project

ui/vitest.config.ts routes Playwright-from-Node .browser.test.ts files to the
unit-node project; without registering the new cursor policy test there, the
in-browser chromium project tried to import it and failed on node:fs/playwright.

* fix(ui): keep the desktop arrow in the native app hosts

The macOS dashboard embeds the Control UI in a plain web view, which
reports `display-mode: browser`, so the display-mode-only policy would
have handed it the browser-tab pointer. It already announces itself with
`openclaw-native-macos`/`-nav`/`-web-chrome` on `<html>`, the same markers
`ui/src/styles/layout.css` matches on, so the policy reads those too.
2026-08-09 22:23:00 -03:00
Patrick Erichsen c66ca2fbb2 feat: show ClawHub skill icons in Control UI (#114152) 2026-07-26 14:44:36 -05:00
Peter Steinberger c66c55abfd fix(ui): keep sessions hub tabs stationary (#112039) 2026-07-21 00:57:24 -07:00
Peter Steinberger 74880cb56f feat(ui): manage MCP servers directly from Settings → MCP (#110654)
* feat(ui): manage MCP servers directly on the Settings MCP page

* refactor(ui): mcp config section owned by the MCP settings page only

* chore(ui): drop test-only McpServersCard export for knip
2026-07-18 12:54:05 +01:00
Peter Steinberger 31314920ce improve(ui): plugins hub hierarchy, settings section spacing, and grid-aligned secret inputs (#110482)
* improve(ui): align settings section headers, dedupe plugin row status pills, clean hub tab strip

* improve(ui): hub tabs as page nav, one-row plugins toolbar, honest section spacing, inset secret-input reveal
2026-07-18 11:57:36 +01:00
Patrick Erichsen 55bb6cfa2e feat(control-ui): proxy plugin catalog icons (#109510) 2026-07-16 20:31:27 -07:00
Peter Steinberger 4733a59f26 feat(ui): web delights — empty-state mascots, first-reply confetti, composer drag-catch (#109118)
* feat(ui): web delights — empty-state mascots, first-reply confetti, composer drag-catch

Three mascot-powered moments in the Control UI: the plugins page and
channels hub show a sleepy Clawd when truly empty and a curious one on
a search miss; the very first successful assistant reply in a browser
earns a single confetti burst in the mascot palette (localStorage
once-flag, reduced-motion aware); and dragging files over the new-
session composer makes the welcome mascot tease with an open mouth,
then snap a catch on drop — upload behavior untouched.

* fix(ui): satisfy strict types and knip for the confetti module

Tuple index under noUncheckedIndexedAccess gets an anchored fallback,
the once-flag helper stays module-internal (knip counts only production
consumers), and its coverage moves to the public fireFirstReplyConfetti
path in jsdom using the shared storage mock.
2026-07-16 09:02:32 -07:00
Peter Steinberger 2ac723282c refactor(ui): unified settings design language across all Control UI settings surfaces (#106470)
* feat(ui): add settings design-language foundation (tokens, settings.css, helpers)

* refactor(ui): move settings workspace shell styles into settings.css

* refactor(ui): migrate all settings surfaces to the unified settings design language

Every settings surface (General quick+advanced schema form, Appearance,
Communications, Automation, MCP, Infrastructure, AI Agents, Channels,
Connection, About, Profile, Model Providers, Plugins, Skills, Skill
Workshop chrome, Devices, Worktrees, Debug, Logs, Activity, Automations,
Sessions, Usage chrome) now renders through the settings-ui helpers and
settings.css: sections as plain uppercase headings outside one flat
group surface, hairline-divided rows, a single toggle/segmented/status
vocabulary, status dots instead of pills, and no cards-in-cards or enter
animations. Deletes the qs-*/cfg-*/config-section-card/account-card/
plugins-row/cron-editor-card/session-badge/agent-pill families and
orphaned shared rules.

* style(ui-docs): format design-system docs

* fix(ui): make activity statusKind lookup exhaustive for consistent-return lint

* fix(ui): address settings design-language review findings

Label-wrapped toggle rows with required accessible names, named selects
and cron form controls, busy-disabled segmented controls with restored
theme-transition anchors, collapsible skill groups, semantic plugin
headings, gateway connected status, paired-devices empty state, logs
subtitle, cron prompt help, and keyboard-accessible session goal
objectives.

* fix(ui): harden settings primitives per review round two

Wrap row action clusters, fully-inset nav focus ring, restore number
steppers in the schema form, cap node capability lines, keep the named
Activity region landmark, and associate cron help text via the row
label.

* fix(ui): skip empty section headings and fix the toggle doc example

* docs(ui): import renderSettingsToggleRow in the settings example

* fix(ui): rename number stepper delta to avoid shadowing
2026-07-13 08:40:58 -07:00
Peter Steinberger f110687cfe refactor(ui): align plugin filter chips with the hub tab strip (#106168)
* refactor(ui): align plugin filter chips with the hub tab strip

Drop the segmented inventory meter above the installed filters and
restyle the filter chips to match the tab strip above them: same
radius, hover, active fill, and count badges. Removes the unused
pluginsPage.pulseLabel key and prunes generated locales.

* ci: trigger PR checks
2026-07-13 08:00:35 -07:00
Peter Steinberger e168443123 refactor(ui): direct enable/disable and remove actions on plugin cards (#106040)
* refactor(ui): direct enable/disable and remove actions on plugin cards

Replace the state chip + kebab menu on plugin cards, installed rows,
ClawHub results, and MCP server rows with a direct Enable/Disable
button and a trash icon for removable entries. Drop the redundant
'View details' menu item (the whole card opens details) and delete the
now-unused menu machinery, document listeners, and CSS.

* style: oxfmt plugins-page test helper

* chore(i18n): prune removed pluginsPage menu keys from locale bundles
2026-07-13 00:38:35 -07:00
Peter Steinberger 401f278f11 feat: add Control UI plugin management (#103176)
* feat(ui): add plugin catalog management

* feat(gateway): add plugins.uninstall and richer plugin catalog metadata

Adds a plugins.uninstall gateway method (operator.admin, control-plane write)
backed by a lock-guarded uninstallManagedPlugin that mirrors the CLI flow:
config cleanup, install-record removal, managed file deletion, and registry
refresh. Bundled plugins stay disable-only. Catalog entries now carry a
manifest-derived category and a removable flag; ClawHub search results expose
download counts and verification tiers.

* feat(ui): redesign plugins page with inventory, store shelves, and cover art

Rebuilds /settings/plugins around three tabs: Installed (category-grouped
inventory with overview stats, state filters, uninstall for external plugins,
and inline MCP server management through the shared config seam), Discover
(featured/official shelves plus one-click MCP connectors and curated ClawHub
searches), and ClawHub (search with download counts and verification badges).
Every catalog entry renders bundled cover art or a deterministic gradient
monogram tile - no more empty boxes. Artwork generated with Codex CLI, shipped
as 512px WebP under ui/public/plugin-art.

* chore(ui): regenerate locale bundles for plugins manager strings

* docs: describe plugins manager tabs, uninstall, and MCP connectors

* fix(plugins): human catalog labels and un-pinned hosted fallback ids

listManagedPlugins now prefers manifest names over registry package-name
backfill, falls back to channel catalog labels and blurbs, and stops pinning
expectedPluginId when a hosted feed entry only exposes its package name
(which rejected every legitimate install of that package). Found via live
gateway testing against ClawHub.

* fix(ui): send minimal RFC 7396 merge patches for MCP server edits

config.patch merges rather than replaces, so key removal needs an explicit
null; sending the full config back made MCP server removal a no-op. Found
via live gateway testing.

* fix(ui): write explicit MCP transports for URL servers

The MCP runtime defaults URL-only servers to SSE, so streamable HTTP
endpoints saved by the add form or connector templates would fail at
connect time. Connector templates now declare their transport and the
add form infers streamable-http unless the URL follows the /sse
convention. Flagged by autoreview against the transport resolver.

* test(ui): wait for deferred plugin requests before resolving in e2e

* feat(ui): plugins detail view, action menus, and unified ClawHub search

Reworks the plugins page from PR #103176 feedback: merges the ClawHub tab into
Discover (typing searches ClawHub inline and appends a quiet From ClawHub
section, with Browse ClawHub demoted to a header text link), makes every row and
store card open a plugin detail overlay (hero art, primary enable/install
action, metadata table), and replaces enable/disable switches with a state chip
plus an overflow menu (Enable/Disable, Remove for external plugins, View
details) matching the ChatGPT-store install+menu pattern. MCP rows use the same
menu; refresh is now icon-only.

* chore(ui): regenerate locale bundles for plugins UI iteration

* feat(ui): vetted, grouped connector catalog for the plugins store

Expands Connect your world to 28 connectors organized into use-case shelves
(Work & productivity, Coding & infrastructure, Home & media, Everyday life).
Every entry passed a three-stage subagent review: official-docs verification
plus live endpoint probes for MCP servers, ClawHub result-quality and
malware/typosquat screening for curated searches, and an adversarial pass
that dynamically registered OAuth clients to prove one-click viability.

That review removed Figma (registration allowlisted, 403) and Atlassian
(OAuth issuer-mismatch bug upstream), downgraded GitHub to PAT-based setup
(no dynamic client registration upstream), fixed Linear (/sse retired) and
Home Assistant (/api/mcp, streamable HTTP) endpoints, retargeted poisoned or
dead searches (youtube, finance, hue dropped; calendar -> google calendar;
stocks replaces finance), and added Todoist, Airtable, Canva, Stripe,
Context7, DeepWiki, Hugging Face one-click MCP servers plus Jira, PDF,
transcription, Kubernetes, Reddit, maps, translation, and notes searches.
Keyless servers get a ready-to-use success message; new cover art included.

* chore(ui): regenerate locale bundles for connector groups

* fix(plugins): suppress hosted catalog rows once their package is installed

Hosted feed entries without a declared runtime id fall back to their package
name as catalog id, which never matches the installed runtime id, so the
Discover shelf kept offering an already-installed package. Installed package
names now also suppress official rows. Flagged by autoreview.

* fix(plugins): pin declared runtime ids and surface connector errors in place

The runtime-id pin now keys off explicitly declared catalog ids (plugin,
channel, or provider) instead of string-comparing against the package name,
so declared ids that equal their package name stay enforced while entry-id
fallbacks stay unpinned. Connector add failures on Discover now render on the
triggering card instead of the Installed tab's MCP section. Both flagged by
autoreview; regression tests included.

* feat(ui): full inventory artwork, pulse header, and two-column plugin list

Every bundled plugin now ships distinctive cover art (113 new Codex CLI
illustrations; 172 total, ~2.1MB WebP), so inventory rows and detail views
never fall back to monogram tiles. The four stat cards give way to a compact
inventory pulse: a segmented enabled/disabled/issues meter whose legend and
counts live inside the filter chips. Inventory, MCP, and search rows flow
into two columns when the panel is wide enough.

* chore(ui): regenerate locale bundles for pulse header

* fix(ui): omit stdio args from the MCP server row target

Stdio MCP args routinely carry tokens, and the inventory is visible to
read-only operators; mirror the config page and show only the command.
Flagged by autoreview; regression test included.

* fix(merge): point crestodian setup at relocated plugin commit/refresh modules

* fix(merge): add bootstrapToken to plugins page test gateway harness

* fix(plugins): name catalog install-action branches so Swift emits the union

* fix(ui): satisfy strict lint on plugins page form parsing and mocks

* chore(build): regen docs map, raise plugin-sdk declaration budget for new protocol surface

* fix(ui): type the plugins page patch mock with its real call signature
2026-07-10 11:56:44 +01:00