From b9ce52dc95697fea479c678a518f6e1d84f9cc66 Mon Sep 17 00:00:00 2001 From: "R.Amogh" Date: Thu, 13 Nov 2025 17:11:38 +0530 Subject: [PATCH] agent_ui: Fix scrolling in context server configuration modal (#42502) ## Summary Fixes #42342 When installing a dev extension with long installation instructions, the configuration modal would overflow and users couldn't scroll to see the full content or interact with buttons at the bottom. ## Solution This PR adds a `ScrollHandle` to the `ConfigureContextServerModal` and passes it to the `Modal` component, enabling the built-in modal scrolling capability. This ensures all content remains accessible regardless of length. ## Changes - Added `ScrollHandle` import to the ui imports - Added `scroll_handle: ScrollHandle` field to `ConfigureContextServerModal` struct - Initialize `scroll_handle` with `ScrollHandle::new()` when creating the modal - Pass the scroll handle to `Modal::new()` instead of `None` ## Testing - Built the changes locally - Tested with extensions that have long installation instructions - Verified scrolling works and all content is accessible - Confirmed no regression for extensions with short descriptions Release Notes: - Fixed scrolling issue in extension configuration modal when installation instructions overflow the viewport --------- Co-authored-by: Finn Evers --- .../configure_context_server_modal.rs | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/crates/agent_ui/src/agent_configuration/configure_context_server_modal.rs b/crates/agent_ui/src/agent_configuration/configure_context_server_modal.rs index 88896f51086dc5f7d3eddb2fffef2fa3a7039c79..ed1e8afd1b3b3220d31119f7292b6b0934cd2ba7 100644 --- a/crates/agent_ui/src/agent_configuration/configure_context_server_modal.rs +++ b/crates/agent_ui/src/agent_configuration/configure_context_server_modal.rs @@ -7,8 +7,8 @@ use anyhow::{Context as _, Result}; use context_server::{ContextServerCommand, ContextServerId}; use editor::{Editor, EditorElement, EditorStyle}; use gpui::{ - AsyncWindowContext, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Task, - TextStyle, TextStyleRefinement, UnderlineStyle, WeakEntity, prelude::*, + AsyncWindowContext, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, ScrollHandle, + Task, TextStyle, TextStyleRefinement, UnderlineStyle, WeakEntity, prelude::*, }; use language::{Language, LanguageRegistry}; use markdown::{Markdown, MarkdownElement, MarkdownStyle}; @@ -23,7 +23,8 @@ use project::{ use settings::{Settings as _, update_settings_file}; use theme::ThemeSettings; use ui::{ - CommonAnimationExt, KeyBinding, Modal, ModalFooter, ModalHeader, Section, Tooltip, prelude::*, + CommonAnimationExt, KeyBinding, Modal, ModalFooter, ModalHeader, Section, Tooltip, + WithScrollbar, prelude::*, }; use util::ResultExt as _; use workspace::{ModalView, Workspace}; @@ -252,6 +253,7 @@ pub struct ConfigureContextServerModal { source: ConfigurationSource, state: State, original_server_id: Option, + scroll_handle: ScrollHandle, } impl ConfigureContextServerModal { @@ -361,6 +363,7 @@ impl ConfigureContextServerModal { window, cx, ), + scroll_handle: ScrollHandle::new(), }) }) }) @@ -680,6 +683,7 @@ impl ConfigureContextServerModal { impl Render for ConfigureContextServerModal { fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement { + let scroll_handle = self.scroll_handle.clone(); div() .elevation_3(cx) .w(rems(34.)) @@ -699,14 +703,29 @@ impl Render for ConfigureContextServerModal { Modal::new("configure-context-server", None) .header(self.render_modal_header()) .section( - Section::new() - .child(self.render_modal_description(window, cx)) - .child(self.render_modal_content(cx)) - .child(match &self.state { - State::Idle => div(), - State::Waiting => Self::render_waiting_for_context_server(), - State::Error(error) => Self::render_modal_error(error.clone()), - }), + Section::new().child( + div() + .size_full() + .child( + div() + .id("modal-content") + .max_h(vh(0.7, window)) + .overflow_y_scroll() + .track_scroll(&scroll_handle) + .child(self.render_modal_description(window, cx)) + .child(self.render_modal_content(cx)) + .child(match &self.state { + State::Idle => div(), + State::Waiting => { + Self::render_waiting_for_context_server() + } + State::Error(error) => { + Self::render_modal_error(error.clone()) + } + }), + ) + .vertical_scrollbar_for(scroll_handle, window, cx), + ), ) .footer(self.render_modal_footer(cx)), )