DescriptionList

A versatile component for displaying key-value pairs in a structured, organized layout. Supports both horizontal and vertical layouts, multiple columns, borders, and different sizes. Perfect for showing detailed information like metadata, specifications, or summary data.

Install

#Import

use gpui_kit::component::description_list::{DescriptionList, DescriptionItem, DescriptionText};
// Installed in ui/components. That directory is on the Slint include path, so import by file name:
import { DescriptionItem, DescriptionLayout, DescriptionList } from "description-list.slint";
use iced::widget::{column, container, mouse_area, row, scrollable, svg, text};
use iced::{Alignment, Element, Length, Task, Theme};

#Usage

#Basic Description List

DescriptionList::new()
    .item("Name", "uni-kit", 1)
    .item("Version", "0.1.0", 1)
    .item("License", "Apache-2.0", 1)
DescriptionList {
    bordered: true;
    items: [
        root.entry("Name", "GPUI Kit", 1),
        root.entry("Version", "0.1.0", 1),
        root.entry("License", "Apache-2.0", 1),
    ];
}
// One bordered list at the medium insets: the Slint example's first
// `GroupBox`.
let basic = body_box(DescriptionList::new([
    Item::new("Name", "GPUI Kit"),
    Item::new("Version", "0.1.0"),
    Item::new("License", "Apache-2.0"),
]));

#Using DescriptionItem Builder

DescriptionList::new()
    .children([
        DescriptionItem::new("Name").value("uni-kit"),
        DescriptionItem::new("Description").value("UI components for building desktop applications"),
        DescriptionItem::new("Version").value("0.1.0"),
    ])
SlintNo Slint version of this example yet.

#Different Layouts

// Horizontal layout (default)
DescriptionList::horizontal()
    .item("Platform", "macOS, Windows, Linux", 1)
    .item("Repository", "https://github.com/MohsenDastaran/uni-kit", 1)

// Vertical layout
DescriptionList::vertical()
    .item("Name", "uni-kit", 1)
    .item("Description", "A comprehensive Rust desktop framework", 1)
VerticalLayout {
    spacing: 16px;
    Text {
        text: "Horizontal";
        color: Theme.muted-foreground;
        font-size: Theme.font-size-xs;
        font-weight: 500;
    }
    DescriptionList {
        layout: DescriptionLayout.horizontal;
        bordered: true;
        items: [
            root.entry("Platform", "macOS, Windows, Linux", 1),
            root.entry("Repository", "https://github.com/longbridge/gpui-kit", 1),
        ];
    }
    Text {
        text: "Vertical";
        color: Theme.muted-foreground;
        font-size: Theme.font-size-xs;
        font-weight: 500;
    }
    DescriptionList {
        layout: DescriptionLayout.vertical;
        bordered: true;
        items: [
            root.entry("Name", "GPUI Kit", 1),
            root.entry("Description", "A comprehensive Rust desktop framework", 1),
        ];
    }
}
// Horizontal (the default) beside the stacked form, each under the caption
// the Slint example writes above it.
let layouts = body_box(
    column![
        caption("Horizontal"),
        DescriptionList::new([
            Item::new("Platform", "macOS, Windows, Linux"),
            Item::new("Repository", "https://github.com/longbridge/gpui-kit"),
        ]),
        caption("Vertical"),
        DescriptionList::new([
            Item::new("Name", "GPUI Kit"),
            Item::new("Description", "A comprehensive Rust desktop framework"),
        ])
        .layout(Layout::Vertical),
    ]
    .spacing(theme::SPACING_LG),
);

#Multiple Columns with Spans

DescriptionList::new()
    .columns(3)
    .child(DescriptionItem::new("Name").value("uni-kit").span(1))
    .children([
        DescriptionItem::new("Version").value("0.1.0").span(1),
        DescriptionItem::new("License").value("Apache-2.0").span(1),
        DescriptionItem::new("Description")
            .value("Full-featured UI components for desktop applications")
            .span(3), // Spans all 3 columns
        DescriptionItem::new("Repository")
            .value("https://github.com/MohsenDastaran/uni-kit")
            .span(2), // Spans 2 columns
    ])
