SIGN IN SIGN UP

button: Preserve inner DropdownButton configuration (#2760)

## Summary

`DropdownButton` now preserves the configuration of its inner action
button instead of unconditionally replacing shared values or mirroring
action-specific `Button` options.

### What changed

- An outer variant or size still applies to both halves. When either is
unset, the inner button's value becomes the shared value for the split.
- Action-specific options such as `compact`, `loading`, `rounded`,
`tooltip`, and the click handler remain on the inner `Button`.
- An inner selected or disabled state is no longer cleared by the
`DropdownButton` defaults.
- The menu trigger renders independently of the optional action button
instead of disappearing when `.button(...)` is omitted.
- The existing ghost behavior is explicit: an unselected ghost split
renders as two separate buttons and joins when selected.
- The Story uses focused export, save, and recent-file examples with
visible action feedback.

## Breaking Changes

`compact`, `loading`, `rounded`, and `tooltip` have been removed from
`DropdownButton`. Set them on the inner action `Button`:

```diff
 DropdownButton::new("dropdown")
-    .button(Button::new("btn").label("Save"))
-    .compact()
-    .loading(is_saving)
-    .rounded(ButtonRounded::Small)
-    .tooltip("Save options")
+    .button(
+        Button::new("btn")
+            .label("Save")
+            .compact()
+            .loading(is_saving)
+            .rounded(ButtonRounded::Small)
+            .tooltip("Save options"),
+    )
     .dropdown_menu(|menu, _, _| menu)
```

Leaving the outer variant or size unset now uses the inner button's
value for both halves:

```rust
DropdownButton::new("dropdown")
    .button(Button::new("btn").label("Delete").danger().small())
    .dropdown_menu(|menu, _, _| menu)
```

Loading is now action-specific. A loading inner button is inert while
the menu trigger remains available; use `DropdownButton::disabled(true)`
when both halves must be disabled.

These four removed methods had no users in the downstream application,
so no downstream call site required migration.

## Test plan

- `cargo test -p gpui-component --lib` — 426 passed.
- `cargo test -p gpui-component --test legacy_button_compat` — 5 passed.
- `cargo clippy --workspace --all-targets -- --deny warnings` — passed.
- `cargo fmt --all -- --check` and `git diff --check` — passed.
- `cargo check -p gpui-component-story` — passed.

## AI-generated code

The initial implementation was written with Claude Code. The final
design was reviewed and refined with Codex, then reviewed by hand.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Codex <codex@openai.com>
J
Jason Lee committed
6bd53de4bf4de080b9f23b9c90c0b3effb567927
Parent: 222cf96
Committed by GitHub <noreply@github.com> on 8/18/2026, 12:27:54 PM