## Description:
This PR adds support for customizing the Switch component's thumb color.
- Changes:
• Added switch_thumb field to ThemeColor and ThemeConfig.
• Updated Switch component to use cx.theme().switch_thumb.
• Config key: switch.thumb.background (falls back to background color if
not set).
Co-authored-by: hl <hl@nmcsoft.com>
## Break Change
- The `width`, `border_width` method has been removed from Sidebar, use
`Styled` trait to use `w`, `border` method from GPUI instead.
```diff
Sidebar::left()
- .width(relative(1.))
- .border_width(px(0.))
+ .w(relative(1.))
+ .border_0()
.collapsed(false)
```
This makes use of the `IconNamed` trait and a blanked implementation to
convert anything that implements this to an `Icon`.
This allows for easily defined custom versions of `IconName`, while
minimally changing existing code (essentially only if you previously
made use of the `.path()` method on the `IconName` enum; this now
requires an import of the `IconNamed` trait).
# Example
```rust
use gpui_component::IconNamed;
pub enum IconName {
Encounters,
Monsters,
Spells,
}
impl IconNamed for IconName {
fn path(self) -> gpui::SharedString {
match self {
IconName::Encounters => "icons/encounters.svg",
IconName::Monsters => "icons/monsters.svg",
IconName::Spells => "icons/spells.svg",
}
.into()
}
}
// this allows for the following interactions (works with anything that has the `.icon(icon)` method
Button::new("my-button").icon(IconName::Spells);
Icon::new(IconName::Monsters);
```
If you want to directly "render" a custom `IconName` you must implement
the `RenderOnce` trait and derive `IntoElement` on the `IconName`.
```rust
use gpui::{IntoElement, RenderOnce};
use gpui_component::IconNamed;
#[derive(IntoElement)]
pub enum IconName {
// The same as before
}
impl IconNamed for IconName {
// The same as before
}
impl RenderOnce for IconName {
fn render(self, _: &mut gpui::Window, _: &mut gpui::App) -> impl gpui::IntoElement {
gpui_component::Icon::empty().path(self.path())
}
}
// this allows for the following interaction
div()
.child(IconName::Monsters)
```
Overall I think is an improvement to the existing way to do custom
`IconName` implementations.
I am unsure if this change should also be reflected in the documentation
on the section with "Icons & Assets", though I personally think it would
make sense to highlight this way to do custom versions of `IconName` as
it is considerably less involved than the current approach.
Closes#1627.
---------
Co-authored-by: Jason Lee <huacnlee@gmail.com>
Fixes#1410
## Problem
The `display_title` prop was overriding the default way dropdown option
titles are displayed, causing incorrect rendering of option titles.
**Expected behavior:**
<img width="716" height="944" alt="Expected dropdown display"
src="https://github.com/user-attachments/assets/38926731-32dd-4a16-9d08-7f2eed2c99a4"
/>
**Actual behavior:**
<img width="580" height="974" alt="image"
src="https://github.com/user-attachments/assets/d96b935a-ce4d-462c-a9ce-4995f5c8eeb5"
/>
## Solution
- Revert the `display_title` change that was causing the issue
- Add a `render` function to allow custom rendering of option titles
instead
This approach provides more flexibility for customizing option display
while preserving the default behavior.
cc @stippi
Fix the issue where clicking a button inside a table row can't stop the
click event from propagating to the table, causing the `td` element to
be selected unexpectedly.
This is a follow up to #1560 I noticed a couple small issues with
resizable panels and their use in docks after experimenting a lot:
- Sometimes the resizable group would take about ~500ms to update after
a resize. This was caused by the `StackPanel` not getting notified and
therefore not redrawn when the `ResizableState` was notified, as well as
the notify in `adjust_to_container_size` not actually firing properly.
The latter was fixed by defering the notify, though I'm still not quite
sure why that is necessary.
- In a couple of places, the total size all the panel missmatches the
container size, causing small glitches the first time a panel is
resized. Update the code in those places to properly adjust all the
panel sizes so they match the container size.
---------
Co-authored-by: Jason Lee <huacnlee@gmail.com>
## Breaking changes
```diff
- Label::new()
+ PlotLabel::new()
- Axis::new()
+ PlotAxis::new()
```
This is to avoid naming conflicts with `gpui` and `gpui-component`.
Currently, there is no good way for a Panel in a dock to e.g. add a tab
to its own tab bar. This is especially annoying as the state in
DockArea::items isn't synced to the underlying views, meaning the
`DockArea::add_panel` function will do nothing after first splitting the
panel, and then deleting the only element in the first part of the
split.
https://github.com/user-attachments/assets/2c61f2f0-9b1c-4154-8a53-b917335b94f0
This pull request adds a function that is called when a PanelView is
added to a tabbar via `add_panel` or `insert_panel_at` or when it is
removed via `detach_panel`.
This allows for entities that implement Panel to keep track of and
directly access the tab bar they belong to, and for example add new
panels to it through buttons in the dropdown menu or the top right of
the tab bar.
Right now the last tab can be closed via the keyboard action, even
though it's explicitly not allowed to be closed via the context menu.
This can result in an invalid app state. This pull request takes the
same check that's currently done to decide whether the close button
should be drawn in the context menu, and adds it to the close action.
Fixes#1562
## Problem
Single-line input fields were blocking all scroll wheel events,
preventing parent containers from handling vertical page scrolling.
## Solution
- Check if input is in single-line mode and scroll is purely vertical
- Allow vertical scroll events to propagate in single-line mode
- Only stop propagation when scroll offset actually changes
## Behavior
- Single-line inputs: vertical scroll passes through to parent
- Multi-line inputs: all scroll behavior unchanged
- Horizontal scrolling still works in both modes
Currently, if dismiss is called from the content_builder or
action_builder, the closing animation doesn't play.
This is because the callback happens after the `closing` variable is
set, so the animation will only start on the next frame, (and for some
reason notify() doesn't trigger another frame?).
This change makes it so that the content_builder is called first, so the
closing animation starts playing immediately on the same frame.
This also adds a check to dismiss to prevent spawning unnecessary
futures if it is called multiple times
## Break Change
- The `Root::render_notification_layer`, `Root::render_sheet_layer`,
`Root::render_dialog_layer` has been removed, we don't need it now, the
Root element has default rendered them.