DescriptionList {
    columns: 3;
    bordered: true;
    items: [
        root.entry("Name", "GPUI Kit", 1),
        root.entry("Version", "0.1.0", 1),
        root.entry("License", "Apache-2.0", 1),
        root.entry("Description", "Full-featured UI components for desktop applications", 3),
        root.entry("Repository", "https://github.com/longbridge/gpui-kit", 2),
        root.entry("Author", "Longbridge", 1),
    ];
}
// Three columns; the description spans all three and the repository two.
let spans = body_box(
    DescriptionList::new([
        Item::new("Name", "GPUI Kit"),
        Item::new("Version", "0.1.0"),
        Item::new("License", "Apache-2.0"),
        Item::new(
            "Description",
            "Full-featured UI components for desktop applications",
        )
        .span(3),
        Item::new("Repository", "https://github.com/longbridge/gpui-kit").span(2),
        Item::new("Author", "Longbridge"),
    ])
    .columns(3),
);

#With Separators

DescriptionList::new()
    .item("Name", "uni-kit", 1)
    .item("Version", "0.1.0", 1)
    .separator() // Add a visual separator
    .item("Author", "Longbridge", 1)
    .item("License", "Apache-2.0", 1)
DescriptionList {
    bordered: true;
    items: [
        root.entry("Name", "GPUI Kit", 1),
        root.entry("Version", "0.1.0", 1),
        root.rule(),
        root.entry("Author", "Longbridge", 1),
        root.entry("License", "Apache-2.0", 1),
    ];
}
// The separator band between the version and the author.
let separators = body_box(DescriptionList::new([
    Item::new("Name", "GPUI Kit"),
    Item::new("Version", "0.1.0"),
    Item::separator(),
    Item::new("Author", "Longbridge"),
    Item::new("License", "Apache-2.0"),
]));

#Different Sizes

// Large size
DescriptionList::new()
    .large()
    .item("Title", "Large Description List", 1)

// Medium size (default)
DescriptionList::new()
    .item("Title", "Medium Description List", 1)

// Small size
DescriptionList::new()
    .small()
    .item("Title", "Small Description List", 1)
VerticalLayout {
    spacing: 16px;
    DescriptionList {
        size: ControlSize.large;
        bordered: true;
        items: [
            root.entry("Title", "Large Description List", 1)
        ];
    }
    DescriptionList {
        bordered: true;
        items: [
            root.entry("Title", "Medium Description List", 1)
        ];
    }
    DescriptionList {
        size: ControlSize.small;
        bordered: true;
        items: [
            root.entry("Title", "Small Description List", 1)
        ];
    }
}
// The three named steps: large, medium and small.
let sizes = body_box(
    column![
        DescriptionList::new([Item::new("Title", "Large Description List")])
            .size(ControlSize::Large),
        DescriptionList::new([Item::new("Title", "Medium Description List")]),
        DescriptionList::new([Item::new("Title", "Small Description List")])
            .size(ControlSize::Small),
    ]
    .spacing(theme::SPACING_LG),
);

#Without Borders

DescriptionList::new()
    .bordered(false) // Remove borders for a cleaner look
    .item("Name", "uni-kit", 1)
    .item("Type", "UI Library", 1)
DescriptionList {
    bordered: false;
    items: [
        root.entry("Name", "GPUI Kit", 1),
        root.entry("Type", "UI Library", 1),
    ];
}
// `bordered(false)` drops the surface edge, the label fill and the row rules.
let borderless = body_box(
    DescriptionList::new([
        Item::new("Name", "GPUI Kit"),
        Item::new("Type", "UI Library"),
    ])
    .bordered(false),
);

#Custom Label Width (Horizontal Layout)

use gpui_kit::px;

DescriptionList::horizontal()
    .label_width(px(200.0)) // Set custom label width
    .item("Very Long Label Name", "Short Value", 1)
    .item("Short", "Very long value that needs more space", 1)
DescriptionList {
    label-width: 200px;
    bordered: true;
    items: [
        root.entry("Very Long Label Name", "Short Value", 1),
        root.entry("Short", "Very long value that needs more space", 1),
    ];
}
// A 200px label column, so the long term keeps one line and the short one
// gives its space to the detail.
let label_width = body_box(
    DescriptionList::new([
        Item::new("Very Long Label Name", "Short Value"),
        Item::new("Short", "Very long value that needs more space"),
    ])
    .label_width(200.0),
);

#Rich Content with Custom Elements

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

