Settings

Framework

Since: v0.5.0

The Settings component provides a UI for managing application settings. It includes grouped setting items and pages. We can search by title, description, and custom keywords to filter the settings to display only relevant settings (Like this macOS, iOS Settings).

#Import

use gpui_kit::component::setting::{Settings, SettingPage, SettingGroup, SettingItem, SettingField};
SlintNo Slint version of this example yet.

#Usage

#Build a settings

Here we have components that can be used to build a settings page.

  • Settings - The main settings component that holds multiple setting pages.
  • SettingPage - A page of related setting groups.
  • SettingGroup - A group of related setting items based on GroupBox style.
  • SettingItem - A single setting item with title, description, and field.
  • SettingField - Provide different field types like Input, Dropdown, Switch, etc.

The layout of the settings is like this:

Settings
  SettingPage
    SettingGroup
      SettingItem
        Title
        Description (optional)
        SettingField
SlintNo Slint version of this example yet.

#Basic Settings

use gpui_kit::component::setting::{Settings, SettingPage, SettingGroup, SettingItem, SettingField};

Settings::new("my-settings")
    .pages(vec![
        SettingPage::new("General")
            .group(
                SettingGroup::new()
                    .title("Basic Options")
                    .item(
                        SettingItem::new(
                            "Enable Feature",
                            SettingField::switch(
                                |cx: &App| true,
                                |val: bool, cx: &mut App| {
                                    println!("Feature enabled: {}", val);
                                },
                            )
                        )
                    )
            )
    ])
SlintNo Slint version of this example yet.

#With Multiple Pages

Settings::new("app-settings")
    .pages(vec![
        SettingPage::new("General")
            .default_open(true)
            .group(SettingGroup::new().title("Appearance").items(vec![...])),
        SettingPage::new("Software Update")
            .group(SettingGroup::new().title("Updates").items(vec![...])),
        SettingPage::new("About")
            .group(SettingGroup::new().items(vec![...])),
    ])
SlintNo Slint version of this example yet.

#Selection While Searching

Search keeps the current page selected while it contains matching settings. If it no longer matches, the first matching page is selected. A matching selected group is preserved; otherwise selection falls back to its page. Clearing the search keeps the current page rather than restoring an earlier selection. When no settings match, no page content is shown and the selection is retained for when results return.

#Group Variants

use gpui_kit::component::group_box::GroupBoxVariant;

Settings::new("my-settings")
    .with_group_variant(GroupBoxVariant::Outline)
    .pages(vec![...])

Settings::new("my-settings")
    .with_group_variant(GroupBoxVariant::Fill)
    .pages(vec![...])
SlintNo Slint version of this example yet.

A group can override the settings-level variant, for example to present one page’s items directly while the other pages keep the global card surface:

SettingGroup::new()
    .variant(GroupBoxVariant::Normal)
    .items(vec![...])
SlintNo Slint version of this example yet.

#Complete Settings Example

use gpui_kit::{App, SharedString};
use gpui_kit::component::{
    Settings, SettingPage, SettingGroup, SettingItem, SettingField,
    setting::NumberFieldOptions,
    group_box::GroupBoxVariant,
    Size,
};

Settings::new("app-settings")
    .with_size(Size::Medium)
    .with_group_variant(GroupBoxVariant::Outline)
    .pages(vec![
        SettingPage::new("General")
            .resettable(true)
            .default_open(true)
            .groups(vec![
                SettingGroup::new()
                    .title("Appearance")
                    .items(vec![
                        SettingItem::new(
                            "Dark Mode",
                            SettingField::switch(
                                |cx: &App| cx.theme().mode.is_dark(),
                                |val: bool, cx: &mut App| {
                                    // Handle theme change
                                },
                            )
                        )
                        .description("Switch between light and dark themes."),
                    ]),
                SettingGroup::new()
                    .title("Font")
                    .items(vec![
                        SettingItem::new(
                            "Font Family",
                            SettingField::dropdown(
                                vec![
                                    ("Arial".into(), "Arial".into()),
                                    ("Helvetica".into(), "Helvetica".into()),
                                ],
                                |cx: &App| "Arial".into(),
                                |val: SharedString, cx: &mut App| {
                                    // Handle font change
                                },
                            )
                        ),
                        SettingItem::new(
                            "Font Size",
                            SettingField::number_input(
                                NumberFieldOptions {
                                    min: 8.0,
                                    max: 72.0,
                                    ..Default::default()
                                },
                                |cx: &App| 14.0,
                                |val: f64, cx: &mut App| {
                                    // Handle size change
                                },
                            )
                        ),
                    ]),
            ]),
        SettingPage::new("Software Update")
            .resettable(true)
            .group(
                SettingGroup::new()
                    .title("Updates")
                    .items(vec![
                        SettingItem::new(
                            "Auto Update",
                            SettingField::switch(
                                |cx: &App| true,
                                |val: bool, cx: &mut App| {
                                    // Handle auto update
                                },
                            )
                        )
                        .description("Automatically download and install updates."),
                    ])
            ),
    ])
