Enable scrolling in tab bar (#3614)

Marshall Bowers created

This PR enables scrolling horizontally in the tab bar.

Currently this requires holding down <kbd>Shift</kbd> for the scroll to
activate. We'll need to look into this.

Scrolling also currently works when there is a split in the editor, as
the non-split view goes down a different rendering path that does not
constrain the pane width, which breaks a number of things.

Release Notes:

- N/A

Change summary

crates/storybook2/src/stories.rs                 |  2 
crates/storybook2/src/stories/overflow_scroll.rs | 41 ++++++++++++++++++
crates/storybook2/src/story_selector.rs          |  4 +
crates/ui2/src/components/tab_bar.rs             | 13 +++-
4 files changed, 56 insertions(+), 4 deletions(-)

Detailed changes

crates/storybook2/src/stories.rs 🔗

@@ -2,6 +2,7 @@ mod auto_height_editor;
 mod cursor;
 mod focus;
 mod kitchen_sink;
+mod overflow_scroll;
 mod picker;
 mod scroll;
 mod text;
@@ -12,6 +13,7 @@ pub use auto_height_editor::*;
 pub use cursor::*;
 pub use focus::*;
 pub use kitchen_sink::*;
+pub use overflow_scroll::*;
 pub use picker::*;
 pub use scroll::*;
 pub use text::*;

crates/storybook2/src/stories/overflow_scroll.rs 🔗

@@ -0,0 +1,41 @@
+use gpui::{Div, Render};
+use story::Story;
+
+use ui::prelude::*;
+
+pub struct OverflowScrollStory;
+
+impl Render for OverflowScrollStory {
+    type Element = Div;
+
+    fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
+        Story::container()
+            .child(Story::title("Overflow Scroll"))
+            .child(Story::label("`overflow_x_scroll`"))
+            .child(
+                h_stack()
+                    .id("overflow_x_scroll")
+                    .gap_2()
+                    .overflow_x_scroll()
+                    .children((0..100).map(|i| {
+                        div()
+                            .p_4()
+                            .debug_bg_cyan()
+                            .child(SharedString::from(format!("Child {}", i + 1)))
+                    })),
+            )
+            .child(Story::label("`overflow_y_scroll`"))
+            .child(
+                v_stack()
+                    .id("overflow_y_scroll")
+                    .gap_2()
+                    .overflow_y_scroll()
+                    .children((0..100).map(|i| {
+                        div()
+                            .p_4()
+                            .debug_bg_green()
+                            .child(SharedString::from(format!("Child {}", i + 1)))
+                    })),
+            )
+    }
+}

crates/storybook2/src/story_selector.rs 🔗

@@ -27,6 +27,7 @@ pub enum ComponentStory {
     List,
     ListHeader,
     ListItem,
+    OverflowScroll,
     Scroll,
     Tab,
     TabBar,
@@ -54,6 +55,9 @@ impl ComponentStory {
             Self::List => cx.build_view(|_| ui::ListStory).into(),
             Self::ListHeader => cx.build_view(|_| ui::ListHeaderStory).into(),
             Self::ListItem => cx.build_view(|_| ui::ListItemStory).into(),
+            Self::OverflowScroll => cx
+                .build_view(|_| crate::stories::OverflowScrollStory)
+                .into(),
             Self::Scroll => ScrollStory::view(cx).into(),
             Self::Text => TextStory::view(cx).into(),
             Self::Tab => cx.build_view(|_| ui::TabStory).into(),

crates/ui2/src/components/tab_bar.rs 🔗

@@ -93,11 +93,10 @@ impl RenderOnce for TabBar {
             .id(self.id)
             .group("tab_bar")
             .track_focus(&self.focus_handle)
-            .w_full()
-            .h(rems(HEIGHT_IN_REMS))
-            .overflow_hidden()
             .flex()
             .flex_none()
+            .w_full()
+            .h(rems(HEIGHT_IN_REMS))
             .bg(cx.theme().colors().tab_bar_background)
             .child(
                 h_stack()
@@ -125,7 +124,13 @@ impl RenderOnce for TabBar {
                             .border_b()
                             .border_color(cx.theme().colors().border),
                     )
-                    .child(h_stack().id("tabs").z_index(2).children(self.children)),
+                    .child(
+                        h_stack()
+                            .id("tabs")
+                            .z_index(2)
+                            .overflow_x_scroll()
+                            .children(self.children),
+                    ),
             )
             .child(
                 h_stack()