DescriptionList::new()
    .columns(2)
    .children([
        DescriptionItem::new("Name").value("uni-kit"),
        DescriptionItem::new("Description").value(
            markdown(
                "UI components for building **fantastic** desktop applications.",
            ).into_any_element()
        ),
    ])
SlintNo Slint version of this example yet.

#Complex Example with Mixed Content

DescriptionList::new()
    .columns(3)
    .label_width(px(150.0))
    .children([
        DescriptionItem::new("Project Name").value("uni-kit").span(1),
        DescriptionItem::new("Version").value("0.1.0").span(1),
        DescriptionItem::new("Status").value("Active").span(1),

        DescriptionItem::Separator, // Full-width separator

        DescriptionItem::new("Description").value(
            "A comprehensive Rust desktop framework built on GPUI"
        ).span(3),

        DescriptionItem::new("Repository").value(
            "https://github.com/MohsenDastaran/uni-kit"
        ).span(2),
        DescriptionItem::new("License").value("Apache-2.0").span(1),

        DescriptionItem::new("Platforms").value("macOS, Windows, Linux").span(2),
        DescriptionItem::new("Language").value("Rust").span(1),
    ])
DescriptionList {
    columns: 3;
    label-width: 150px;
    bordered: true;
    items: [
        root.entry("Project Name", "GPUI Kit", 1),
        root.entry("Version", "0.1.0", 1),
        root.entry("Status", "Active", 1),
        root.rule(),
        root.entry("Description", "A comprehensive Rust desktop framework built on GPUI", 3),
        root.entry("Repository", "https://github.com/longbridge/gpui-kit", 2),
        root.entry("License", "Apache-2.0", 1),
        root.entry("Platforms", "macOS, Windows, Linux", 2),
        root.entry("Language", "Rust", 1),
    ];
}
// Three columns at a 150px label width, with a full-width rule and the
// spanned fields in the same arrangement as the Slint example.
let complex = body_box(
    DescriptionList::new([
        Item::new("Project Name", "GPUI Kit"),
        Item::new("Version", "0.1.0"),
        Item::new("Status", "Active"),
        Item::separator(),
        Item::new(
            "Description",
            "A comprehensive Rust desktop framework built on GPUI",
        )
        .span(3),
        Item::new("Repository", "https://github.com/longbridge/gpui-kit").span(2),
        Item::new("License", "Apache-2.0"),
        Item::new("Platforms", "macOS, Windows, Linux").span(2),
        Item::new("Language", "Rust"),
    ])
    .columns(3)
    .label_width(150.0),
);

#User Profile Information

DescriptionList::new()
    .columns(2)
    .bordered(true)
    .children([
        DescriptionItem::new("Full Name").value("John Doe"),
        DescriptionItem::new("Email").value("john@example.com"),
        DescriptionItem::new("Phone").value("+1 (555) 123-4567"),
        DescriptionItem::new("Department").value("Engineering"),
        DescriptionItem::Separator,
        DescriptionItem::new("Bio").value(
            "Senior software engineer with 10+ years of experience in Rust and system programming."
        ).span(2),
    ])
DescriptionList {
    columns: 2;
    bordered: true;
    items: [
        root.entry("Full Name", "Ada Lovelace", 1),
        root.entry("Email", "ada@uni.dev", 1),
        root.entry("Phone", "+1 (555) 123-4567", 1),
        root.entry("Department", "Engineering", 1),
        root.rule(),
        root.entry("Bio", "Senior software engineer with 10+ years of experience in Rust and system programming.", 2),
    ];
}
// Two columns, with the bio spanning both under a rule.
let profile = body_box(
    DescriptionList::new([
        Item::new("Full Name", "Ada Lovelace"),
        Item::new("Email", "ada@uni.dev"),
        Item::new("Phone", "+1 (555) 123-4567"),
        Item::new("Department", "Engineering"),
        Item::separator(),
        Item::new(
            "Bio",
            "Senior software engineer with 10+ years of experience in Rust and system programming.",
        )
        .span(2),
    ])
    .columns(2),
);

#System Information

DescriptionList::vertical()
    .small()
    .bordered(false)
    .children([
        DescriptionItem::new("Operating System").value("macOS 14.0"),
        DescriptionItem::new("Architecture").value("Apple Silicon (M2)"),
        DescriptionItem::new("Memory").value("16 GB"),
        DescriptionItem::new("Storage").value("512 GB SSD"),
        DescriptionItem::new("GPU").value("Apple M2 10-core GPU"),
    ])