SlintNo Slint version of this example yet.

#Setting Page

#Basic Page

SettingPage::new("General")
    .group(SettingGroup::new().title("Options").items(vec![...]))
SlintNo Slint version of this example yet.

#Multiple Groups

SettingPage::new("General")
    .groups(vec![
        SettingGroup::new().title("Appearance").items(vec![...]),
        SettingGroup::new().title("Font").items(vec![...]),
        SettingGroup::new().title("Other").items(vec![...]),
    ])
SlintNo Slint version of this example yet.

#Icon

SettingPage::new("General")
    .icon(IconName::Settings)
    .groups(vec![...])
SlintNo Slint version of this example yet.

#Title Suffix

Use title_suffix to render a custom element after the title in the page header, for example an info icon button that opens the help documentation:

SettingPage::new("General")
    .title_suffix(|_, _| {
        Button::new("help")
            .icon(IconName::Info)
            .ghost()
            .xsmall()
            .on_click(|_, _, cx| cx.open_url("https://example.com/help"))
    })
    .groups(vec![...])
SlintNo Slint version of this example yet.

#Default Open

SettingPage::new("General")
    .default_open(true)
    .groups(vec![...])
SlintNo Slint version of this example yet.

#resettable

Enable reset functionality for a page:

SettingPage::new("General")
    .resettable(true)
    .groups(vec![...])
SlintNo Slint version of this example yet.

#Setting Group

#Basic Group

SettingGroup::new()
    .title("Appearance")
    .items(vec![
        SettingItem::new(...),
        SettingItem::new(...),
    ])
SlintNo Slint version of this example yet.

#Single Item

SettingGroup::new()
    .title("Font")
    .item(SettingItem::new(...))
SlintNo Slint version of this example yet.

#Without Title

SettingGroup::new()
    .items(vec![...])
SlintNo Slint version of this example yet.

Use footer to render supporting content below the group’s background or border. It aligns with the group title and renders as small muted text like a description, so plain text is enough; the callback receives the current window and application context for richer content. It scrolls and is filtered with the group; it is not an independently searchable setting or a sidebar entry, and a group still needs at least one item to be shown.

SettingGroup::new()
    .item(SettingItem::new(
        "Update source",
        SettingField::render(|_, _, _| "GitHub Releases"),
    ))
    .footer(|_, _| "Changes apply to this device only.")
SlintNo Slint version of this example yet.

#Setting Item

#Basic Item

SettingItem::new("Title", SettingField::switch(...))
    .description("Description text")
SlintNo Slint version of this example yet.

#Custom Item with a render closure

You can create a fully custom setting item using SettingItem::render:

SettingItem::render(|options, _, _| {
    h_flex()
        .w_full()
        .justify_between()
        .child("Custom content")
        .child(
            Button::new("action")
                .label("Action")
                .with_size(options.size)
        )
        .into_any_element()
})
SlintNo Slint version of this example yet.

#Vertical Layout

By default, setting items use horizontal layout. Use layout(Axis::Vertical) for vertical layout:

SettingItem::new(
    "CLI Path",
    SettingField::input(...)
)
.layout(Axis::Vertical)
.description("This item uses vertical layout.")
SlintNo Slint version of this example yet.

#With Markdown Description

use gpui_kit::component::text::markdown;

SettingItem::new(
    "Documentation",
    SettingField::element(...)
)
.description(markdown("Rust doc for the `gpui-component` crate."))
SlintNo Slint version of this example yet.

#Disabled

Use disabled(true) to render a setting item in a non-interactive state. The whole row is dimmed and the built-in field (Switch, Checkbox, Input, Dropdown, NumberInput) is automatically disabled.

SettingItem::new(
    "Dark Mode",
    SettingField::switch(...)
)
.description("Switch between light and dark themes.")
.disabled(true)
SlintNo Slint version of this example yet.

For [SettingItem::render] custom items, the row is still dimmed automatically, but the renderer is responsible for honoring the disabled state on any interactive controls inside it via options.disabled:

SettingItem::render(|options, _, _| {
    h_flex()
        .child("Custom content")
        .child(
            Button::new("action")
                .label("Action")
                .with_size(options.size)
                .disabled(options.disabled)
        )
        .into_any_element()
})
.disabled(true)
SlintNo Slint version of this example yet.

#Search Keywords

