chore: audit all components (#2)

Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
2026-11-08 06:27:12 +00:00
parent 0ad5c3fe90
commit 11b29dc91a
51 changed files with 2096 additions and 958 deletions
+138 -18
View File
@@ -23,6 +23,10 @@ pub use system::{AccessibilityPreferences, PartialPalette, SourceKind, SystemThe
use gpui::{App, Global, Hsla, Pixels, WindowAppearance, px};
use std::time::Duration;
/// The hairline width of the control border every button and field paints;
/// sized outside the stated metrics so control sizes match across platforms.
pub const BORDER_WIDTH: Pixels = px(1.0);
/// Light or dark, resolved from the system appearance.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "lowercase")]
@@ -48,6 +52,9 @@ pub struct Theme {
pub colors: ColorTokens,
pub ramps: Ramps,
pub radius: Radius,
/// Per-platform border and focus chrome.
pub borders: Borders,
pub spacing: Spacing,
pub elevations: Elevations,
/// Overlay transition timing; gpui's animation primitives do the rest.
pub motion: Motion,
@@ -88,6 +95,59 @@ impl Default for Radius {
}
}
/// Which surfaces keep a 1px border, per the platform's chrome: Windows and
/// KDE frame their controls, macOS and GNOME paint fills.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Borders {
/// Filled actions keep a border (Windows, KDE).
pub buttons: bool,
/// Text fields and selects keep a border.
pub fields: bool,
/// Floating layers keep a border.
pub overlays: bool,
/// Keyboard focus paints an accent ring around the control.
pub focus_ring: bool,
}
impl Borders {
pub(crate) fn for_platform(source: SourceKind, variant: ThemeVariant) -> Self {
let overlays = variant == ThemeVariant::Dark;
match source {
SourceKind::Windows | SourceKind::Kde => Self {
buttons: true,
fields: true,
overlays: true,
focus_ring: false,
},
SourceKind::Macos => Self {
buttons: false,
fields: true,
overlays,
focus_ring: true,
},
SourceKind::Omarchy | SourceKind::Gnome => Self {
buttons: false,
fields: false,
overlays,
focus_ring: true,
},
SourceKind::Fallback => Self {
buttons: true,
fields: true,
overlays: true,
focus_ring: false,
},
}
}
}
/// The spacing rhythm of the platform: paddings and gaps step by this unit.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Spacing {
pub unit: Pixels,
}
/// One layer of a floating panel's drop shadow.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Shadow {
@@ -129,6 +189,13 @@ pub struct Elevation {
}
impl Elevation {
/// No shadow: dark floating layers separate by border.
fn none() -> Self {
Self {
layers: [Shadow::none(), Shadow::none()],
}
}
fn single(key: Shadow) -> Self {
Self {
layers: [key, Shadow::none()],
@@ -172,8 +239,8 @@ impl Elevations {
pub(crate) fn for_platform(source: SourceKind, variant: ThemeVariant) -> Self {
if variant == ThemeVariant::Dark {
return Self {
popover: Elevation::single(Shadow::black(0., 4., 24., 0.3)),
dialog: Elevation::single(Shadow::black(0., 8., 40., 0.35)),
popover: Elevation::none(),
dialog: Elevation::none(),
control: Elevation::single(Shadow::black(0., 1., 2., 0.25)),
};
}
@@ -283,12 +350,18 @@ pub struct ControlMetrics {
pub avatar_size: Pixels,
/// Dense label text.
pub caption_size: Pixels,
/// Tight horizontal padding inside pills, segments, and fields.
/// Tight horizontal padding inside pills, segments, fields, and icon-only buttons.
pub dense_padding_x: Pixels,
/// The inset between a control's edge and a raised inner plate.
pub plate_inset: Pixels,
/// The band height of multi-segment strips.
pub strip_height: Pixels,
/// The height of one menu row.
pub menu_item_height: Pixels,
/// Switch track height, width, and knob size.
pub switch_height: Pixels,
pub switch_width: Pixels,
pub switch_knob: Pixels,
}
/// The control metrics for every size class.
@@ -309,6 +382,7 @@ impl SizeTable {
avatar: f32,
strip: f32,
inset: f32,
floor_icon: bool,
}
let small = ClassFactors {
@@ -319,6 +393,7 @@ impl SizeTable {
avatar: 1.5,
strip: 1.5,
inset: 0.125,
floor_icon: false,
};
let medium = ClassFactors {
@@ -329,6 +404,7 @@ impl SizeTable {
avatar: 2.0,
strip: 2.0,
inset: 0.25,
floor_icon: true,
};
let large = ClassFactors {
@@ -339,21 +415,34 @@ impl SizeTable {
avatar: 3.0,
strip: 3.0,
inset: 0.375,
floor_icon: true,
};
let metrics = |f: &ClassFactors| ControlMetrics {
control_height: rem_size * f.height,
input_height: rem_size * (f.height + 0.125),
padding_x: rem_size * f.padding,
text_size: rem_size * f.text,
icon_size: rem_size * f.icon,
dense_icon_size: rem_size * f.icon * 0.75,
indicator_size: rem_size * f.height * 0.7,
avatar_size: rem_size * f.avatar,
caption_size: rem_size * f.text,
dense_padding_x: rem_size * f.padding * 0.75,
plate_inset: rem_size * f.inset,
strip_height: rem_size * f.strip,
let metrics = |f: &ClassFactors| {
let icon_size = if f.floor_icon {
(rem_size * f.icon).max(px(16.))
} else {
rem_size * f.icon
};
let switch_height = rem_size * f.height * 0.75;
ControlMetrics {
control_height: rem_size * f.height,
input_height: rem_size * (f.height + 0.125),
padding_x: rem_size * f.padding,
text_size: rem_size * f.text,
icon_size,
dense_icon_size: icon_size * 0.75,
indicator_size: rem_size * f.height * 0.7,
avatar_size: rem_size * f.avatar,
caption_size: rem_size * f.text,
dense_padding_x: rem_size * f.padding * 0.75,
plate_inset: rem_size * f.inset,
strip_height: rem_size * f.strip,
menu_item_height: rem_size * f.height * 0.85,
switch_height,
switch_width: switch_height * 2.25,
switch_knob: switch_height * 0.85,
}
};
let mut table = Self {
@@ -379,9 +468,38 @@ impl SizeTable {
/// Sets the medium class's text-field height to the platform's stated value.
pub fn set_input_height(&mut self, medium_input_height: Pixels) {
let ratio = medium_input_height / self.medium.input_height;
self.small.input_height *= ratio;
self.small.input_height = (self.small.input_height * ratio).floor();
self.medium.input_height = medium_input_height;
self.large.input_height *= ratio;
self.large.input_height = (self.large.input_height * ratio).floor();
}
/// Sets the medium class's control height to the platform's stated value.
pub fn set_control_height(&mut self, medium_control_height: Pixels) {
let ratio = medium_control_height / self.medium.control_height;
self.small.control_height = (self.small.control_height * ratio).floor();
self.medium.control_height = medium_control_height;
self.large.control_height = (self.large.control_height * ratio).floor();
}
/// Sets the medium class's menu row height to the platform's stated value.
pub fn set_menu_item_height(&mut self, medium_menu_item_height: Pixels) {
let ratio = medium_menu_item_height / self.medium.menu_item_height;
self.small.menu_item_height *= ratio;
self.medium.menu_item_height = medium_menu_item_height;
self.large.menu_item_height *= ratio;
}
/// Sets the medium class's switch dimensions to the platform's stated values.
pub fn set_switch_metrics(&mut self, track_height: Pixels, track_width: Pixels, knob: Pixels) {
let ratio = track_height / self.medium.switch_height;
for metrics in [&mut self.small, &mut self.large] {
metrics.switch_height *= ratio;
metrics.switch_width *= ratio;
metrics.switch_knob *= ratio;
}
self.medium.switch_height = track_height;
self.medium.switch_width = track_width;
self.medium.switch_knob = knob;
}
}
@@ -408,6 +526,8 @@ impl Theme {
colors: resolved.colors,
ramps: resolved.ramps,
radius: resolved.radius,
borders: resolved.borders,
spacing: resolved.spacing,
elevations: resolved.elevations,
motion: resolved.motion,
scrollbar: resolved.scrollbar,