DescriptionList {
    layout: DescriptionLayout.vertical;
    size: ControlSize.small;
    bordered: false;
    items: [
        root.entry("Operating System", "macOS 14.0", 1),
        root.entry("Architecture", "Apple Silicon (M2)", 1),
        root.entry("Memory", "16 GB", 1),
        root.entry("Storage", "512 GB SSD", 1),
        root.entry("GPU", "Apple M2 10-core GPU", 1),
    ];
}
// The stacked form at the small size, without borders.
let system = body_box(
    DescriptionList::new([
        Item::new("Operating System", "macOS 14.0"),
        Item::new("Architecture", "Apple Silicon (M2)"),
        Item::new("Memory", "16 GB"),
        Item::new("Storage", "512 GB SSD"),
        Item::new("GPU", "Apple M2 10-core GPU"),
    ])
    .layout(Layout::Vertical)
    .size(ControlSize::Small)
    .bordered(false),
);

#Product Specifications

DescriptionList::new()
    .columns(3)
    .large()
    .children([
        DescriptionItem::new("Model").value("MacBook Pro").span(1),
        DescriptionItem::new("Year").value("2023").span(1),
        DescriptionItem::new("Screen Size").value("14-inch").span(1),

        DescriptionItem::new("Processor").value("Apple M2 Pro").span(2),
        DescriptionItem::new("Base Price").value("$1,999").span(1),

        DescriptionItem::Separator,

        DescriptionItem::new("Key Features").value(
            "Liquid Retina XDR display, ProMotion technology, P3 wide color gamut"
        ).span(3),
    ])
DescriptionList {
    columns: 3;
    size: ControlSize.large;
    bordered: true;
    items: [
        root.entry("Model", "MacBook Pro", 1),
        root.entry("Year", "2023", 1),
        root.entry("Screen Size", "14-inch", 1),
        root.entry("Processor", "Apple M2 Pro", 2),
        root.entry("Base Price", "$1,999", 1),
        root.rule(),
        root.entry("Key Features", "Liquid Retina XDR display, ProMotion technology, P3 wide color gamut", 3),
    ];
}
// Three columns at the large size, with a rule and the key features
// spanning the row.
let specifications = body_box(
    DescriptionList::new([
        Item::new("Model", "MacBook Pro"),
        Item::new("Year", "2023"),
        Item::new("Screen Size", "14-inch"),
        Item::new("Processor", "Apple M2 Pro").span(2),
        Item::new("Base Price", "$1,999"),
        Item::separator(),
        Item::new(
            "Key Features",
            "Liquid Retina XDR display, ProMotion technology, P3 wide color gamut",
        )
        .span(3),
    ])
    .columns(3)
    .size(ControlSize::Large),
);

#Configuration Settings

DescriptionList::horizontal()
    .label_width(px(180.0))
    .bordered(false)
    .children([
        DescriptionItem::new("Theme").value("Dark Mode"),
        DescriptionItem::new("Font Size").value("14px"),
        DescriptionItem::new("Auto Save").value("Enabled"),
        DescriptionItem::new("Backup Frequency").value("Every 30 minutes"),
        DescriptionItem::new("Language").value("English (US)"),
    ])
DescriptionList {
    layout: DescriptionLayout.horizontal;
    label-width: 180px;
    bordered: false;
    items: [
        root.entry("Theme", "Dark Mode", 1),
        root.entry("Font Size", "14px", 1),
        root.entry("Auto Save", "Enabled", 1),
        root.entry("Backup Frequency", "Every 30 minutes", 1),
        root.entry("Language", "English (US)", 1),
    ];
}
// Horizontal at a 180px label width, without borders.
let settings = body_box(
    DescriptionList::new([
        Item::new("Theme", "Dark Mode"),
        Item::new("Font Size", "14px"),
        Item::new("Auto Save", "Enabled"),
        Item::new("Backup Frequency", "Every 30 minutes"),
        Item::new("Language", "English (US)"),
    ])
    .label_width(180.0)
    .bordered(false),
);

#Design Guidelines

  • Use horizontal layout for simple key-value pairs
  • Use vertical layout when values are lengthy or complex
  • Limit columns to 3-4 for optimal readability
  • Use separators to group related information
  • Keep labels concise and descriptive
  • Use consistent spacing with the size prop
  • Consider removing borders for embedded contexts