Use keywords to attach additional search terms to an item. They are only used for search matching and are never rendered. For example, an item titled “Enable Two-factor auth” can be made searchable via “MFA”:

SettingItem::new(
    "Enable Two-factor auth",
    SettingField::switch(...)
)
.keywords(["MFA", "2FA"])
SlintNo Slint version of this example yet.

This is also useful for [SettingItem::render] custom items that have no title or description but should still appear in search results:

SettingItem::render(|options, _, _| {
    h_flex().child("Custom content").into_any_element()
})
.keywords(["Advanced", "Network"])
SlintNo Slint version of this example yet.

#Setting Fields

The SettingField enum provides different field types for various input needs.

#Switch

The switch field represents a boolean on/off state.

SettingItem::new(
    "Dark Mode",
    SettingField::switch(
        |cx: &App| cx.theme().mode.is_dark(),
        |val: bool, cx: &mut App| {
            // Handle value change
        },
    )
    .default_value(false)
)
SlintNo Slint version of this example yet.

#Checkbox

Like the switch, but uses a checkbox UI.

SettingItem::new(
    "Auto Switch Theme",
    SettingField::checkbox(
        |cx: &App| AppSettings::global(cx).auto_switch_theme,
        |val: bool, cx: &mut App| {
            AppSettings::global_mut(cx).auto_switch_theme = val;
        },
    )
    .default_value(false)
)
SlintNo Slint version of this example yet.

#Input

Display a single line text input.

SettingItem::new(
    "CLI Path",
    SettingField::input(
        |cx: &App| AppSettings::global(cx).cli_path.clone(),
        |val: SharedString, cx: &mut App| {
            AppSettings::global_mut(cx).cli_path = val;
        },
    )
    .default_value("/usr/local/bin/bash".into())
)
.layout(Axis::Vertical)
.description("Path to the CLI executable.")
SlintNo Slint version of this example yet.

A dropdown with a list of options.

SettingItem::new(
    "Font Family",
    SettingField::dropdown(
        vec![
            ("Arial".into(), "Arial".into()),
            ("Helvetica".into(), "Helvetica".into()),
            ("Times New Roman".into(), "Times New Roman".into()),
        ],
        |cx: &App| AppSettings::global(cx).font_family.clone(),
        |val: SharedString, cx: &mut App| {
            AppSettings::global_mut(cx).font_family = val;
        },
    )
    .default_value("Arial".into())
)
SlintNo Slint version of this example yet.

#NumberInput

use gpui_kit::component::setting::NumberFieldOptions;

SettingItem::new(
    "Font Size",
    SettingField::number_input(
        NumberFieldOptions {
            min: 8.0,
            max: 72.0,
            ..Default::default()
        },
        |cx: &App| AppSettings::global(cx).font_size,
        |val: f64, cx: &mut App| {
            AppSettings::global_mut(cx).font_size = val;
        },
    )
    .default_value(14.0)
)
SlintNo Slint version of this example yet.

#Custom Field by Render Closure

The SettingField::render method allows you to create a custom field using a closure that returns an element.

SettingItem::new(
    "GitHub Repository",
    SettingField::render(|options, _window, _cx| {
        Button::new("open-url")
            .outline()
            .label("Repository...")
            .with_size(options.size)
            .on_click(|_, _window, cx| {
                cx.open_url("https://github.com/example/repo");
            })
    })
)
SlintNo Slint version of this example yet.

#Custom Field Element

You may have a complex field that you want to reuse, you may want split the element into a separate struct to do the complex logic.

In this case, the SettingFieldElement trait can help you to create a custom field element.

use gpui_kit::component::setting::{SettingFieldElement, RenderOptions};

struct OpenURLSettingField {
    label: SharedString,
    url: SharedString,
}

impl SettingFieldElement for OpenURLSettingField {
    type Element = Button;

    fn render_field(&self, options: &RenderOptions, _: &mut Window, _: &mut App) -> Self::Element {
        let url = self.url.clone();
        Button::new("open-url")
            .outline()
            .label(self.label.clone())
            .with_size(options.size)
            .on_click(move |_, _window, cx| {
                cx.open_url(url.as_str());
            })
    }
}
SlintNo Slint version of this example yet.

Then use it in the setting item:

SettingItem::new(
    "GitHub Repository",
    SettingField::element(OpenURLSettingField {
        label: "Repository...".into(),
        url: "https://github.com/MohsenDastaran/uni-kit".into(),
    })
)
SlintNo Slint version of this example yet.

#API Reference

#Sizing

Implements Sizable trait:

  • xsmall() - Extra small size
  • small() - Small size
  • medium() - Medium size (default)
  • large() - Large size
  • with_size(Size) - Set specific size