Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the Connectors/MCP UI and shared UI components to improve connect/disconnect affordances, status indicators, and loading/hydration behavior (reducing “Connect → Disconnect” flashing). It also adjusts toast layering so notifications appear above dialogs/modals, and aligns i18n strings for connect/disconnect across locales.
Changes:
- Add “hydration” flags for installed-state derivation and disable actions until data is loaded (MCP market, tool selection, integration management).
- Introduce pill/rounded-full buttons and status-dot UI across MCP/integration lists and several dialogs.
- Move Sonner’s Toaster rendering to a portal + raise toaster z-index; add/align connect/disconnect i18n keys across locales.
Reviewed changes
Copilot reviewed 40 out of 40 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/style/index.css | Ensures Sonner toaster is stacked above modals/dialogs via z-index. |
| src/pages/Connectors/components/MCPMarket.tsx | Adds userInstallsHydrated gating + pill connect/disconnect button behavior. |
| src/pages/Connectors/components/MCPListItem.tsx | Replaces hardcoded green dot with status-derived dot classes. |
| src/pages/Connectors/components/MCPEnvDialog.tsx | Uses new DialogFooter rounded props for pill footer actions. |
| src/pages/Connectors/components/MCPAddDialog.tsx | Makes Monaco editor area flex-fill + enables word wrapping for long JSON. |
| src/pages/Browser/CDP.tsx | Updates buttons to pill style and refactors some layout class ordering. |
| src/i18n/locales/zh-Hant/setting.json | Adds disconnect translation. |
| src/i18n/locales/zh-Hant/layout.json | Reorders/adds connect/disconnect keys near install-related strings. |
| src/i18n/locales/zh-Hans/setting.json | Adds disconnect translation. |
| src/i18n/locales/zh-Hans/layout.json | Reorders/adds connect/disconnect keys near install-related strings. |
| src/i18n/locales/ru/setting.json | Adds disconnect translation. |
| src/i18n/locales/ru/layout.json | Reorders/adds connect/disconnect keys near install-related strings. |
| src/i18n/locales/ko/setting.json | Adds disconnect translation. |
| src/i18n/locales/ko/layout.json | Reorders/adds connect/disconnect keys near install-related strings. |
| src/i18n/locales/ja/setting.json | Adds disconnect translation. |
| src/i18n/locales/ja/layout.json | Reorders/adds connect/disconnect keys near install-related strings. |
| src/i18n/locales/it/setting.json | Adds disconnect translation. |
| src/i18n/locales/it/layout.json | Reorders/adds connect/disconnect keys near install-related strings. |
| src/i18n/locales/fr/setting.json | Updates connect phrasing and adds disconnect. |
| src/i18n/locales/fr/layout.json | Reorders/adds connect/disconnect keys near install-related strings. |
| src/i18n/locales/es/setting.json | Adds disconnect translation. |
| src/i18n/locales/es/layout.json | Reorders/adds connect/disconnect keys near install-related strings. |
| src/i18n/locales/en-us/setting.json | Adds connect/disconnect near install strings; removes some duplicate connect entries. |
| src/i18n/locales/en-us/layout.json | Reorders/adds connect/disconnect keys near install-related strings. |
| src/i18n/locales/de/setting.json | Adds disconnect translation. |
| src/i18n/locales/de/layout.json | Reorders/adds connect/disconnect keys near install-related strings. |
| src/i18n/locales/ar/setting.json | Adds disconnect translation (in both duplicated blocks). |
| src/i18n/locales/ar/layout.json | Reorders/adds connect/disconnect keys near install-related strings. |
| src/hooks/useIntegrationManagement.ts | Introduces configsHydrated to avoid install-state flashing before configs load. |
| src/components/ui/sonner.tsx | Renders Toaster via portal into document.body. |
| src/components/ui/input.tsx | Improves layout/overflow handling for narrow containers and long notes. |
| src/components/ui/input-select.tsx | Refactors component formatting/behavior + improves note wrapping/scroll handling. |
| src/components/ui/dialog.tsx | Adds optional rounded props for footer confirm/cancel buttons. |
| src/components/ui/button.tsx | Adds rounded variant (default/full) to support pill buttons. |
| src/components/ui/button.stories.tsx | Adds Storybook control + example for rounded="full". |
| src/components/IntegrationList/index.tsx | Replaces ellipse icon with status dots; adds hydration gating and new connect/disconnect button behavior. |
| src/components/AddWorker/index.tsx | Applies rounded footer actions and layout class reordering. |
| src/components/AddWorker/ToolSelect.tsx | Adds userMcpsHydrated gating to prevent premature installed-state derivation and disables install until ready. |
| src/App.tsx | Switches to app-local Toaster component and removes inline z-index style. |
| .storybook/preview.tsx | Switches to app-local Toaster component in Storybook. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Per-item error state for status dot | ||
| const [errorKeys, setErrorKeys] = useState<Record<string, boolean>>({}); | ||
| const errorTimers = useRef<Record<string, ReturnType<typeof setTimeout>>>({}); | ||
|
|
||
| const markError = useCallback((key: string) => { | ||
| setErrorKeys((prev) => ({ ...prev, [key]: true })); | ||
| if (errorTimers.current[key]) clearTimeout(errorTimers.current[key]); | ||
| errorTimers.current[key] = setTimeout(() => { | ||
| setErrorKeys((prev) => ({ ...prev, [key]: false })); | ||
| }, 4000); | ||
| }, []); |
There was a problem hiding this comment.
markError schedules per-key setTimeout callbacks but there’s no cleanup on unmount, so the timeout can fire after the component is gone (state update on unmounted component) and the ref will retain timers. Add a cleanup effect that clears all pending timeouts (and optionally deletes entries from errorTimers.current) when the component unmounts.
| const handleEscape = (event: KeyboardEvent) => { | ||
| if (event.key === "Escape") { | ||
| setInputValue(value) // Reset to original value | ||
| setIsOpen(false) | ||
| inputRef.current?.blur() | ||
| if (event.key === 'Escape') { | ||
| setInputValue(value); // Reset to original value | ||
| setIsOpen(false); | ||
| inputRef.current?.blur(); | ||
| } |
There was a problem hiding this comment.
Pressing Escape resets inputValue to value, but value is the option’s underlying value while the input display is supposed to show the option label. This will show the raw value string after Esc for most selects. Reset to the selected option’s label (or reuse the same mapping logic used in the [value, options] sync effect).
| "coming-soon": "Coming Soon", | ||
| "uninstall": "Uninstall", | ||
| "install": "Install", | ||
| "connect": "Connect", | ||
| "disconnect": "Disconnect", |
There was a problem hiding this comment.
This locale file still contains large duplicated blocks of keys (e.g., coming-soon/install/connect/disconnect appear multiple times in the same top-level object). In JSON, duplicate keys are ambiguous and most parsers will keep only the last occurrence, silently overriding earlier translations. Please deduplicate the file so each key is defined exactly once.
| "google-custom-search-api": "Google واجهة برمجة تطبيقات البحث المخصص من", | ||
| "google-cloud-console": "Google Cloud وحدة تحكم", | ||
| "connect": "اتصال", | ||
| "disconnect": "قطع الاتصال", |
There was a problem hiding this comment.
This file defines connect/disconnect (and many other keys) more than once in the same JSON object (there’s a second duplicated block later in the file). Duplicate keys will cause earlier translations to be ignored by typical JSON parsers, making behavior depend on key order. Please remove the duplicated block(s) so each key is unique.
Related Issue
Closes #
Description
Connectors / MCP
Shared UI
input, input-select, sonner: Refactors / behavior or styling updates (large input-select diff).
i18n (second commit + part of first)
Storybook
button.stories: rounded control + RoundedFull example.
Testing Evidence (REQUIRED)
What is the purpose of this pull request?
Contribution Guidelines Acknowledgement