spinner: Rename Indicator to Spinner. (#1526)

## Break Change

- Renamed `Indicator` to `Spinner`.

```diff
- use gpui_component::indicator::Indicator;
+ use gpui_component::spinner::Spinner;
```
This commit is contained in:
Jason Lee 2025-11-06 11:36:39 +08:00 committed by GitHub
parent c06e91101e
commit 4dc10165fb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 102 additions and 124 deletions

View file

@ -18,7 +18,6 @@ mod form_story;
mod group_box_story;
mod icon_story;
mod image_story;
mod indicator_story;
mod input_story;
mod kbd_story;
mod label_story;
@ -37,6 +36,7 @@ mod select_story;
mod sidebar_story;
mod skeleton_story;
mod slider_story;
mod spinner_story;
mod switch_story;
mod table_story;
mod tabs_story;
@ -78,7 +78,6 @@ pub use form_story::FormStory;
pub use group_box_story::GroupBoxStory;
pub use icon_story::IconStory;
pub use image_story::ImageStory;
pub use indicator_story::IndicatorStory;
pub use input_story::InputStory;
pub use kbd_story::KbdStory;
pub use label_story::LabelStory;
@ -98,6 +97,7 @@ use serde::{Deserialize, Serialize};
pub use sidebar_story::SidebarStory;
pub use skeleton_story::SkeletonStory;
pub use slider_story::SliderStory;
pub use spinner_story::SpinnerStory;
pub use switch_story::SwitchStory;
pub use table_story::TableStory;
pub use tabs_story::TabsStory;

View file

@ -54,7 +54,7 @@ impl Gallery {
StoryContainer::panel::<GroupBoxStory>(window, cx),
StoryContainer::panel::<IconStory>(window, cx),
StoryContainer::panel::<ImageStory>(window, cx),
StoryContainer::panel::<IndicatorStory>(window, cx),
StoryContainer::panel::<SpinnerStory>(window, cx),
StoryContainer::panel::<InputStory>(window, cx),
StoryContainer::panel::<KbdStory>(window, cx),
StoryContainer::panel::<LabelStory>(window, cx),

View file

@ -1,23 +1,23 @@
use gpui::{
px, App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, Styled,
Window,
App, AppContext, Context, Entity, Focusable, IntoElement, ParentElement, Render, Styled,
Window, px,
};
use gpui_component::{indicator::Indicator, v_flex, ActiveTheme as _, IconName, Sizable};
use gpui_component::{ActiveTheme as _, IconName, Sizable, spinner::Spinner, v_flex};
use crate::section;
pub struct IndicatorStory {
pub struct SpinnerStory {
focus_handle: gpui::FocusHandle,
value: f32,
}
impl super::Story for IndicatorStory {
impl super::Story for SpinnerStory {
fn title() -> &'static str {
"Indicator"
"Spinner"
}
fn description() -> &'static str {
"Displays an indicator showing the completion progress of a task."
"Displays an spinner showing the completion progress of a task."
}
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
@ -25,7 +25,7 @@ impl super::Story for IndicatorStory {
}
}
impl IndicatorStory {
impl SpinnerStory {
pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
cx.new(|cx| Self::new(window, cx))
}
@ -42,39 +42,40 @@ impl IndicatorStory {
}
}
impl Focusable for IndicatorStory {
impl Focusable for SpinnerStory {
fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}
impl Render for IndicatorStory {
impl Render for SpinnerStory {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.items_center()
.gap_y_3()
.child(section("Indicator").gap_x_2().child(Indicator::new()))
.size_full()
.gap_6()
.child(section("Spinner").gap_x_2().child(Spinner::new()))
.child(
section("Indicator with color")
section("Spinner with color")
.gap_x_2()
.child(Indicator::new().color(cx.theme().blue))
.child(Indicator::new().color(cx.theme().green)),
.child(Spinner::new().color(cx.theme().blue))
.child(Spinner::new().color(cx.theme().green)),
)
.child(
section("Indicator with size")
section("Spinner with size")
.gap_x_2()
.child(Indicator::new().with_size(px(64.)))
.child(Indicator::new().large())
.child(Indicator::new())
.child(Indicator::new().small())
.child(Indicator::new().xsmall()),
.child(Spinner::new().with_size(px(64.)))
.child(Spinner::new().large())
.child(Spinner::new())
.child(Spinner::new().small())
.child(Spinner::new().xsmall()),
)
.child(
section("Indicator with Icon")
section("Spinner with Icon")
.gap_x_2()
.child(Indicator::new().icon(IconName::LoaderCircle))
.child(Spinner::new().icon(IconName::LoaderCircle))
.child(
Indicator::new()
Spinner::new()
.icon(IconName::LoaderCircle)
.large()
.color(cx.theme().cyan),

View file

@ -16,10 +16,10 @@ use gpui_component::{
button::Button,
checkbox::Checkbox,
h_flex,
indicator::Indicator,
input::{Input, InputEvent, InputState},
label::Label,
menu::{DropdownMenu, PopupMenu},
spinner::Spinner,
table::{Column, ColumnFixed, ColumnSort, Table, TableDelegate, TableEvent, TableState},
v_flex,
};
@ -942,10 +942,7 @@ impl Render for TableStory {
)
.when(delegate.loading, |this| {
this.child(
h_flex()
.gap_1()
.child(Indicator::new())
.child("Loading..."),
h_flex().gap_1().child(Spinner::new()).child("Loading..."),
)
}),
)

View file

@ -1,7 +1,7 @@
use std::rc::Rc;
use crate::{
h_flex, indicator::Indicator, tooltip::Tooltip, ActiveTheme, Colorize as _, Disableable,
h_flex, spinner::Spinner, tooltip::Tooltip, ActiveTheme, Colorize as _, Disableable,
FocusableExt as _, Icon, Selectable, Sizable, Size, StyleSized, StyledExt,
};
use gpui::{
@ -562,7 +562,7 @@ impl RenderOnce for Button {
})
.when(self.loading, |this| {
this.child(
Indicator::new()
Spinner::new()
.with_size(self.size)
.when_some(self.loading_icon, |this, icon| this.icon(icon)),
)

View file

@ -6,10 +6,10 @@ use gpui::{
};
use crate::button::{Button, ButtonVariants as _};
use crate::indicator::Indicator;
use crate::input::clear_button;
use crate::input::element::{LINE_NUMBER_RIGHT_MARGIN, RIGHT_MARGIN};
use crate::scroll::Scrollbar;
use crate::spinner::Spinner;
use crate::{h_flex, Selectable, StyledExt};
use crate::{v_flex, ActiveTheme};
use crate::{IconName, Size};
@ -406,7 +406,7 @@ impl RenderOnce for Input {
.when(self.appearance, |this| this.bg(bg))
.items_center()
.when(state.loading, |this| {
this.child(Indicator::new().color(cx.theme().muted_foreground))
this.child(Spinner::new().color(cx.theme().muted_foreground))
})
.when(self.mask_toggle, |this| {
this.child(Self::render_toggle_mask_button(self.state.clone()))

View file

@ -771,7 +771,7 @@ impl InputState {
self
}
/// Set true to show indicator at the input right.
/// Set true to show spinner at the input right.
///
/// Only for [`InputMode::SingleLine`] mode.
pub fn set_loading(&mut self, loading: bool, _: &mut Window, cx: &mut Context<Self>) {

View file

@ -36,7 +36,6 @@ pub mod form;
pub mod group_box;
pub mod highlighter;
pub mod history;
pub mod indicator;
pub mod input;
pub mod kbd;
pub mod label;
@ -55,6 +54,7 @@ pub mod select;
pub mod sidebar;
pub mod skeleton;
pub mod slider;
pub mod spinner;
pub mod switch;
pub mod tab;
pub mod table;

View file

@ -6,17 +6,17 @@ use gpui::{
Hsla, IntoElement, ParentElement, RenderOnce, Styled as _, Transformation, Window,
};
/// A cycling loading indicator.
/// A cycling loading spinner.
#[derive(IntoElement)]
pub struct Indicator {
pub struct Spinner {
size: Size,
icon: Icon,
speed: Duration,
color: Option<Hsla>,
}
impl Indicator {
/// Create a new loading indicator.
impl Spinner {
/// Create a new loading spinner.
pub fn new() -> Self {
Self {
size: Size::Medium,
@ -26,11 +26,11 @@ impl Indicator {
}
}
/// Set specified icon for the indicator.
/// Set specified icon for the spinner.
///
/// Default is [`IconName::Loader`].
///
/// Please ensure the icon used is suitable for a loading indicator.
/// Please ensure the icon used is suitable for a loading spinner.
pub fn icon(mut self, icon: impl Into<Icon>) -> Self {
self.icon = icon.into();
self
@ -43,14 +43,14 @@ impl Indicator {
}
}
impl Sizable for Indicator {
impl Sizable for Spinner {
fn with_size(mut self, size: impl Into<Size>) -> Self {
self.size = size.into();
self
}
}
impl RenderOnce for Indicator {
impl RenderOnce for Spinner {
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
div()
.child(

View file

@ -17,13 +17,13 @@ collapsed: false
- [Collapsible](collapsible) - Expandable/collapsible content
- [Icon](icon) - Icon display component
- [Image](image) - Image display with fallbacks
- [Indicator](indicator) - Loading and status indicators
- [Kbd](kbd) - Keyboard shortcut display
- [Label](label) - Text labels for form elements
- [Progress](progress) - Progress bars
- [Radio](radio) - Single selection from multiple options
- [Skeleton](skeleton) - Loading placeholders
- [Slider](slider) - Value selection from a range
- [Spinner](spinner) - Loading and status spinners
- [Switch](switch) - Toggle on/off control
- [Tag](tag) - Labels and categories
- [Toggle](toggle) - Toggle button states

View file

@ -1,93 +1,93 @@
---
title: Indicator
description: Displays an animated loading indicator showing the completion progress of a task.
title: Spinner
description: Displays an animated loading showing the completion progress of a task.
---
# Indicator
# Spinner
A versatile indicator component that displays an animated loading spinner. Perfect for showing loading states, progress indicators, and other visual feedback during asynchronous operations. Features customizable icons, colors, sizes, and rotation animations.
Spinner element displays an animated loading. Perfect for showing loading states, progress spinners, and other visual feedback during asynchronous operations. Features customizable icons, colors, sizes, and rotation animations.
## Import
```rust
use gpui_component::indicator::Indicator;
use gpui_component::spinner::Spinner;
```
## Usage
### Basic Indicator
### Basic
```rust
// Default loader icon
Indicator::new()
Spinner::new()
```
### Indicator with Custom Color
### Spinner with Custom Color
```rust
use gpui_component::ActiveTheme;
// Blue indicator
Indicator::new()
// Blue spinner
Spinner::new()
.color(cx.theme().blue)
// Green indicator for success states
Indicator::new()
// Green spinner for success states
Spinner::new()
.color(cx.theme().green)
// Custom color
Indicator::new()
Spinner::new()
.color(cx.theme().cyan)
```
### Indicator Sizes
### Spinner Sizes
```rust
// Extra small indicator
Indicator::new().xsmall()
// Extra small spinner
Spinner::new().xsmall()
// Small indicator
Indicator::new().small()
// Small spinner
Spinner::new().small()
// Medium indicator (default)
Indicator::new()
// Medium spinner (default)
Spinner::new()
// Large indicator
Indicator::new().large()
// Large spinner
Spinner::new().large()
// Custom size
Indicator::new().with_size(px(64.))
Spinner::new().with_size(px(64.))
```
### Indicator with Custom Icon
### Spinner with Custom Icon
```rust
use gpui_component::IconName;
// Loading circle icon
Indicator::new()
Spinner::new()
.icon(IconName::LoaderCircle)
// Large loading circle with custom color
Indicator::new()
Spinner::new()
.icon(IconName::LoaderCircle)
.large()
.color(cx.theme().cyan)
// Different loading icons
Indicator::new()
Spinner::new()
.icon(IconName::Loader)
.color(cx.theme().primary)
```
## Available Icons
The Indicator component supports various loading and progress icons:
The Spinner component supports various loading and progress icons:
### Loading Icons
- `Loader` (default) - Rotating line spinner
- `LoaderCircle` - Circular loading indicator
- `LoaderCircle` - Circular loading spinner
### Other Compatible Icons
@ -95,7 +95,7 @@ The Indicator component supports various loading and progress icons:
## Animation
The Indicator component features a built-in rotation animation:
The Spinner component features a built-in rotation animation:
- **Duration**: 0.8 seconds (configurable via speed parameter)
- **Easing**: Ease-in-out transition
@ -112,40 +112,20 @@ The Indicator component features a built-in rotation animation:
| Large | `.large()` | ~24px |
| Custom | `.with_size(px(n))` | n px |
## API Reference
### Indicator
| Method | Description |
| -------------- | ----------------------------------------------- |
| `new()` | Create a new indicator with default loader icon |
| `icon(icon)` | Set custom icon (accepts `IconName` or `Icon`) |
| `color(color)` | Set indicator color (accepts `Hsla`) |
### Size Methods (from Sizable trait)
| Method | Description |
| ----------------- | ------------------------------- |
| `xsmall()` | Extra small indicator size |
| `small()` | Small indicator size |
| `medium()` | Medium indicator size (default) |
| `large()` | Large indicator size |
| `with_size(size)` | Custom size in pixels |
## Examples
### Loading States
```rust
// Simple loading spinner
Indicator::new()
Spinner::new()
// Loading with custom color
Indicator::new()
Spinner::new()
.color(cx.theme().blue)
// Large loading indicator
Indicator::new()
// Large loading spinner
Spinner::new()
.large()
.color(cx.theme().primary)
```
@ -154,36 +134,36 @@ Indicator::new()
```rust
// Default loader (line spinner)
Indicator::new()
Spinner::new()
.color(cx.theme().muted_foreground)
// Circle loader
Indicator::new()
Spinner::new()
.icon(IconName::LoaderCircle)
.color(cx.theme().blue)
// Large circle loader with custom color
Indicator::new()
Spinner::new()
.icon(IconName::LoaderCircle)
.large()
.color(cx.theme().green)
```
### Status Indicators
### Status Spinners
```rust
// Loading state
Indicator::new()
Spinner::new()
.small()
.color(cx.theme().muted_foreground)
// Processing state
Indicator::new()
Spinner::new()
.icon(IconName::LoaderCircle)
.color(cx.theme().blue)
// Success processing (still animating)
Indicator::new()
Spinner::new()
.icon(IconName::LoaderCircle)
.color(cx.theme().green)
```
@ -192,26 +172,26 @@ Indicator::new()
```rust
// Extra small for inline text
Indicator::new()
Spinner::new()
.xsmall()
.color(cx.theme().muted_foreground)
// Small for buttons
Indicator::new()
Spinner::new()
.small()
.color(cx.theme().primary_foreground)
// Medium for general use (default)
Indicator::new()
Spinner::new()
.color(cx.theme().primary)
// Large for prominent loading states
Indicator::new()
Spinner::new()
.large()
.color(cx.theme().blue)
// Custom size for specific requirements
Indicator::new()
Spinner::new()
.with_size(px(32.))
.color(cx.theme().orange)
```
@ -223,7 +203,7 @@ Indicator::new()
Button::new("submit-btn")
.loading(true)
.icon(
Indicator::new()
Spinner::new()
.small()
.color(cx.theme().primary_foreground)
)
@ -236,7 +216,7 @@ div()
.gap_2()
.child("Processing...")
.child(
Indicator::new()
Spinner::new()
.small()
.color(cx.theme().muted_foreground)
)
@ -249,7 +229,7 @@ div()
.h_full()
.w_full()
.child(
Indicator::new()
Spinner::new()
.large()
.color(cx.theme().primary)
)
@ -258,19 +238,19 @@ div()
## Performance Considerations
- The animation uses CSS transforms for optimal performance
- Multiple indicators on the same page share the same animation timing
- Multiple spinners on the same page share the same animation timing
- The component is lightweight and suitable for frequent updates
- Consider using smaller sizes for better performance with many indicators
- Consider using smaller sizes for better performance with many spinners
## Common Patterns
### Conditional Loading
```rust
// Show indicator only when loading
// Show spinner only when loading
.when(is_loading, |this| {
this.child(
Indicator::new()
Spinner::new()
.small()
.color(cx.theme().muted_foreground)
)
@ -280,12 +260,12 @@ div()
### Loading with Text
```rust
// Loading text with indicator
// Loading text with spinner
h_flex()
.items_center()
.gap_2()
.child(
Indicator::new()
Spinner::new()
.small()
.color(cx.theme().primary)
)
@ -295,7 +275,7 @@ h_flex()
### Overlay Loading
```rust
// Full overlay with indicator
// Full overlay with spinner
div()
.absolute()
.inset_0()
@ -308,7 +288,7 @@ div()
.items_center()
.gap_3()
.child(
Indicator::new()
Spinner::new()
.large()
.color(cx.theme().primary)
)