mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-10-06 11:23:26 +08:00
e1f5a6662f
* fix(conversation): cap chat column width at 800px Replace responsive max-w-4xl / max-w-6xl with max-w-[800px] so the middle column stays narrower on large viewports. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(chat): Connect Repo CTA and hide empty branch pill - Use COMMON$CONNECT_REPO with FolderOpen when no repo/workspace is linked - Show branch control only when selectedBranch is set (drop No Branch) - Cap chat interface wrapper at max-w-[800px] without right-panel width coupling Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): refine input controls and local auth fallback Improve chat input pills and model dropdown interactions while ensuring local agent-server auth uses the configured session key for default-local and cloud-proxy calls to avoid stale-key 401s. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): align attachment and placeholder control styling Move the file-attach trigger into the chat action controls so it sits before Tools, and restyle it as a grey plus button with a circular hover state to match adjacent controls. Also align the chat input placeholder color with the same neutral control tone for visual consistency. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): simplify agent status labels and tone Shorten English agent-status messages for the chat pill and align the status text color with the other grey controls for a more consistent compact UI. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): align model popover settings row styling Add an LLM Settings action to the model popover and normalize its layout, spacing, and divider treatment to match existing dropdown menu patterns while keeping left-aligned positioning. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): restyle status controls and move send action Make the agent-status control transparent by default with gray-to-white icon hover behavior, and move the submit button to the bottom-right controls area beside agent status. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): tighten spacing above git control bar Reduce the top margin before the git control bar so it better matches the bottom spacing around the chat action controls. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): gate submit button on input content Keep the send button inactive until the input has non-whitespace text, and align the revised button sizing/positioning with the bottom action row layout. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): streamline overlays and remove legacy event rails Unify chat control styling and overlay behavior so status/typing/scroll controls float above the thread without adding layout bars, and remove left-rail/checkmark affordances from grouped and generic event cards for a cleaner stream. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): tighten status indicator spacing Reduce status indicator pill padding and icon size, and add right text padding to balance the compact layout in the chat control overlay. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): prioritize centered scroll control over loader Keep the scroll-to-bottom control centered and visible whenever the user is away from the bottom, and use solid base/hover fills so it matches the updated chat surface styling. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): soften conversation event header styling Use the lighter gray chat tone for conversation event header labels/icons and switch those labels to normal weight so grouped event rows match the updated control styling. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): refine markdown spacing and divider styling Tighten markdown vertical rhythm in chat content, add a shared grey horizontal-rule renderer, and tune heading hierarchy to medium/compact styles for clearer structure without heavy emphasis. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): tighten vertical spacing in action event rows Reduce stacked margins and paddings across grouped action rows, generic event cards, and collapsible thinking blocks so adjacent conversation entries read as a denser, more consistent stream. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(design): add app gray palette reference artifacts Capture the current gray color usage in dedicated SVG references, including both a curated palette and a strict exhaustive inventory for design and UI consistency work. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): align compact input overflow menus with menu conventions Keep add-file pinned inline, collapse controls only when width truly runs out, and switch overflow entries to standard context-menu row/submenu patterns while preserving the send button layout at tight widths. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(conversation-panel): use list filter icon for older filters Swap the older-conversations summary toggle icon to ListFilter so it matches the intended sidebar filter affordance. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): complete local workspace launch flow in git controls Switch the local git control CTA from repository connection to workspace launching, including an above-button workspace menu and automatic add-workspace modal when none exist. This also captures the pending chat action/menu styling and test updates in the current working tree. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): relocate desktop vertical padding to input controls Remove desktop top/bottom padding from the main chat panel and apply equivalent bottom spacing to the chat control area so the open repo/workspace controls and input footer keep consistent breathing room. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(conversation): remove bottom margin from chat pane header Drop the chat header bottom margin so the conversation title row sits flush with the content below. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(chat): refresh git control bar immediately after Connect Repo The "Connect Repo" empty-state in the chat input footer kept rendering even after the Open Repository modal had successfully launched a clone and the agent had reported the repository as ready. The bar would only heal after a hard refresh (or never, on cloud backends). Three independent bugs were stacking: 1. Optimistic update was writing to the wrong React Query cache key. `useUpdateConversationRepository.onMutate` called `setQueryData` with `["user", "conversation", id]` (3 elements), but `useUserConversation` reads from `["user", "conversation", id, backendId, orgId]` (5 elements). `setQueryData` requires an *exact* key match, so the update landed on an orphan cache entry that no observer ever read. Switched to `setQueriesData`/`getQueriesData` with the 3-element prefix so the optimistic write actually reaches the active query (Tanstack v5 prefix-matches `setQueriesData` filters). Also normalized `branch`/`gitProvider` to `null` to match the shape produced by the server-side refetch and prevent identity-flicker between the two updates. 2. Cloud `batchGetCloudConversations` / `searchCloudConversations` ignored the local repo selection entirely. For local backends `toAppConversation` overlays `selected_repository`/`selected_branch`/ `git_provider` from `localStorage`, but the cloud path returned the raw SaaS payload — and the SaaS often returns `null` for those fields until its own background hydration finishes. So every refetch (mutation invalidation, 30s poll, panel mount) overwrote the optimistic value with `null` and the bar snapped back to "Connect Repo". Added `overlayStoredRepoSelection` which fills only the `null` slots from local storage; populated server values still win, so we don't shadow real backend changes. 3. `updateConversationRepository` overwrote the entire metadata blob. `setStoredConversationMetadata` is replace-not-merge, so calling it with just `{selected_repository, selected_branch, git_provider}` silently dropped `selected_workspace` (the local-folder attach marker used by the Files tab to default to diff view, see the "Files tab diff-view default logic" note in `AGENTS.md`). Now reads the existing entry first and spreads it under the new repo fields. Defense-in-depth changes: - `useLocalGitInfo` now stays enabled until the conversation reports a *complete* repo tuple (`selected_repository` + `git_provider` + `selected_branch`), not just `selected_repository`. This lets the bar recover from partial-metadata cases (e.g. cloud hydration populates only the repo name first, or the user clones into a subdirectory of `working_dir`). The probe also gained a nested `find . -mindepth 2 -maxdepth 4 -name .git` fallback so a clone into `<workingDir>/<repo>/` is still detected after the direct `git remote get-url origin` in `<workingDir>` returns "no such remote 'origin'" (the agent-server pre-initialises every workspace as a worktree, so the parent directory always has a `.git` folder with no remote). - `useUpdateConversationRepository.onSettled` invalidates `["local-git-info", conversationId]` so the bar re-probes immediately after a connect rather than waiting on the next 10s refetch tick. - `git-control-bar.tsx`'s `hasRepository` predicate now keys off the *resolved* `selectedRepository` + `gitProvider` (which include the local-git probe's findings), not just the conversation field. This lets pull/push/PR buttons light up for local-workspace conversations whose repo metadata was inferred from `git remote`, matching what the repo + branch chips already showed. Verification I traced the failure mode by hitting the live agent-server directly: $ curl -s -X POST .../api/bash/execute_bash_command \\ -H "X-Session-API-Key: \$KEY" \\ -d '{"command":"git remote get-url origin", "cwd":"<workingDir>"}' git remote: error: No such remote 'origin' git rev-parse HEAD: ambiguous argument 'HEAD': unknown revision confirming the worktree-without-remote shape that broke the direct probe and forced the nested-find fallback. Tests __tests__/hooks/mutation/use-update-conversation-repository.test.tsx - optimistically updates the cached conversation under the prefix-extended key used by useUserConversation - rolls back the prefix-keyed cache entry when the mutation rejects __tests__/api/cloud-conversation-service.test.ts (new) - overlays locally-stored repo selection onto batchGetCloudConversations results when the server returns nulls - prefers the cloud server values over locally-stored selections when present - leaves null entries untouched when the cloud server returns null for a missing conversation - returns an empty array without calling the proxy when no ids are provided - overlays repo selection on each item returned from searchCloudConversations Wider sweep: npx vitest run __tests__/hooks/mutation \\ __tests__/api/cloud-conversation-service.test.ts \\ __tests__/api/conversation-metadata-store.test.ts \\ __tests__/api/agent-server-adapter.test.ts \\ __tests__/components/features/chat -> 22 files, 152 tests passed. User-visible behavior after this change: 1. Clicking Launch in the Connect Repo modal flips the bar to repo + branch chips immediately (optimistic update now reaches the active query). 2. The bar stays flipped through the next refetch on cloud backends (overlay keeps the local selection visible until the SaaS catches up). 3. Bar picks up nested clones within ~1s on local backends (local-git-info invalidation forces a re-probe instead of waiting on the 10s poll), and the nested-find fallback handles 'clone into <workingDir>/<repo>/' flows. 4. Pull/push/PR buttons now light up for local-workspace conversations whose remote was inferred from git remote. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(conversation): make right-panel drawer state session-only The right-side drawer's open/closed state (`isRightPanelShown` / `hasRightPanelToggled`) was persisted in localStorage, which made the panel feel sticky in a way users didn't expect — it would still be open after reloads or revisits even though they wanted a clean, focused chat view. Move drawer state fully into the in-memory Zustand store so it: - always starts closed on app load (or on opening a conversation after a restart), - survives in-app navigation because Zustand stays alive across React Router transitions, - only persists tab selection (`selectedTab`), which is the part users do want to come back to. The legacy `rightPanelShown` field is silently stripped from older persisted blobs by `sanitizeStoredState`, so old localStorage data doesn't churn or leak into the new schema. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(ui): standardize three-dots ellipsis trigger across the app Different surfaces had drifted to slightly different "more options" buttons: - conversation header used a 24x24 icon with a hardcoded fill color, - conversation cards in the side panel used a separate square `ellipsis.svg` glyph, - the conversation tab bar used a 20x20 icon with bespoke colors, - LLM profile rows wrapped the icon in a bordered button with yet another color. Promote `EllipsisButton` to be the canonical trigger and route every inline variant through it so size (w-4 h-4 / 16x16), color (`text-[#9299AA]`), and hover treatment (`hover:text-white hover:bg-white/10`) stay consistent everywhere. Layout-only overrides (e.g. translate, opacity-when-paused) flow through `className`, and a `testId` escape hatch keeps the existing `profile-menu-trigger` selector working. The chat-input overflow button intentionally keeps its pill-shaped custom variant; a doc comment on `EllipsisButton` calls that out so future contributors don't replace it. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(design): add 15-stop cool grey palette and complete migration plan Documents migration of ~98 scattered grey values across agent-canvas to a unified 15-stop cool blue-grey family (hue ≈ 220–224°), with all existing hex values, Tailwind utilities, CSS variables, and alpha variants mapped to the nearest new token by RGB + lightness proximity. Artifacts: - cool-grey-palette.svg: visual palette strip + per-shade migration map - cool-grey-migration.md: CSS/Tailwind definitions, per-file migration tables, alpha variant equivalents, and a 6-phase implementation plan Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ui): remove circular pill and ripple effect from autocomplete caret buttons Replace the default HeroUI selector button styling (rounded-full, fixed dimensions, hover fill) with a flat transparent icon and disable the press ripple via selectorButtonProps={{ disableRipple: true }} on all Autocomplete instances. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(design): enforce single border color token across all UI elements - Unify --oh-border-input to cool-grey-700 (same as --oh-border), eliminating the 3-way border split across inputs, cards, and dividers - Replace border-neutral-600 in .button-base with border-[var(--oh-border)] - Replace all border-tertiary usages (27 files) with --oh-border for outer borders and --oh-border-subtle for within-panel dividers - Fix border-tertiary-light on toggle switch OFF state → --oh-border - Fix border-t-tertiary on app-settings Git section divider → --oh-border-subtle - Fix divide-tertiary in profiles-body → divide-[var(--oh-border-subtle)] - Fix secrets table row dividers: --oh-border-subtle → --oh-border - Fix files-tab toolbar and file-quick-row header lines → --oh-border - Fix repo-connector and new-conversation card borders → --oh-border - Remove bg-surface from automations-list and automation-detail routes so they inherit bg-base from the root layout, matching all other pages Co-authored-by: Cursor <cursoragent@cursor.com> * fix(design): migrate automations to shared tokens; fix secondary button, card, and hover strokes - Replace all legacy tailwind.config.js color tokens in automations/ (27 files): bg-surface-card → bg-[var(--oh-surface)], bg-surface-elevated → bg-surface-raised, border-border → border-[var(--oh-border)], text-content-muted → text-muted, status/toggle/badge tokens → --oh-success/--oh-danger/--oh-muted variants - Fix active-status-badge and status-badge inactive fills from bg-border → bg-surface-raised - BrandButton secondary variant: yellow outline+text → border-[var(--oh-border)] text-white hover:bg-surface-raised; move hover:opacity-80 off base onto primary/tertiary only - BrandButton primary: replace text-base (font-size conflict) with text-[var(--oh-color-base)] so all variants share the base text-sm font size - Card primitive default/outlined themes: --oh-border-input → --oh-border (fixes visible mismatch between repo-connector and Start from Scratch cards on home screen) - marketplace-card, skill-card, skills-toolbar: replace hover:border-white/40 with hover:border-[var(--cool-grey-500)] and focus:ring-primary/60 with focus:ring-[var(--oh-border)] - automations routes: remove explicit bg-surface so pages inherit bg-base from root layout Co-authored-by: Cursor <cursoragent@cursor.com> * fix(design): normalize spinners, borders, and accent colors to design tokens Replace hardcoded `border-primary`, `border-blue-500`, and `text-primary` with cool-grey-aligned tokens (`border-white`, `border-white/20`, `var(--oh-border)`, `var(--oh-muted)`) across loading spinners, modals, dropdowns, and link styles. Switch dropdown selected-item highlight from `--oh-interactive-active` to `--oh-interactive-selected`. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(theme): add runtime color theme switcher with OpenHands-Neutral palette - Add src/themes/color-themes.ts: two themes (OpenHands-DeepSea / OpenHands-Neutral) with --cool-grey-* scale overrides and matching --heroui-* HSL channel overrides (default, content, background, foreground families) so HeroUI components and portalled popovers both respond to theme changes. - Inject overrides via a <style> tag on [data-agent-server-ui] AND [data-theme=dark] so portal content rendered to document.body picks up the new palette alongside inline components. - Add ThemeInput (SettingsDropdownInput) to Application Settings; applies the theme immediately on selection and persists to localStorage under openhands-color-theme. - Add ColorThemeApplier to root.tsx so the persisted theme is re-applied on every page load with no flash. Additional token fixes found during theme testing: - Define --color-tertiary-alt → --oh-text-dim in tailwind.css so the ~25 placeholder:text-tertiary-alt / text-tertiary-alt usages (API key input, helper text, badges) resolve correctly. - Fix environment-switch-overlay: replace bg-card / border-border / text-foreground with --oh-surface / --oh-border / --oh-foreground. - Fix AutocompleteSection headings in model-selector: add classNames={{ heading: "text-[var(--oh-muted)]" }} so Verified / Other Models labels are readable against the dropdown background. - Unify structural panel dividers: sidebar right edge + footer separator + files-tab tree divider all changed from --oh-border-subtle to --oh-border, matching the right panel. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ui): improve suggestion card hover to match secondary button style Co-authored-by: Cursor <cursoragent@cursor.com> * fix(theme): set OpenHands-Neutral as the default color theme Co-authored-by: Cursor <cursoragent@cursor.com> * fix: failing tests --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: hieptl <hieptl.developer@gmail.com>
66 lines
2.3 KiB
TypeScript
66 lines
2.3 KiB
TypeScript
import { heroui } from "@heroui/react";
|
|
|
|
export default heroui({
|
|
defaultTheme: "dark",
|
|
layout: {
|
|
radius: {
|
|
small: "5px",
|
|
large: "20px",
|
|
},
|
|
},
|
|
themes: {
|
|
dark: {
|
|
colors: {
|
|
primary: "#4465DB",
|
|
|
|
// Map HeroUI's zinc-based semantic colours to our cool-grey palette.
|
|
// This ensures every HeroUI component that uses bg-default, bg-content*,
|
|
// etc. stays within the same colour family as the rest of the UI.
|
|
|
|
background: {
|
|
DEFAULT: "#0B0E14", // cool-grey-950 — app shell base
|
|
foreground: "#F7F9FC", // cool-grey-50
|
|
},
|
|
|
|
foreground: {
|
|
DEFAULT: "#C3CDDC", // cool-grey-300 — primary readable text
|
|
"50": "#05070A", // cool-grey-975
|
|
"100": "#0B0E14", // cool-grey-950
|
|
"200": "#21252F", // cool-grey-925
|
|
"300": "#2C313F", // cool-grey-900
|
|
"400": "#383F50", // cool-grey-800
|
|
"500": "#4B5468", // cool-grey-700
|
|
"600": "#626D82", // cool-grey-600
|
|
"700": "#7E8A9E", // cool-grey-500
|
|
"800": "#A3B0C4", // cool-grey-400
|
|
"900": "#C3CDDC", // cool-grey-300
|
|
},
|
|
|
|
// Surface layers: panel → card → inner card → inset
|
|
content1: { DEFAULT: "#21252F", foreground: "#EEF2F7" }, // cool-grey-925 / 100
|
|
content2: { DEFAULT: "#2C313F", foreground: "#DCE3EE" }, // cool-grey-900 / 200
|
|
content3: { DEFAULT: "#383F50", foreground: "#C3CDDC" }, // cool-grey-800 / 300
|
|
content4: { DEFAULT: "#4B5468", foreground: "#A3B0C4" }, // cool-grey-700 / 400
|
|
|
|
focus: {
|
|
DEFAULT: "#ffffff", // white focus ring — visible on all dark surfaces
|
|
},
|
|
default: {
|
|
"50": "#05070A", // cool-grey-975
|
|
"100": "#0B0E14", // cool-grey-950
|
|
"200": "#21252F", // cool-grey-925
|
|
"300": "#2C313F", // cool-grey-900
|
|
"400": "#383F50", // cool-grey-800
|
|
"500": "#4B5468", // cool-grey-700
|
|
"600": "#626D82", // cool-grey-600
|
|
"700": "#7E8A9E", // cool-grey-500
|
|
"800": "#A3B0C4", // cool-grey-400
|
|
"900": "#C3CDDC", // cool-grey-300
|
|
DEFAULT: "#383F50", // cool-grey-800 — hover/selected tint
|
|
foreground: "#F7F9FC", // cool-grey-50 — text on default bg
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|