commit 289aa858ed7249e293620d220c42bb5da5dfa191
parent 022c1e7a50653ed78630ac8a3e76b3140efa40c6
Author: triesap <tyson@radroots.org>
Date: Sun, 19 Apr 2026 17:58:57 +0000
ui: normalize layered theme contract
Diffstat:
4 files changed, 657 insertions(+), 549 deletions(-)
diff --git a/crates/launchers/desktop/src/window.rs b/crates/launchers/desktop/src/window.rs
@@ -33,11 +33,14 @@ use radroots_app_state::{
FarmSetupFlowStage, FarmWorkspaceStatus, HomeRoute, derive_product_publish_blockers,
};
use radroots_app_ui::{
- APP_UI_THEME, AppCheckboxFieldSpec, IconSegmentButtonSpec, LabelValueRow, action_button,
- action_button_compact, action_button_primary, action_button_primary_disabled,
- action_icon_button, app_checkbox_field, app_shared_label_text, app_shared_text, app_text_input,
- app_window_shell, icon_segment_button, label_value_list, section_divider, status_indicator,
- utility_title_row,
+ APP_UI_THEME, AppCheckboxFieldSpec, AppSegmentButtonIconSpec as IconSegmentButtonSpec,
+ LabelValueRow, app_button_compact as action_button_compact,
+ app_button_icon as action_icon_button, app_button_primary as action_button_primary,
+ app_button_primary_disabled as action_button_primary_disabled,
+ app_button_secondary as action_button, app_checkbox_field, app_divider as section_divider,
+ app_input_text as app_text_input, app_segment_button_icon as icon_segment_button,
+ app_shared_label_text, app_shared_text, app_status_indicator as status_indicator,
+ app_surface_window as app_window_shell, label_value_list, utility_title_row,
};
use radroots_nostr::prelude::RadrootsNostrClient;
use std::time::Duration;
@@ -111,8 +114,8 @@ pub fn home_window_options(cx: &mut App) -> WindowOptions {
fn home_window_launch_size_px() -> (f32, f32) {
(
- APP_UI_THEME.windows.home_min_width_px,
- APP_UI_THEME.windows.home_min_height_px,
+ APP_UI_THEME.shells.home_min_width_px,
+ APP_UI_THEME.shells.home_min_height_px,
)
}
@@ -124,8 +127,8 @@ pub fn settings_window_options(cx: &mut App) -> WindowOptions {
let bounds = Bounds::centered(
None,
size(
- px(APP_UI_THEME.windows.settings_width_px),
- px(APP_UI_THEME.windows.settings_height_px),
+ px(APP_UI_THEME.shells.settings_width_px),
+ px(APP_UI_THEME.shells.settings_height_px),
),
cx,
);
@@ -133,8 +136,8 @@ pub fn settings_window_options(cx: &mut App) -> WindowOptions {
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
window_min_size: Some(size(
- px(APP_UI_THEME.windows.settings_width_px),
- px(APP_UI_THEME.windows.settings_height_px),
+ px(APP_UI_THEME.shells.settings_width_px),
+ px(APP_UI_THEME.shells.settings_height_px),
)),
titlebar: Some(settings_titlebar_options()),
window_background: WindowBackgroundAppearance::Transparent,
@@ -1310,11 +1313,11 @@ impl HomeView {
div()
.w_full()
- .max_w(px(APP_UI_THEME.layout.home_card_max_width_px))
+ .max_w(px(APP_UI_THEME.shells.home_card_max_width_px))
.mx_auto()
.flex()
.flex_col()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(products_title_row(
runtime,
action_button_primary(
@@ -1329,7 +1332,7 @@ impl HomeView {
div()
.w_full()
.flex()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(home_summary_metric(
AppTextKey::ProductsSummaryTotal,
summary.total_products,
@@ -1484,7 +1487,7 @@ impl HomeView {
.w_full()
.flex()
.flex_col()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(products_table_row(product, row, action))
.when(is_editing, |this| {
this.when_some(self.products_stock_editor.as_ref(), |this, editor| {
@@ -3039,8 +3042,11 @@ impl SettingsWindowView {
}
fn account_panel(&self, cx: &mut Context<Self>) -> impl IntoElement {
- let detail_text_px = APP_UI_THEME.typography.settings_account_detail_text_px;
- let account_status_color = APP_UI_THEME.controls.status_indicator.offline;
+ let detail_text_px = APP_UI_THEME
+ .foundation
+ .typography
+ .settings_account_detail_text_px;
+ let account_status_color = APP_UI_THEME.components.app_status_indicator.offline;
div()
.size_full()
@@ -3048,22 +3054,22 @@ impl SettingsWindowView {
.child(
div()
.h_full()
- .w(px(APP_UI_THEME.layout.settings_account_sidebar_width_px))
- .p(px(APP_UI_THEME.layout.settings_account_sidebar_padding_px))
+ .w(px(APP_UI_THEME.shells.settings_account_sidebar_width_px))
+ .p(px(APP_UI_THEME.shells.settings_account_sidebar_padding_px))
.flex()
.flex_col()
.justify_between()
.child(
div()
.w_full()
- .bg(rgb(APP_UI_THEME.surfaces.chrome_background))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.chrome_background))
.rounded(px(
APP_UI_THEME
.layout
.settings_account_sidebar_button_corner_radius_px,
))
.p(px(
- APP_UI_THEME.layout.settings_account_sidebar_button_padding_px,
+ APP_UI_THEME.shells.settings_account_sidebar_button_padding_px,
))
.child(
div()
@@ -3078,7 +3084,7 @@ impl SettingsWindowView {
.settings_account_identity_text_px,
))
.font_weight(gpui::FontWeight::MEDIUM)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(app_shared_text(
AppTextKey::SettingsAccountNoSelectionTitle,
)),
@@ -3090,7 +3096,7 @@ impl SettingsWindowView {
.typography
.settings_account_identity_text_px,
))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.line_height(relative(1.2))
.child(app_shared_text(
AppTextKey::SettingsAccountNoSelectionBody,
@@ -3109,7 +3115,7 @@ impl SettingsWindowView {
.flex()
.flex_col()
.gap(px(
- APP_UI_THEME.layout.settings_account_sidebar_footer_row_gap_px,
+ APP_UI_THEME.shells.settings_account_sidebar_footer_row_gap_px,
))
.child(section_divider())
.child(
@@ -3141,14 +3147,14 @@ impl SettingsWindowView {
.child(
div()
.h_full()
- .w(px(APP_UI_THEME.layout.divider_thickness_px))
- .bg(rgb(APP_UI_THEME.surfaces.divider)),
+ .w(px(APP_UI_THEME.foundation.borders.divider_thickness_px))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.divider)),
)
.child(
div()
.flex_1()
.h_full()
- .p(px(APP_UI_THEME.layout.settings_account_main_padding_px))
+ .p(px(APP_UI_THEME.shells.settings_account_main_padding_px))
.flex()
.flex_col()
.items_center()
@@ -3156,18 +3162,18 @@ impl SettingsWindowView {
.child(
div()
.w_full()
- .max_w(px(APP_UI_THEME.layout.settings_account_content_max_width_px))
+ .max_w(px(APP_UI_THEME.shells.settings_account_content_max_width_px))
.flex()
.flex_col()
.items_start()
- .gap(px(APP_UI_THEME.layout.settings_account_main_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.settings_account_main_stack_gap_px))
.child(
div()
.w_full()
.flex()
.flex_col()
.items_center()
- .gap(px(APP_UI_THEME.layout.settings_account_main_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.settings_account_main_stack_gap_px))
.child(
div()
.size(px(
@@ -3175,7 +3181,7 @@ impl SettingsWindowView {
.layout
.settings_account_profile_avatar_size_px,
))
- .bg(rgb(APP_UI_THEME.surfaces.card_background))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.card_background))
.rounded(px(
APP_UI_THEME
.layout
@@ -3187,7 +3193,7 @@ impl SettingsWindowView {
div()
.text_size(px(detail_text_px))
.font_weight(gpui::FontWeight::MEDIUM)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(app_shared_text(
AppTextKey::SettingsAccountNoSelectionTitle,
)),
@@ -3198,12 +3204,12 @@ impl SettingsWindowView {
.w_full()
.flex()
.flex_col()
- .gap(px(APP_UI_THEME.layout.settings_account_detail_row_gap_px))
+ .gap(px(APP_UI_THEME.shells.settings_account_detail_row_gap_px))
.child(self.settings_account_detail_row(
AppTextKey::SettingsAccountProfileLabel,
div()
.text_size(px(detail_text_px))
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(app_shared_text(AppTextKey::ValueNone)),
))
.child(self.settings_account_detail_row(
@@ -3220,7 +3226,7 @@ impl SettingsWindowView {
.child(
div()
.text_size(px(detail_text_px))
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(app_shared_text(
AppTextKey::SettingsAccountStatusLoggedOut,
)),
@@ -3230,21 +3236,21 @@ impl SettingsWindowView {
AppTextKey::SettingsAccountCustodyLabel,
div()
.text_size(px(detail_text_px))
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(app_shared_text(AppTextKey::ValueNone)),
))
.child(self.settings_account_detail_row(
AppTextKey::SettingsAccountSurfaceLabel,
div()
.text_size(px(detail_text_px))
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(app_shared_text(AppTextKey::ValueNone)),
))
.child(self.settings_account_detail_row(
AppTextKey::SettingsAccountActivationLabel,
div()
.text_size(px(detail_text_px))
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(app_shared_text(
AppTextKey::SettingsAccountActivationInactive,
)),
@@ -3254,7 +3260,7 @@ impl SettingsWindowView {
.w_full()
.text_size(px(detail_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_text(
AppTextKey::SettingsAccountNoSelectionBody,
)),
@@ -3305,12 +3311,15 @@ impl SettingsWindowView {
.w_full()
.flex()
.items_center()
- .gap(px(APP_UI_THEME.layout.settings_account_detail_value_gap_px))
+ .gap(px(APP_UI_THEME.shells.settings_account_detail_value_gap_px))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.settings_account_detail_text_px))
+ .text_size(px(APP_UI_THEME
+ .foundation
+ .typography
+ .settings_account_detail_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_label_text(label_key)),
)
.child(value)
@@ -3334,7 +3343,7 @@ impl SettingsWindowView {
.w_full()
.flex()
.items_start()
- .gap(px(APP_UI_THEME.layout.settings_account_detail_value_gap_px))
+ .gap(px(APP_UI_THEME.shells.settings_account_detail_value_gap_px))
.child(app_checkbox_field(
AppCheckboxFieldSpec::new(id, app_shared_text(label_key), note_text),
checked,
@@ -3782,7 +3791,7 @@ impl SettingsWindowView {
.overflow_y_scroll()
.child(
div()
- .p(px(APP_UI_THEME.layout.settings_content_padding_px))
+ .p(px(APP_UI_THEME.shells.settings_content_padding_px))
.size_full()
.flex()
.flex_col()
@@ -3793,9 +3802,9 @@ impl SettingsWindowView {
.flex()
.flex_col()
.justify_between()
- .gap(px(APP_UI_THEME.layout.settings_account_main_stack_gap_px))
- .text_size(px(APP_UI_THEME.typography.body_text_px))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .gap(px(APP_UI_THEME.shells.settings_account_main_stack_gap_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_text(
AppTextKey::SettingsAboutPlaceholderTopPrimary,
))
@@ -3811,8 +3820,8 @@ impl SettingsWindowView {
div()
.w_full()
.py_12()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_text(AppTextKey::SettingsAboutPlaceholderMiddle)),
)
.child(section_divider())
@@ -3820,8 +3829,8 @@ impl SettingsWindowView {
div()
.w_full()
.py_12()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_text(AppTextKey::SettingsAboutPlaceholderBottom)),
),
)
@@ -3850,18 +3859,18 @@ impl Render for SettingsWindowView {
.collect::<Vec<_>>();
app_window_shell(
- APP_UI_THEME.surfaces.panel_background,
+ APP_UI_THEME.foundation.surfaces.panel_background,
div()
.size_full()
- .bg(rgb(APP_UI_THEME.surfaces.panel_background))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.panel_background))
.overflow_hidden()
.flex()
.flex_col()
.child(
div()
.w_full()
- .h(px(APP_UI_THEME.layout.settings_chrome_height_px))
- .bg(rgb(APP_UI_THEME.surfaces.chrome_background))
+ .h(px(APP_UI_THEME.shells.settings_chrome_height_px))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.chrome_background))
.flex()
.flex_col()
.child(utility_title_row(app_shared_text(
@@ -3872,9 +3881,9 @@ impl Render for SettingsWindowView {
.w_full()
.flex()
.justify_center()
- .pt(px(APP_UI_THEME.layout.settings_navigation_row_padding_px))
- .pb(px(APP_UI_THEME.layout.settings_navigation_row_padding_px))
- .gap(px(APP_UI_THEME.layout.settings_navigation_row_gap_px))
+ .pt(px(APP_UI_THEME.shells.settings_navigation_row_padding_px))
+ .pb(px(APP_UI_THEME.shells.settings_navigation_row_padding_px))
+ .gap(px(APP_UI_THEME.shells.settings_navigation_row_gap_px))
.children(navigation_buttons),
),
)
@@ -4048,11 +4057,11 @@ fn holding_home_shell(runtime: &DesktopAppRuntimeSummary) -> impl IntoElement {
.child(
div()
.w_full()
- .max_w(px(APP_UI_THEME.layout.home_card_max_width_px))
+ .max_w(px(APP_UI_THEME.shells.home_card_max_width_px))
.mx_auto()
.flex()
.flex_col()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(home_status_row(&home_status))
.children(sections),
)
@@ -4097,14 +4106,14 @@ fn startup_home_shell(
let surface = startup_home_surface(runtime);
app_window_shell(
- APP_UI_THEME.surfaces.window_background,
+ APP_UI_THEME.foundation.surfaces.window_background,
div()
.size_full()
- .bg(rgb(APP_UI_THEME.surfaces.window_background))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.window_background))
.child(
div()
.size_full()
- .p(px(APP_UI_THEME.layout.home_window_padding_px))
+ .p(px(APP_UI_THEME.shells.home_window_padding_px))
.child(
div()
.size_full()
@@ -4114,12 +4123,12 @@ fn startup_home_shell(
.child(
div()
.w_full()
- .max_w(px(APP_UI_THEME.layout.home_card_max_width_px))
+ .max_w(px(APP_UI_THEME.shells.home_card_max_width_px))
.mx_auto()
.flex()
.flex_col()
.items_center()
- .gap(px(APP_UI_THEME.layout.startup_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.startup_stack_gap_px))
.child(startup_home_title(surface))
.child(startup_home_tagline())
.child(match surface {
@@ -4127,7 +4136,7 @@ fn startup_home_shell(
.flex()
.flex_col()
.items_center()
- .gap(px(APP_UI_THEME.layout.startup_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.startup_stack_gap_px))
.child(action_button_primary(
"home-continue",
app_shared_text(
@@ -4146,7 +4155,7 @@ fn startup_home_shell(
.flex()
.flex_col()
.items_center()
- .gap(px(APP_UI_THEME.layout.startup_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.startup_stack_gap_px))
.child(action_button_primary(
"home-generate-key",
app_shared_text(
@@ -4173,7 +4182,7 @@ fn startup_home_shell(
.flex()
.flex_col()
.items_center()
- .gap(px(APP_UI_THEME.layout.startup_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.startup_stack_gap_px))
.child(action_button_primary_disabled(
"home-generate-key",
app_shared_text(
@@ -4213,9 +4222,9 @@ fn startup_home_title(surface: StartupHomeSurface) -> impl IntoElement {
};
div()
- .text_size(px(APP_UI_THEME.typography.startup_title_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.startup_title_text_px))
.font_weight(gpui::FontWeight::NORMAL)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.text_center()
.child(app_shared_text(title_key))
.with_animation(
@@ -4227,18 +4236,21 @@ fn startup_home_title(surface: StartupHomeSurface) -> impl IntoElement {
fn startup_home_tagline() -> impl IntoElement {
div()
- .text_size(px(APP_UI_THEME.typography.startup_tagline_text_px))
+ .text_size(px(APP_UI_THEME
+ .foundation
+ .typography
+ .startup_tagline_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.text_center()
.child(app_shared_text(AppTextKey::HomeSetupTagline))
}
fn startup_home_support_text(body: impl Into<SharedString>) -> impl IntoElement {
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.text_center()
.child(body.into())
}
@@ -4272,12 +4284,12 @@ fn startup_signer_entry_surface(
.flex()
.flex_col()
.items_center()
- .gap(px(APP_UI_THEME.layout.startup_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.startup_stack_gap_px))
.when_some(signer_entry, |this, signer_entry| {
this.child(
div()
.w_full()
- .max_w(px(APP_UI_THEME.layout.home_card_max_width_px))
+ .max_w(px(APP_UI_THEME.shells.home_card_max_width_px))
.id("home-signer-source-input")
.child(
app_text_input(&signer_entry.input, !source_input_is_editable)
@@ -4471,7 +4483,7 @@ fn startup_text_button(
.custom(
ButtonCustomVariant::new(cx)
.color(transparent_black().into())
- .foreground(rgb(APP_UI_THEME.text.secondary).into())
+ .foreground(rgb(APP_UI_THEME.foundation.text.secondary).into())
.border(transparent_black())
.hover(transparent_black().into())
.active(transparent_black().into()),
@@ -4480,9 +4492,9 @@ fn startup_text_button(
.on_click(on_click)
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::MEDIUM)
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_text(key)),
)
}
@@ -4490,7 +4502,7 @@ fn startup_text_button(
fn startup_home_card(title: impl Into<SharedString>, body: impl IntoElement) -> impl IntoElement {
div()
.w_full()
- .bg(rgb(APP_UI_THEME.surfaces.card_background))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.card_background))
.rounded(px(APP_UI_THEME
.controls
.action_button
@@ -4499,16 +4511,16 @@ fn startup_home_card(title: impl Into<SharedString>, body: impl IntoElement) ->
.child(
div()
.w_full()
- .p(px(APP_UI_THEME.layout.home_card_padding_px))
+ .p(px(APP_UI_THEME.shells.home_card_padding_px))
.flex()
.flex_col()
.items_center()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(title.into()),
)
.child(body),
@@ -4523,9 +4535,9 @@ fn startup_home_body(runtime: &DesktopAppRuntimeSummary) -> impl IntoElement {
div()
.w_full()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.text_center()
.child(body)
}
@@ -4580,7 +4592,7 @@ async fn run_startup_signer_pending_poll(
fn home_shell_frame(sidebar: AnyElement, main_content: AnyElement) -> impl IntoElement {
app_window_shell(
- APP_UI_THEME.surfaces.window_background,
+ APP_UI_THEME.foundation.surfaces.window_background,
div()
.size_full()
.overflow_hidden()
@@ -4589,19 +4601,19 @@ fn home_shell_frame(sidebar: AnyElement, main_content: AnyElement) -> impl IntoE
.child(
div()
.h_full()
- .w(px(APP_UI_THEME.layout.divider_thickness_px))
- .bg(rgb(APP_UI_THEME.surfaces.divider)),
+ .w(px(APP_UI_THEME.foundation.borders.divider_thickness_px))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.divider)),
)
.child(
div()
.flex_1()
.h_full()
- .bg(rgb(APP_UI_THEME.surfaces.window_background))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.window_background))
.overflow_hidden()
.child(
div()
.size_full()
- .p(px(APP_UI_THEME.layout.home_window_padding_px))
+ .p(px(APP_UI_THEME.shells.home_window_padding_px))
.child(main_content),
),
),
@@ -4619,9 +4631,9 @@ fn home_sidebar(
div()
.h_full()
- .w(px(APP_UI_THEME.layout.home_sidebar_width_px))
- .bg(rgb(APP_UI_THEME.surfaces.card_background))
- .p(px(APP_UI_THEME.layout.home_window_padding_px))
+ .w(px(APP_UI_THEME.shells.home_sidebar_width_px))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.card_background))
+ .p(px(APP_UI_THEME.shells.home_window_padding_px))
.flex()
.flex_col()
.justify_between()
@@ -4631,7 +4643,7 @@ fn home_sidebar(
.flex()
.flex_col()
.justify_start()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(home_sidebar_nav_button(
"home-nav-today",
AppTextKey::HomeNavToday,
@@ -4652,9 +4664,9 @@ fn home_sidebar(
.child(
div().child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.when_some(home_saved_farm(runtime), |this, farm| {
this.child(farm.display_name.clone())
}),
@@ -4665,9 +4677,9 @@ fn home_sidebar(
fn holding_home_sidebar(runtime: &DesktopAppRuntimeSummary) -> impl IntoElement {
div()
.h_full()
- .w(px(APP_UI_THEME.layout.home_sidebar_width_px))
- .bg(rgb(APP_UI_THEME.surfaces.card_background))
- .p(px(APP_UI_THEME.layout.home_window_padding_px))
+ .w(px(APP_UI_THEME.shells.home_sidebar_width_px))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.card_background))
+ .p(px(APP_UI_THEME.shells.home_window_padding_px))
.flex()
.flex_col()
.justify_between()
@@ -4675,21 +4687,21 @@ fn holding_home_sidebar(runtime: &DesktopAppRuntimeSummary) -> impl IntoElement
div()
.flex()
.flex_col()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px * 2.0))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px * 2.0))
.font_weight(gpui::FontWeight::BOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(app_shared_text(AppTextKey::HomeTodayTitle)),
),
)
.child(
div().child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.when_some(home_saved_farm(runtime), |this, farm| {
this.child(farm.display_name.clone())
}),
@@ -4855,11 +4867,11 @@ fn home_today_content(
div()
.w_full()
- .max_w(px(APP_UI_THEME.layout.home_card_max_width_px))
+ .max_w(px(APP_UI_THEME.shells.home_card_max_width_px))
.mx_auto()
.flex()
.flex_col()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(
div()
.w_full()
@@ -4868,17 +4880,17 @@ fn home_today_content(
.gap(px(4.0))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px * 2.0))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px * 2.0))
.font_weight(gpui::FontWeight::BOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(app_shared_text(AppTextKey::HomeTodayTitle)),
)
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::MEDIUM)
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.when_some(home_saved_farm(runtime), |this, farm| {
this.child(farm.display_name.clone())
})
@@ -4920,7 +4932,13 @@ fn home_sidebar_nav_button(
cx: &App,
) -> impl IntoElement {
if is_active {
- action_button_primary(id, app_shared_text(key), on_click, cx).into_any_element()
+ div()
+ .id(id)
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px * 2.0))
+ .font_weight(gpui::FontWeight::BOLD)
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
+ .child(app_shared_text(key))
+ .into_any_element()
} else {
action_button(id, app_shared_text(key), on_click, cx).into_any_element()
}
@@ -4935,7 +4953,7 @@ fn products_title_row(
.flex()
.items_end()
.justify_between()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(
div()
.flex()
@@ -4943,17 +4961,17 @@ fn products_title_row(
.gap(px(4.0))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px * 2.0))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px * 2.0))
.font_weight(gpui::FontWeight::BOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(app_shared_text(AppTextKey::ProductsTitle)),
)
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::MEDIUM)
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.when_some(home_saved_farm(runtime), |this, farm| {
this.child(farm.display_name.clone())
}),
@@ -4987,7 +5005,7 @@ fn products_controls_card(
.w_full()
.flex()
.flex_col()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.when_some(products_search, |this, products_search| {
this.child(
app_text_input(&products_search.input, false)
@@ -5050,12 +5068,12 @@ fn products_controls_card(
.flex()
.items_center()
.justify_between()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_text(AppTextKey::ProductsSortTitle)),
)
.child(
@@ -5122,7 +5140,7 @@ fn products_table_header() -> impl IntoElement {
.w_full()
.flex()
.items_center()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(products_table_header_column(
AppTextKey::ProductsColumnProduct,
None,
@@ -5168,9 +5186,9 @@ fn products_table_header_column(
div()
.when_some(width_px, |this, width_px| this.w(px(width_px)))
.when(grows, |this| this.flex_1().min_w_0())
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_text(key))
}
@@ -5183,7 +5201,7 @@ fn products_table_row(
.w_full()
.flex()
.items_center()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(product)
.child(
div()
@@ -5194,41 +5212,41 @@ fn products_table_row(
.child(status_indicator(products_row_status_color(row)))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(app_shared_text(products_status_key(row.status))),
),
)
.child(
div()
.w(px(192.0))
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(row.availability.label.clone()),
)
.child(
div()
.w(px(128.0))
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(products_stock_text(row)),
)
.child(
div()
.w(px(128.0))
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(products_price_text(row)),
)
.child(
div()
.w(px(164.0))
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(row.updated_at.clone()),
)
.child(div().w(px(120.0)).flex().justify_end().child(action))
@@ -5241,7 +5259,7 @@ fn products_row_open_button(
on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
cx: &App,
) -> impl IntoElement {
- let selected_background = rgb(APP_UI_THEME.surfaces.window_background);
+ let selected_background = rgb(APP_UI_THEME.foundation.surfaces.window_background);
Button::new(id)
.custom(
@@ -5251,7 +5269,7 @@ fn products_row_open_button(
} else {
transparent_black().into()
})
- .foreground(rgb(APP_UI_THEME.text.primary).into())
+ .foreground(rgb(APP_UI_THEME.foundation.text.primary).into())
.border(transparent_black())
.hover(selected_background.into())
.active(selected_background.into()),
@@ -5275,17 +5293,17 @@ fn products_row_open_button(
.py(px(6.0))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::MEDIUM)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(product_display_title(row.title.as_str())),
)
.when_some(row.subtitle.as_ref(), |this, subtitle| {
this.child(
div()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(subtitle.clone()),
)
}),
@@ -5319,12 +5337,12 @@ fn products_status_key(status: ProductStatus) -> AppTextKey {
fn products_row_status_color(row: &ProductsListRow) -> u32 {
if row.attention_state != ProductAttentionState::Healthy {
- APP_UI_THEME.controls.status_indicator.attention
+ APP_UI_THEME.components.app_status_indicator.attention
} else {
match row.status {
- ProductStatus::Published => APP_UI_THEME.controls.status_indicator.online,
+ ProductStatus::Published => APP_UI_THEME.components.app_status_indicator.online,
ProductStatus::Draft | ProductStatus::Paused | ProductStatus::Archived => {
- APP_UI_THEME.controls.status_indicator.offline
+ APP_UI_THEME.components.app_status_indicator.offline
}
}
}
@@ -5356,8 +5374,8 @@ fn products_row_action_button(
on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
cx: &App,
) -> impl IntoElement {
- let sizing = APP_UI_THEME.controls.action_button.sizing;
- let colors = APP_UI_THEME.controls.action_button.colors;
+ let sizing = APP_UI_THEME.components.app_button.sizing;
+ let colors = APP_UI_THEME.components.app_button.colors;
Button::new(id)
.custom(
@@ -5396,7 +5414,7 @@ fn products_stock_editor_card(
div()
.w_full()
- .bg(rgb(APP_UI_THEME.surfaces.window_background))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.window_background))
.rounded(px(APP_UI_THEME
.controls
.action_button
@@ -5414,16 +5432,16 @@ fn products_stock_editor_card(
.gap(px(2.0))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(app_shared_text(AppTextKey::ProductsStockEditorTitle)),
)
.child(
div()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(product_display_title(row.title.as_str())),
),
)
@@ -5432,7 +5450,7 @@ fn products_stock_editor_card(
.w_full()
.flex()
.items_end()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(
div()
.flex_1()
@@ -5442,27 +5460,36 @@ fn products_stock_editor_card(
.gap(px(6.0))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME
+ .foundation
+ .typography
+ .utility_title_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_text(AppTextKey::ProductsStockEditorFieldLabel)),
)
.child(app_text_input(&editor.input, false).w_full())
.when_some(validation_key, |this, key| {
this.child(
div()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME
+ .foundation
+ .typography
+ .utility_title_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_text(key)),
)
})
.when(editor.save_failed, |this| {
this.child(
div()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME
+ .foundation
+ .typography
+ .utility_title_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_text(
AppTextKey::ProductsStockEditorSaveFailed,
)),
@@ -5532,7 +5559,7 @@ fn products_editor_surface(
.w_full()
.flex()
.flex_col()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(home_body_text(app_shared_text(
AppTextKey::ProductsEditorBody,
)))
@@ -5581,11 +5608,14 @@ fn products_editor_surface(
.flex()
.items_center()
.justify_between()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_size(px(APP_UI_THEME
+ .foundation
+ .typography
+ .utility_title_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(product_display_title(
form.title_input.read(cx).value().as_ref(),
)),
@@ -5738,9 +5768,9 @@ fn products_editor_publish_blocker_row(blocker: ProductPublishBlocker) -> AnyEle
.w_full()
.flex()
.items_start()
- .gap(px(APP_UI_THEME.layout.settings_account_status_gap_px))
+ .gap(px(APP_UI_THEME.shells.settings_account_status_gap_px))
.child(status_indicator(
- APP_UI_THEME.controls.status_indicator.attention,
+ APP_UI_THEME.components.app_status_indicator.attention,
))
.child(home_body_text(app_shared_text(
products_editor_publish_blocker_key(blocker),
@@ -5887,7 +5917,7 @@ fn home_farm_setup_onboarding_card(
.flex()
.flex_col()
.items_start()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(home_body_text(app_shared_text(spec.body_key)))
.when_some(spec.action_key, |this, action_key| {
this.child(div().child(action_button_primary(
@@ -5918,7 +5948,7 @@ fn home_farm_setup_form_card(
.flex()
.flex_col()
.items_start()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(home_body_text(app_shared_text(
AppTextKey::HomeFarmSetupOnboardingBody,
)))
@@ -5954,7 +5984,7 @@ fn home_farm_setup_form_card(
.flex()
.flex_col()
.items_start()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(home_body_text(app_shared_text(farm_setup_save_state_key(
form.save_state,
))))
@@ -6072,25 +6102,25 @@ fn home_farm_setup_order_method_section(
fn home_farm_setup_section_label(key: AppTextKey) -> impl IntoElement {
div()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_text(key))
}
fn home_farm_setup_field_label(key: AppTextKey) -> impl IntoElement {
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::MEDIUM)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(app_shared_text(key))
}
fn home_farm_setup_blocker(key: AppTextKey) -> impl IntoElement {
div()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_text(key))
}
@@ -6187,7 +6217,7 @@ fn settings_pickup_location_card(
div()
.w_full()
- .bg(rgb(APP_UI_THEME.surfaces.chrome_background))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.chrome_background))
.rounded(px(APP_UI_THEME
.controls
.action_button
@@ -6206,9 +6236,9 @@ fn settings_pickup_location_card(
.gap(px(8.0))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(title),
)
.child(action_row),
@@ -6289,7 +6319,7 @@ fn settings_fulfillment_window_card(
) -> impl IntoElement {
div()
.w_full()
- .bg(rgb(APP_UI_THEME.surfaces.chrome_background))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.chrome_background))
.rounded(px(APP_UI_THEME
.controls
.action_button
@@ -6308,9 +6338,9 @@ fn settings_fulfillment_window_card(
.gap(px(8.0))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(settings_fulfillment_window_title(
index,
fulfillment_window,
@@ -6374,7 +6404,7 @@ fn settings_blackout_period_card(
) -> impl IntoElement {
div()
.w_full()
- .bg(rgb(APP_UI_THEME.surfaces.chrome_background))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.chrome_background))
.rounded(px(APP_UI_THEME
.controls
.action_button
@@ -6393,9 +6423,9 @@ fn settings_blackout_period_card(
.gap(px(8.0))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(settings_blackout_period_title(index, blackout_period, cx)),
)
.child(
@@ -6474,9 +6504,9 @@ fn settings_timing_conflict_key(kind: FarmTimingConflictKind) -> AppTextKey {
fn settings_badge_text(key: AppTextKey) -> impl IntoElement {
div()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.accent))
+ .text_color(rgb(APP_UI_THEME.foundation.text.accent))
.child(app_shared_text(key))
}
@@ -6487,11 +6517,11 @@ fn settings_dynamic_action_button(
on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
cx: &App,
) -> impl IntoElement {
- let sizing = APP_UI_THEME.controls.action_button.sizing;
+ let sizing = APP_UI_THEME.components.app_button.sizing;
let colors = if is_primary {
- APP_UI_THEME.controls.action_button.primary_colors
+ APP_UI_THEME.components.app_button.primary_colors
} else {
- APP_UI_THEME.controls.action_button.colors
+ APP_UI_THEME.components.app_button.colors
};
let hover_background = if colors.hover_changes_background {
colors.hover_background
@@ -6535,7 +6565,7 @@ fn settings_inventory_panel(intro_key: AppTextKey, cards: Vec<AnyElement>) -> im
.child(
div()
.w_full()
- .p(px(APP_UI_THEME.layout.settings_content_padding_px))
+ .p(px(APP_UI_THEME.shells.settings_content_padding_px))
.flex()
.flex_col()
.items_center()
@@ -6545,7 +6575,7 @@ fn settings_inventory_panel(intro_key: AppTextKey, cards: Vec<AnyElement>) -> im
.max_w(px(content_max_width_px))
.flex()
.flex_col()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(home_body_text(app_shared_text(intro_key)))
.children(cards),
),
@@ -6570,7 +6600,7 @@ fn settings_inventory_card(spec: SettingsInventorySectionSpec) -> impl IntoEleme
fn settings_inventory_field_row(key: AppTextKey) -> impl IntoElement {
div()
.w_full()
- .bg(rgb(APP_UI_THEME.surfaces.chrome_background))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.chrome_background))
.rounded(px(APP_UI_THEME
.controls
.action_button
@@ -6620,7 +6650,7 @@ fn home_saved_farm_summary_card(runtime: &DesktopAppRuntimeSummary) -> Option<An
fn home_card(title: impl Into<SharedString>, body: impl IntoElement) -> impl IntoElement {
div()
.w_full()
- .bg(rgb(APP_UI_THEME.surfaces.card_background))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.card_background))
.rounded(px(APP_UI_THEME
.controls
.action_button
@@ -6629,15 +6659,15 @@ fn home_card(title: impl Into<SharedString>, body: impl IntoElement) -> impl Int
.child(
div()
.w_full()
- .p(px(APP_UI_THEME.layout.home_card_padding_px))
+ .p(px(APP_UI_THEME.shells.home_card_padding_px))
.flex()
.flex_col()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(title.into()),
)
.child(body),
@@ -6647,9 +6677,9 @@ fn home_card(title: impl Into<SharedString>, body: impl IntoElement) -> impl Int
fn home_body_text(body: impl Into<SharedString>) -> impl IntoElement {
div()
.w_full()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(body.into())
}
@@ -6657,12 +6687,12 @@ fn home_status_row(status: &HomeStatusPresentation) -> impl IntoElement {
div()
.flex()
.items_center()
- .gap(px(APP_UI_THEME.layout.settings_account_status_gap_px))
+ .gap(px(APP_UI_THEME.shells.settings_account_status_gap_px))
.child(status_indicator(status.indicator_color))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_text(status.label_key)),
)
}
@@ -6673,7 +6703,7 @@ fn home_summary_card(summary: &radroots_app_models::TodaySummary) -> impl IntoEl
div()
.w_full()
.flex()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(home_summary_metric(
AppTextKey::HomeTodayOrdersNeedingAction,
summary.orders_needing_action,
@@ -6693,7 +6723,7 @@ fn home_summary_metric(label_key: AppTextKey, value: u32) -> impl IntoElement {
div()
.flex_1()
.min_w_0()
- .bg(rgb(APP_UI_THEME.surfaces.window_background))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.window_background))
.rounded(px(APP_UI_THEME
.controls
.action_button
@@ -6705,16 +6735,16 @@ fn home_summary_metric(label_key: AppTextKey, value: u32) -> impl IntoElement {
.gap(px(4.0))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px * 2.0))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px * 2.0))
.font_weight(gpui::FontWeight::BOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(value.to_string()),
)
.child(
div()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
.line_height(relative(1.2))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_text(label_key)),
)
}
@@ -6761,7 +6791,7 @@ fn home_list_card(
.w_full()
.flex()
.flex_col()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.children(rows)
.when_some(action, |this, action| this.child(div().child(action))),
)
@@ -6774,7 +6804,7 @@ fn home_order_row(order: &OrderListRow) -> AnyElement {
.flex()
.items_center()
.justify_between()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(
div()
.min_w_0()
@@ -6783,20 +6813,20 @@ fn home_order_row(order: &OrderListRow) -> AnyElement {
.gap(px(2.0))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(order.order_number.clone()),
)
.child(
div()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(order.customer_display_name.clone()),
),
)
.child(status_indicator(
- APP_UI_THEME.controls.status_indicator.attention,
+ APP_UI_THEME.components.app_status_indicator.attention,
))
.into_any_element()
}
@@ -6808,22 +6838,22 @@ fn home_low_stock_row(product: &ProductListRow) -> AnyElement {
.flex()
.items_center()
.justify_between()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(
div()
.min_w_0()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(product_display_title(product.title.as_str())),
)
.child(
div()
.flex()
.items_center()
- .gap(px(APP_UI_THEME.layout.settings_account_status_gap_px))
+ .gap(px(APP_UI_THEME.shells.settings_account_status_gap_px))
.child(status_indicator(
- APP_UI_THEME.controls.status_indicator.attention,
+ APP_UI_THEME.components.app_status_indicator.attention,
))
.child(
div()
@@ -6832,15 +6862,18 @@ fn home_low_stock_row(product: &ProductListRow) -> AnyElement {
.gap(px(4.0))
.child(
div()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_size(px(APP_UI_THEME
+ .foundation
+ .typography
+ .utility_title_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(app_shared_label_text(AppTextKey::HomeTodayStockCountLabel)),
)
.child(
div()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(product.stock_count.to_string()),
),
),
@@ -6855,17 +6888,17 @@ fn home_draft_row(product: &ProductListRow) -> AnyElement {
.flex()
.items_center()
.justify_between()
- .gap(px(APP_UI_THEME.layout.home_stack_gap_px))
+ .gap(px(APP_UI_THEME.shells.home_stack_gap_px))
.child(
div()
.min_w_0()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::SEMIBOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(product_display_title(product.title.as_str())),
)
.child(status_indicator(
- APP_UI_THEME.controls.status_indicator.offline,
+ APP_UI_THEME.components.app_status_indicator.offline,
))
.into_any_element()
}
@@ -6878,22 +6911,22 @@ fn home_setup_task_row(task: &radroots_app_models::TodaySetupTask) -> AnyElement
.min_w_0()
.flex()
.items_center()
- .gap(px(APP_UI_THEME.layout.settings_account_status_gap_px))
+ .gap(px(APP_UI_THEME.shells.settings_account_status_gap_px))
.child(status_indicator(if is_complete {
- APP_UI_THEME.controls.status_indicator.online
+ APP_UI_THEME.components.app_status_indicator.online
} else {
- APP_UI_THEME.controls.status_indicator.offline
+ APP_UI_THEME.components.app_status_indicator.offline
}))
.child(
div()
.min_w_0()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
.font_weight(gpui::FontWeight::MEDIUM)
.line_height(relative(1.2))
.text_color(rgb(if is_complete {
- APP_UI_THEME.text.secondary
+ APP_UI_THEME.foundation.text.secondary
} else {
- APP_UI_THEME.text.primary
+ APP_UI_THEME.foundation.text.primary
}))
.child(app_shared_text(home_setup_task_label_key(task.kind))),
)
@@ -6979,14 +7012,14 @@ fn home_farm_order_methods_summary(draft: &FarmSetupDraft) -> String {
fn home_status_presentation(runtime: &DesktopAppRuntimeSummary) -> HomeStatusPresentation {
if runtime.startup_issue.is_some() || runtime.startup_gate == AppStartupGate::Blocked {
return HomeStatusPresentation {
- indicator_color: APP_UI_THEME.controls.status_indicator.attention,
+ indicator_color: APP_UI_THEME.components.app_status_indicator.attention,
label_key: AppTextKey::HomeTodayStatusStartupIssue,
};
}
if runtime.startup_gate == AppStartupGate::SetupRequired {
return HomeStatusPresentation {
- indicator_color: APP_UI_THEME.controls.status_indicator.offline,
+ indicator_color: APP_UI_THEME.components.app_status_indicator.offline,
label_key: AppTextKey::HomeTodayStatusSetup,
};
}
@@ -6994,13 +7027,13 @@ fn home_status_presentation(runtime: &DesktopAppRuntimeSummary) -> HomeStatusPre
match farmer_home_farm_state(runtime) {
FarmerHomeFarmState::NoFarm => {
return HomeStatusPresentation {
- indicator_color: APP_UI_THEME.controls.status_indicator.offline,
+ indicator_color: APP_UI_THEME.components.app_status_indicator.offline,
label_key: AppTextKey::HomeTodayStatusNoFarm,
};
}
FarmerHomeFarmState::IncompleteFarm => {
return HomeStatusPresentation {
- indicator_color: APP_UI_THEME.controls.status_indicator.offline,
+ indicator_color: APP_UI_THEME.components.app_status_indicator.offline,
label_key: AppTextKey::HomeTodayStatusSetup,
};
}
@@ -7009,13 +7042,13 @@ fn home_status_presentation(runtime: &DesktopAppRuntimeSummary) -> HomeStatusPre
if runtime.today_projection.has_attention_items() {
return HomeStatusPresentation {
- indicator_color: APP_UI_THEME.controls.status_indicator.attention,
+ indicator_color: APP_UI_THEME.components.app_status_indicator.attention,
label_key: AppTextKey::HomeTodayStatusAttention,
};
}
HomeStatusPresentation {
- indicator_color: APP_UI_THEME.controls.status_indicator.online,
+ indicator_color: APP_UI_THEME.components.app_status_indicator.online,
label_key: AppTextKey::HomeTodayStatusReady,
}
}
diff --git a/crates/shared/ui/src/lib.rs b/crates/shared/ui/src/lib.rs
@@ -5,19 +5,19 @@ mod text;
mod theme;
pub use primitives::{
- AppCheckboxFieldSpec, IconSegmentButtonSpec, LabelValueRow, action_button,
- action_button_compact, action_button_primary, action_button_primary_disabled,
- action_icon_button, app_card, app_center_stage, app_checkbox, app_checkbox_field,
- app_text_input, app_window_shell, icon_segment_button, label_value_list, section_divider,
- status_indicator, utility_title_row,
+ AppCheckboxFieldSpec, AppSegmentButtonIconSpec, LabelValueRow, app_button_compact,
+ app_button_icon, app_button_primary, app_button_primary_disabled, app_button_secondary,
+ app_checkbox_field, app_divider, app_input_text, app_segment_button_icon, app_status_indicator,
+ app_surface_card, app_surface_window, label_value_list, utility_title_row,
};
pub use text::{
app_shared_label_text, app_shared_text, runtime_metadata_rows, settings_about_status_rows,
settings_preferences_general_rows,
};
pub use theme::{
- APP_UI_THEME, ActionButtonColors, ActionButtonSizing, ActionButtonTokens, AppControlTokens,
- AppLayoutTokens, AppSurfaceTokens, AppTextTokens, AppTypographyTokens, AppUiTheme,
- AppWindowTokens, CheckboxTokens, IconSegmentButtonColors, IconSegmentButtonSizing,
- IconSegmentButtonTokens, StatusIndicatorTokens, TextInputTokens,
+ APP_UI_THEME, AppBorderTokens, AppButtonColors, AppButtonSizing, AppButtonTokens,
+ AppCheckboxFieldTokens, AppComponentTokens, AppFoundationTokens, AppInputTextTokens,
+ AppRadiusTokens, AppSegmentButtonIconColors, AppSegmentButtonIconSizing,
+ AppSegmentButtonIconTokens, AppShellTokens, AppSpacingTokens, AppStatusIndicatorTokens,
+ AppSurfaceTokens, AppTextTokens, AppTypographyTokens, AppUiTheme,
};
diff --git a/crates/shared/ui/src/primitives.rs b/crates/shared/ui/src/primitives.rs
@@ -12,18 +12,18 @@ use std::rc::Rc;
use crate::APP_UI_THEME;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-enum ActionButtonVariant {
- Standard,
+enum AppButtonVariant {
+ Secondary,
Primary,
}
-pub struct IconSegmentButtonSpec {
+pub struct AppSegmentButtonIconSpec {
pub id: &'static str,
pub label: SharedString,
pub icon: IconName,
}
-impl IconSegmentButtonSpec {
+impl AppSegmentButtonIconSpec {
pub fn new(id: &'static str, label: impl Into<SharedString>, icon: IconName) -> Self {
Self {
id,
@@ -68,59 +68,49 @@ impl LabelValueRow {
}
}
-pub fn app_window_shell(background: u32, content: impl IntoElement) -> impl IntoElement {
+pub fn app_surface_window(background: u32, content: impl IntoElement) -> impl IntoElement {
div()
.size_full()
.overflow_hidden()
.bg(rgb(background))
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(content)
}
-pub fn app_center_stage(content: impl IntoElement) -> impl IntoElement {
- div()
- .size_full()
- .flex()
- .items_center()
- .justify_center()
- .p(px(APP_UI_THEME.layout.home_window_padding_px))
- .child(content)
-}
-
-pub fn app_card(content: impl IntoElement) -> impl IntoElement {
+pub fn app_surface_card(content: impl IntoElement) -> impl IntoElement {
div()
.w_full()
.h_full()
- .max_w(px(APP_UI_THEME.layout.home_card_max_width_px))
+ .max_w(px(APP_UI_THEME.shells.home_card_max_width_px))
.mx_auto()
- .bg(rgb(APP_UI_THEME.surfaces.card_background))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.card_background))
.overflow_hidden()
.child(
div()
.size_full()
.overflow_hidden()
- .p(px(APP_UI_THEME.layout.home_card_padding_px))
+ .p(px(APP_UI_THEME.shells.home_card_padding_px))
.child(content),
)
}
-pub fn section_divider() -> impl IntoElement {
+pub fn app_divider() -> impl IntoElement {
div()
.w_full()
- .h(px(APP_UI_THEME.layout.divider_thickness_px))
- .bg(rgb(APP_UI_THEME.surfaces.divider))
+ .h(px(APP_UI_THEME.foundation.borders.divider_thickness_px))
+ .bg(rgb(APP_UI_THEME.foundation.surfaces.divider))
}
pub fn utility_title_row(title: impl Into<SharedString>) -> impl IntoElement {
div()
.w_full()
- .h(px(APP_UI_THEME.layout.utility_title_row_height_px))
+ .h(px(APP_UI_THEME.shells.utility_title_row_height_px))
.flex()
.justify_center()
.items_center()
- .text_size(px(APP_UI_THEME.typography.utility_title_text_px))
+ .text_size(px(APP_UI_THEME.foundation.typography.utility_title_text_px))
.font_weight(gpui::FontWeight::BOLD)
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(title.into())
}
@@ -131,8 +121,8 @@ pub fn label_value_list(rows: impl IntoIterator<Item = LabelValueRow>) -> impl I
let line = format!("{}: {}", row.label, row.value);
div()
.w_full()
- .text_size(px(APP_UI_THEME.typography.body_text_px))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_size(px(APP_UI_THEME.foundation.typography.body_text_px))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(line)
})
.collect::<Vec<_>>();
@@ -141,17 +131,17 @@ pub fn label_value_list(rows: impl IntoIterator<Item = LabelValueRow>) -> impl I
.w_full()
.flex()
.flex_col()
- .gap(px(APP_UI_THEME.layout.metadata_row_gap_px))
+ .gap(px(APP_UI_THEME.shells.metadata_row_gap_px))
.children(rows)
}
-pub fn app_checkbox(
+fn app_checkbox(
id: &'static str,
checked: bool,
cx: &App,
on_change: impl Fn(bool, &mut Window, &mut App) + 'static,
) -> impl IntoElement {
- let colors = APP_UI_THEME.controls.checkbox;
+ let colors = APP_UI_THEME.components.app_checkbox_field;
let background = if checked {
colors.checked_background
} else {
@@ -195,10 +185,10 @@ pub fn app_checkbox_field(
let checkbox_id = spec.id;
let checkbox_label = spec.label;
let checkbox_note = spec.note;
- let row_text_px = APP_UI_THEME.typography.settings_row_text_px;
- let note_text_px = APP_UI_THEME.typography.utility_title_text_px;
- let note_indent_px =
- APP_UI_THEME.controls.checkbox.size_px + APP_UI_THEME.layout.settings_checkbox_label_gap_px;
+ let row_text_px = APP_UI_THEME.foundation.typography.settings_row_text_px;
+ let note_text_px = APP_UI_THEME.foundation.typography.utility_title_text_px;
+ let note_indent_px = APP_UI_THEME.components.app_checkbox_field.size_px
+ + APP_UI_THEME.shells.settings_checkbox_label_gap_px;
let on_change = Rc::new(on_change);
div()
@@ -211,7 +201,7 @@ pub fn app_checkbox_field(
.custom(
ButtonCustomVariant::new(cx)
.color(transparent_black().into())
- .foreground(rgb(APP_UI_THEME.text.primary).into())
+ .foreground(rgb(APP_UI_THEME.foundation.text.primary).into())
.border(transparent_black())
.hover(transparent_black().into())
.active(transparent_black().into()),
@@ -227,7 +217,7 @@ pub fn app_checkbox_field(
.w_full()
.flex()
.items_start()
- .gap(px(APP_UI_THEME.layout.settings_checkbox_label_gap_px))
+ .gap(px(APP_UI_THEME.shells.settings_checkbox_label_gap_px))
.child(app_checkbox(checkbox_id, checked, cx, {
let on_change = Rc::clone(&on_change);
move |checked, window, cx| on_change(checked, window, cx)
@@ -237,7 +227,7 @@ pub fn app_checkbox_field(
.min_w_0()
.text_size(px(row_text_px))
.line_height(relative(1.1))
- .text_color(rgb(APP_UI_THEME.text.primary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.primary))
.child(checkbox_label),
),
),
@@ -249,20 +239,20 @@ pub fn app_checkbox_field(
.pl(px(note_indent_px))
.min_w_0()
.text_size(px(note_text_px))
- .text_color(rgb(APP_UI_THEME.text.secondary))
+ .text_color(rgb(APP_UI_THEME.foundation.text.secondary))
.child(note),
)
})
}
-pub fn icon_segment_button(
- spec: IconSegmentButtonSpec,
+pub fn app_segment_button_icon(
+ spec: AppSegmentButtonIconSpec,
is_active: bool,
on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
cx: &App,
) -> impl IntoElement {
- let colors = APP_UI_THEME.controls.icon_segment_button.colors;
- let sizing = APP_UI_THEME.controls.icon_segment_button.sizing;
+ let colors = APP_UI_THEME.components.app_segment_button_icon.colors;
+ let sizing = APP_UI_THEME.components.app_segment_button_icon.sizing;
let background = if is_active {
colors.active_background
} else {
@@ -310,103 +300,109 @@ pub fn icon_segment_button(
)
}
-pub fn app_text_input(input: &Entity<InputState>, disabled: bool) -> Input {
- let tokens = APP_UI_THEME.controls.text_input;
+pub fn app_input_text(input: &Entity<InputState>, disabled: bool) -> Input {
+ let tokens = APP_UI_THEME.components.app_input_text;
let background = if disabled {
tokens.disabled_background
} else {
tokens.background
};
+ let foreground = if disabled {
+ APP_UI_THEME.foundation.text.secondary
+ } else {
+ APP_UI_THEME.foundation.text.primary
+ };
Input::new(input)
.with_size(Size::Medium)
.disabled(disabled)
.focus_bordered(false)
.bg(rgb(background))
+ .text_color(rgb(foreground))
.border_color(rgb(tokens.border))
.border_1()
.rounded(px(tokens.corner_radius_px))
}
-pub fn action_button(
+pub fn app_button_secondary(
id: &'static str,
label: impl Into<SharedString>,
on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
cx: &App,
) -> impl IntoElement {
- action_button_label(
- action_button_base(id, ActionButtonVariant::Standard, on_click, cx),
+ app_button_label(
+ app_button_base(id, AppButtonVariant::Secondary, on_click, cx),
label.into(),
APP_UI_THEME
- .controls
- .action_button
+ .components
+ .app_button
.sizing
.horizontal_padding_px,
- ActionButtonVariant::Standard,
+ AppButtonVariant::Secondary,
)
}
-pub fn action_button_primary(
+pub fn app_button_primary(
id: &'static str,
label: impl Into<SharedString>,
on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
cx: &App,
) -> impl IntoElement {
- action_button_label(
- action_button_base(id, ActionButtonVariant::Primary, on_click, cx),
+ app_button_label(
+ app_button_base(id, AppButtonVariant::Primary, on_click, cx),
label.into(),
APP_UI_THEME
- .controls
- .action_button
+ .components
+ .app_button
.sizing
.horizontal_padding_px,
- ActionButtonVariant::Primary,
+ AppButtonVariant::Primary,
)
}
-pub fn action_button_primary_disabled(
+pub fn app_button_primary_disabled(
id: &'static str,
label: impl Into<SharedString>,
cx: &App,
) -> impl IntoElement {
- action_button_label(
- action_button_base_disabled(id, ActionButtonVariant::Primary, cx),
+ app_button_label(
+ app_button_base_disabled(id, AppButtonVariant::Primary, cx),
label.into(),
APP_UI_THEME
- .controls
- .action_button
+ .components
+ .app_button
.sizing
.horizontal_padding_px,
- ActionButtonVariant::Primary,
+ AppButtonVariant::Primary,
)
}
-pub fn action_button_compact(
+pub fn app_button_compact(
id: &'static str,
label: impl Into<SharedString>,
on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
cx: &App,
) -> impl IntoElement {
- action_button_label(
- action_button_base(id, ActionButtonVariant::Standard, on_click, cx),
+ app_button_label(
+ app_button_base(id, AppButtonVariant::Secondary, on_click, cx),
label.into(),
APP_UI_THEME
- .controls
- .action_button
+ .components
+ .app_button
.sizing
.compact_horizontal_padding_px,
- ActionButtonVariant::Standard,
+ AppButtonVariant::Secondary,
)
}
-fn action_button_label(
+fn app_button_label(
button: Button,
label: SharedString,
horizontal_padding_px: f32,
- variant: ActionButtonVariant,
+ variant: AppButtonVariant,
) -> impl IntoElement {
- let sizing = APP_UI_THEME.controls.action_button.sizing;
- let colors = action_button_colors(variant);
+ let sizing = APP_UI_THEME.components.app_button.sizing;
+ let colors = app_button_colors(variant);
button.child(
div()
.h_full()
@@ -414,22 +410,23 @@ fn action_button_label(
.items_center()
.justify_center()
.px(px(horizontal_padding_px))
+ .whitespace_nowrap()
.text_size(px(sizing.label_size_px))
.text_color(rgb(colors.foreground))
.child(label),
)
}
-pub fn action_icon_button(
+pub fn app_button_icon(
id: &'static str,
icon: IconName,
on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
cx: &App,
) -> impl IntoElement {
- let sizing = APP_UI_THEME.controls.action_button.sizing;
- let colors = action_button_colors(ActionButtonVariant::Standard);
+ let sizing = APP_UI_THEME.components.app_button.sizing;
+ let colors = app_button_colors(AppButtonVariant::Secondary);
- action_button_base(id, ActionButtonVariant::Standard, on_click, cx)
+ app_button_base(id, AppButtonVariant::Secondary, on_click, cx)
.with_size(Size::Size(px(sizing.square_width_px)))
.icon(
Icon::new(icon)
@@ -438,8 +435,8 @@ pub fn action_icon_button(
)
}
-pub fn status_indicator(color: u32) -> impl IntoElement {
- let sizing = APP_UI_THEME.controls.status_indicator;
+pub fn app_status_indicator(color: u32) -> impl IntoElement {
+ let sizing = APP_UI_THEME.components.app_status_indicator;
div()
.size(px(sizing.size_px))
@@ -447,14 +444,14 @@ pub fn status_indicator(color: u32) -> impl IntoElement {
.rounded(px(sizing.size_px / 2.0))
}
-fn action_button_base(
+fn app_button_base(
id: &'static str,
- variant: ActionButtonVariant,
+ variant: AppButtonVariant,
on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
cx: &App,
) -> Button {
- let sizing = APP_UI_THEME.controls.action_button.sizing;
- let colors = action_button_colors(variant);
+ let sizing = APP_UI_THEME.components.app_button.sizing;
+ let colors = app_button_colors(variant);
let hover_background = if colors.hover_changes_background {
colors.hover_background
} else {
@@ -475,9 +472,9 @@ fn action_button_base(
.on_click(on_click)
}
-fn action_button_base_disabled(id: &'static str, variant: ActionButtonVariant, cx: &App) -> Button {
- let sizing = APP_UI_THEME.controls.action_button.sizing;
- let colors = action_button_disabled_colors(variant);
+fn app_button_base_disabled(id: &'static str, variant: AppButtonVariant, cx: &App) -> Button {
+ let sizing = APP_UI_THEME.components.app_button.sizing;
+ let colors = app_button_disabled_colors(variant);
Button::new(id)
.custom(
@@ -492,17 +489,17 @@ fn action_button_base_disabled(id: &'static str, variant: ActionButtonVariant, c
.h(px(sizing.height_px))
}
-fn action_button_colors(variant: ActionButtonVariant) -> crate::ActionButtonColors {
+fn app_button_colors(variant: AppButtonVariant) -> crate::AppButtonColors {
match variant {
- ActionButtonVariant::Standard => APP_UI_THEME.controls.action_button.colors,
- ActionButtonVariant::Primary => APP_UI_THEME.controls.action_button.primary_colors,
+ AppButtonVariant::Secondary => APP_UI_THEME.components.app_button.secondary_colors,
+ AppButtonVariant::Primary => APP_UI_THEME.components.app_button.primary_colors,
}
}
-fn action_button_disabled_colors(variant: ActionButtonVariant) -> crate::ActionButtonColors {
+fn app_button_disabled_colors(variant: AppButtonVariant) -> crate::AppButtonColors {
match variant {
- ActionButtonVariant::Standard | ActionButtonVariant::Primary => {
- APP_UI_THEME.controls.action_button.disabled_colors
+ AppButtonVariant::Secondary | AppButtonVariant::Primary => {
+ APP_UI_THEME.components.app_button.primary_disabled_colors
}
}
}
@@ -511,11 +508,11 @@ fn action_button_disabled_colors(variant: ActionButtonVariant) -> crate::ActionB
mod tests {
use gpui_component::IconName;
- use super::{AppCheckboxFieldSpec, IconSegmentButtonSpec};
+ use super::{AppCheckboxFieldSpec, AppSegmentButtonIconSpec};
#[test]
fn icon_segment_spec_preserves_id_and_label() {
- let spec = IconSegmentButtonSpec::new("settings", "Settings", IconName::Settings2);
+ let spec = AppSegmentButtonIconSpec::new("settings", "Settings", IconName::Settings2);
assert_eq!(spec.id, "settings");
assert_eq!(spec.label.as_ref(), "Settings");
diff --git a/crates/shared/ui/src/theme.rs b/crates/shared/ui/src/theme.rs
@@ -1,19 +1,18 @@
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct AppUiTheme {
- pub windows: AppWindowTokens,
- pub surfaces: AppSurfaceTokens,
- pub text: AppTextTokens,
- pub typography: AppTypographyTokens,
- pub layout: AppLayoutTokens,
- pub controls: AppControlTokens,
+ pub foundation: AppFoundationTokens,
+ pub components: AppComponentTokens,
+ pub shells: AppShellTokens,
}
#[derive(Clone, Copy, Debug, PartialEq)]
-pub struct AppWindowTokens {
- pub home_min_width_px: f32,
- pub home_min_height_px: f32,
- pub settings_width_px: f32,
- pub settings_height_px: f32,
+pub struct AppFoundationTokens {
+ pub surfaces: AppSurfaceTokens,
+ pub text: AppTextTokens,
+ pub typography: AppTypographyTokens,
+ pub spacing: AppSpacingTokens,
+ pub radii: AppRadiusTokens,
+ pub borders: AppBorderTokens,
}
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -45,61 +44,44 @@ pub struct AppTypographyTokens {
}
#[derive(Clone, Copy, Debug, PartialEq)]
-pub struct AppLayoutTokens {
+pub struct AppSpacingTokens {
+ pub micro_px: f32,
+ pub tight_px: f32,
+ pub small_px: f32,
+ pub medium_px: f32,
+ pub large_px: f32,
+ pub xlarge_px: f32,
+}
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub struct AppRadiusTokens {
+ pub small_px: f32,
+ pub medium_px: f32,
+ pub large_px: f32,
+}
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub struct AppBorderTokens {
pub divider_thickness_px: f32,
- pub home_window_padding_px: f32,
- pub home_sidebar_width_px: f32,
- pub home_card_max_width_px: f32,
- pub home_card_padding_px: f32,
- pub home_stack_gap_px: f32,
- pub startup_stack_gap_px: f32,
- pub metadata_row_gap_px: f32,
- pub utility_title_row_height_px: f32,
- pub settings_chrome_height_px: f32,
- pub settings_navigation_width_px: f32,
- pub settings_section_gap_px: f32,
- pub settings_navigation_row_padding_px: f32,
- pub settings_navigation_row_gap_px: f32,
- pub settings_content_padding_px: f32,
- pub settings_account_sidebar_width_px: f32,
- pub settings_account_sidebar_padding_px: f32,
- pub settings_account_sidebar_button_height_px: f32,
- pub settings_account_sidebar_button_padding_px: f32,
- pub settings_account_sidebar_button_corner_radius_px: f32,
- pub settings_account_sidebar_button_gap_px: f32,
- pub settings_account_sidebar_avatar_size_px: f32,
- pub settings_account_identity_text_gap_px: f32,
- pub settings_account_sidebar_footer_padding_top_px: f32,
- pub settings_account_sidebar_footer_row_gap_px: f32,
- pub settings_account_sidebar_footer_button_gap_px: f32,
- pub settings_account_main_padding_px: f32,
- pub settings_account_content_max_width_px: f32,
- pub settings_account_main_stack_gap_px: f32,
- pub settings_account_profile_avatar_size_px: f32,
- pub settings_account_detail_row_gap_px: f32,
- pub settings_account_detail_value_gap_px: f32,
- pub settings_checkbox_label_gap_px: f32,
- pub settings_account_status_gap_px: f32,
- pub settings_account_action_row_gap_px: f32,
}
#[derive(Clone, Copy, Debug, PartialEq)]
-pub struct AppControlTokens {
- pub icon_segment_button: IconSegmentButtonTokens,
- pub action_button: ActionButtonTokens,
- pub text_input: TextInputTokens,
- pub checkbox: CheckboxTokens,
- pub status_indicator: StatusIndicatorTokens,
+pub struct AppComponentTokens {
+ pub app_segment_button_icon: AppSegmentButtonIconTokens,
+ pub app_button: AppButtonTokens,
+ pub app_input_text: AppInputTextTokens,
+ pub app_checkbox_field: AppCheckboxFieldTokens,
+ pub app_status_indicator: AppStatusIndicatorTokens,
}
#[derive(Clone, Copy, Debug, PartialEq)]
-pub struct IconSegmentButtonTokens {
- pub sizing: IconSegmentButtonSizing,
- pub colors: IconSegmentButtonColors,
+pub struct AppSegmentButtonIconTokens {
+ pub sizing: AppSegmentButtonIconSizing,
+ pub colors: AppSegmentButtonIconColors,
}
#[derive(Clone, Copy, Debug, PartialEq)]
-pub struct IconSegmentButtonSizing {
+pub struct AppSegmentButtonIconSizing {
pub height_px: f32,
pub corner_radius_px: f32,
pub inner_padding_px: f32,
@@ -108,7 +90,7 @@ pub struct IconSegmentButtonSizing {
}
#[derive(Clone, Copy, Debug, PartialEq)]
-pub struct IconSegmentButtonColors {
+pub struct AppSegmentButtonIconColors {
pub active_background: u32,
pub inactive_background: u32,
pub active_foreground: u32,
@@ -116,15 +98,15 @@ pub struct IconSegmentButtonColors {
}
#[derive(Clone, Copy, Debug, PartialEq)]
-pub struct ActionButtonTokens {
- pub sizing: ActionButtonSizing,
- pub colors: ActionButtonColors,
- pub primary_colors: ActionButtonColors,
- pub disabled_colors: ActionButtonColors,
+pub struct AppButtonTokens {
+ pub sizing: AppButtonSizing,
+ pub secondary_colors: AppButtonColors,
+ pub primary_colors: AppButtonColors,
+ pub primary_disabled_colors: AppButtonColors,
}
#[derive(Clone, Copy, Debug, PartialEq)]
-pub struct ActionButtonSizing {
+pub struct AppButtonSizing {
pub height_px: f32,
pub corner_radius_px: f32,
pub horizontal_padding_px: f32,
@@ -135,7 +117,7 @@ pub struct ActionButtonSizing {
}
#[derive(Clone, Copy, Debug, PartialEq)]
-pub struct ActionButtonColors {
+pub struct AppButtonColors {
pub background: u32,
pub foreground: u32,
pub hover_changes_background: bool,
@@ -144,7 +126,15 @@ pub struct ActionButtonColors {
}
#[derive(Clone, Copy, Debug, PartialEq)]
-pub struct CheckboxTokens {
+pub struct AppInputTextTokens {
+ pub background: u32,
+ pub disabled_background: u32,
+ pub border: u32,
+ pub corner_radius_px: f32,
+}
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub struct AppCheckboxFieldTokens {
pub size_px: f32,
pub corner_radius_px: f32,
pub icon_size_px: f32,
@@ -155,157 +145,227 @@ pub struct CheckboxTokens {
}
#[derive(Clone, Copy, Debug, PartialEq)]
-pub struct TextInputTokens {
- pub background: u32,
- pub disabled_background: u32,
- pub border: u32,
- pub corner_radius_px: f32,
-}
-
-#[derive(Clone, Copy, Debug, PartialEq)]
-pub struct StatusIndicatorTokens {
+pub struct AppStatusIndicatorTokens {
pub size_px: f32,
pub online: u32,
pub offline: u32,
pub attention: u32,
}
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub struct AppShellTokens {
+ pub home_min_width_px: f32,
+ pub home_min_height_px: f32,
+ pub settings_width_px: f32,
+ pub settings_height_px: f32,
+ pub home_window_padding_px: f32,
+ pub home_sidebar_width_px: f32,
+ pub home_card_max_width_px: f32,
+ pub home_card_padding_px: f32,
+ pub home_stack_gap_px: f32,
+ pub startup_stack_gap_px: f32,
+ pub metadata_row_gap_px: f32,
+ pub utility_title_row_height_px: f32,
+ pub settings_chrome_height_px: f32,
+ pub settings_navigation_width_px: f32,
+ pub settings_section_gap_px: f32,
+ pub settings_navigation_row_padding_px: f32,
+ pub settings_navigation_row_gap_px: f32,
+ pub settings_content_padding_px: f32,
+ pub settings_account_sidebar_width_px: f32,
+ pub settings_account_sidebar_padding_px: f32,
+ pub settings_account_sidebar_button_height_px: f32,
+ pub settings_account_sidebar_button_padding_px: f32,
+ pub settings_account_sidebar_button_corner_radius_px: f32,
+ pub settings_account_sidebar_button_gap_px: f32,
+ pub settings_account_sidebar_avatar_size_px: f32,
+ pub settings_account_identity_text_gap_px: f32,
+ pub settings_account_sidebar_footer_padding_top_px: f32,
+ pub settings_account_sidebar_footer_row_gap_px: f32,
+ pub settings_account_sidebar_footer_button_gap_px: f32,
+ pub settings_account_main_padding_px: f32,
+ pub settings_account_content_max_width_px: f32,
+ pub settings_account_main_stack_gap_px: f32,
+ pub settings_account_profile_avatar_size_px: f32,
+ pub settings_account_detail_row_gap_px: f32,
+ pub settings_account_detail_value_gap_px: f32,
+ pub settings_checkbox_label_gap_px: f32,
+ pub settings_account_status_gap_px: f32,
+ pub settings_account_action_row_gap_px: f32,
+}
+
+const APP_SURFACE_WINDOW_BACKGROUND: u32 = 0xFFFFFF;
+const APP_SURFACE_CHROME_BACKGROUND: u32 = 0xF5F5F7;
+const APP_SURFACE_PANEL_BACKGROUND: u32 = 0xFFFFFF;
+const APP_SURFACE_CARD_BACKGROUND: u32 = 0xF2F2F7;
+const APP_SURFACE_DIVIDER: u32 = 0xD2D2D7;
+const APP_TEXT_PRIMARY: u32 = 0x1D1D1F;
+const APP_TEXT_SECONDARY: u32 = 0x6E6E73;
+const APP_TEXT_ACCENT: u32 = 0x0A84FF;
+const APP_STATUS_ONLINE: u32 = 0x34C759;
+const APP_STATUS_OFFLINE: u32 = 0xFFD60A;
+const APP_STATUS_ATTENTION: u32 = 0xFF3B30;
+const APP_SPACING_MICRO_PX: f32 = 4.0;
+const APP_SPACING_TIGHT_PX: f32 = 6.0;
+const APP_SPACING_SMALL_PX: f32 = 8.0;
+const APP_SPACING_MEDIUM_PX: f32 = 12.0;
+const APP_SPACING_LARGE_PX: f32 = 16.0;
+const APP_SPACING_XLARGE_PX: f32 = 24.0;
+const APP_RADIUS_SMALL_PX: f32 = 5.0;
+const APP_RADIUS_MEDIUM_PX: f32 = 8.0;
+const APP_RADIUS_LARGE_PX: f32 = 10.0;
+
pub const APP_UI_THEME: AppUiTheme = AppUiTheme {
- windows: AppWindowTokens {
- home_min_width_px: 1284.0,
- home_min_height_px: 795.0,
- settings_width_px: 600.0,
- settings_height_px: 540.0,
- },
- surfaces: AppSurfaceTokens {
- window_background: 0xFFFFFF,
- chrome_background: 0xF5F5F7,
- panel_background: 0xFFFFFF,
- card_background: 0xF2F2F7,
- divider: 0xD2D2D7,
- },
- text: AppTextTokens {
- primary: 0x1D1D1F,
- secondary: 0x6E6E73,
- accent: 0x0A84FF,
- },
- typography: AppTypographyTokens {
- utility_title_text_px: 12.0,
- body_text_px: 14.0,
- brand_text_px: 14.0,
- startup_title_text_px: 18.0,
- startup_tagline_text_px: 16.0,
- settings_row_text_px: 13.0,
- settings_account_identity_text_px: 14.0,
- settings_account_detail_text_px: 14.0,
- },
- layout: AppLayoutTokens {
- divider_thickness_px: 1.0,
- home_window_padding_px: 24.0,
- home_sidebar_width_px: 240.0,
- home_card_max_width_px: 1080.0,
- home_card_padding_px: 24.0,
- home_stack_gap_px: 12.0,
- startup_stack_gap_px: 6.0,
- metadata_row_gap_px: 12.0,
- utility_title_row_height_px: 24.0,
- settings_chrome_height_px: 88.0,
- settings_navigation_width_px: 216.0,
- settings_section_gap_px: 8.0,
- settings_navigation_row_padding_px: 8.0,
- settings_navigation_row_gap_px: 8.0,
- settings_content_padding_px: 24.0,
- settings_account_sidebar_width_px: 200.0,
- settings_account_sidebar_padding_px: 8.0,
- settings_account_sidebar_button_height_px: 42.0,
- settings_account_sidebar_button_padding_px: 4.0,
- settings_account_sidebar_button_corner_radius_px: 8.0,
- settings_account_sidebar_button_gap_px: 8.0,
- settings_account_sidebar_avatar_size_px: 32.0,
- settings_account_identity_text_gap_px: 0.0,
- settings_account_sidebar_footer_padding_top_px: 8.0,
- settings_account_sidebar_footer_row_gap_px: 8.0,
- settings_account_sidebar_footer_button_gap_px: 8.0,
- settings_account_main_padding_px: 24.0,
- settings_account_content_max_width_px: 260.0,
- settings_account_main_stack_gap_px: 16.0,
- settings_account_profile_avatar_size_px: 64.0,
- settings_account_detail_row_gap_px: 16.0,
- settings_account_detail_value_gap_px: 12.0,
- settings_checkbox_label_gap_px: 8.0,
- settings_account_status_gap_px: 4.0,
- settings_account_action_row_gap_px: 8.0,
+ foundation: AppFoundationTokens {
+ surfaces: AppSurfaceTokens {
+ window_background: APP_SURFACE_WINDOW_BACKGROUND,
+ chrome_background: APP_SURFACE_CHROME_BACKGROUND,
+ panel_background: APP_SURFACE_PANEL_BACKGROUND,
+ card_background: APP_SURFACE_CARD_BACKGROUND,
+ divider: APP_SURFACE_DIVIDER,
+ },
+ text: AppTextTokens {
+ primary: APP_TEXT_PRIMARY,
+ secondary: APP_TEXT_SECONDARY,
+ accent: APP_TEXT_ACCENT,
+ },
+ typography: AppTypographyTokens {
+ utility_title_text_px: 12.0,
+ body_text_px: 14.0,
+ brand_text_px: 14.0,
+ startup_title_text_px: 18.0,
+ startup_tagline_text_px: 16.0,
+ settings_row_text_px: 13.0,
+ settings_account_identity_text_px: 14.0,
+ settings_account_detail_text_px: 14.0,
+ },
+ spacing: AppSpacingTokens {
+ micro_px: APP_SPACING_MICRO_PX,
+ tight_px: APP_SPACING_TIGHT_PX,
+ small_px: APP_SPACING_SMALL_PX,
+ medium_px: APP_SPACING_MEDIUM_PX,
+ large_px: APP_SPACING_LARGE_PX,
+ xlarge_px: APP_SPACING_XLARGE_PX,
+ },
+ radii: AppRadiusTokens {
+ small_px: APP_RADIUS_SMALL_PX,
+ medium_px: APP_RADIUS_MEDIUM_PX,
+ large_px: APP_RADIUS_LARGE_PX,
+ },
+ borders: AppBorderTokens {
+ divider_thickness_px: 1.0,
+ },
},
- controls: AppControlTokens {
- icon_segment_button: IconSegmentButtonTokens {
- sizing: IconSegmentButtonSizing {
+ components: AppComponentTokens {
+ app_segment_button_icon: AppSegmentButtonIconTokens {
+ sizing: AppSegmentButtonIconSizing {
height_px: 44.0,
- corner_radius_px: 8.0,
+ corner_radius_px: APP_RADIUS_MEDIUM_PX,
inner_padding_px: 2.0,
icon_size_px: 16.0,
label_size_px: 12.0,
},
- colors: IconSegmentButtonColors {
- active_background: 0xFFFFFF,
- inactive_background: 0xF5F5F7,
- active_foreground: 0x0A84FF,
- inactive_foreground: 0x1D1D1F,
+ colors: AppSegmentButtonIconColors {
+ active_background: APP_SURFACE_WINDOW_BACKGROUND,
+ inactive_background: APP_SURFACE_CHROME_BACKGROUND,
+ active_foreground: APP_TEXT_ACCENT,
+ inactive_foreground: APP_TEXT_PRIMARY,
},
},
- action_button: ActionButtonTokens {
- sizing: ActionButtonSizing {
+ app_button: AppButtonTokens {
+ sizing: AppButtonSizing {
height_px: 24.0,
- corner_radius_px: 8.0,
- horizontal_padding_px: 12.0,
- compact_horizontal_padding_px: 4.0,
+ corner_radius_px: APP_RADIUS_MEDIUM_PX,
+ horizontal_padding_px: APP_SPACING_MEDIUM_PX,
+ compact_horizontal_padding_px: APP_SPACING_MICRO_PX,
label_size_px: 13.0,
icon_size_px: 14.0,
square_width_px: 24.0,
},
- colors: ActionButtonColors {
+ secondary_colors: AppButtonColors {
background: 0xE5E5EA,
- foreground: 0x1D1D1F,
+ foreground: APP_TEXT_PRIMARY,
hover_changes_background: false,
hover_background: 0xDCDCE1,
active_background: 0xD1D1D6,
},
- primary_colors: ActionButtonColors {
- background: 0x0A84FF,
- foreground: 0xFFFFFF,
+ primary_colors: AppButtonColors {
+ background: APP_TEXT_ACCENT,
+ foreground: APP_SURFACE_WINDOW_BACKGROUND,
hover_changes_background: true,
hover_background: 0x007AFF,
active_background: 0x0062CC,
},
- disabled_colors: ActionButtonColors {
+ primary_disabled_colors: AppButtonColors {
background: 0xA7C8F8,
- foreground: 0xFFFFFF,
+ foreground: APP_SURFACE_WINDOW_BACKGROUND,
hover_changes_background: false,
hover_background: 0xA7C8F8,
active_background: 0xA7C8F8,
},
},
- text_input: TextInputTokens {
- background: 0xFFFFFF,
- disabled_background: 0xF2F2F7,
+ app_input_text: AppInputTextTokens {
+ background: APP_SURFACE_WINDOW_BACKGROUND,
+ disabled_background: APP_SURFACE_CARD_BACKGROUND,
border: 0xD1D1D6,
- corner_radius_px: 10.0,
+ corner_radius_px: APP_RADIUS_LARGE_PX,
},
- checkbox: CheckboxTokens {
+ app_checkbox_field: AppCheckboxFieldTokens {
size_px: 16.0,
- corner_radius_px: 5.0,
+ corner_radius_px: APP_RADIUS_SMALL_PX,
icon_size_px: 13.0,
- checked_background: 0x0A84FF,
- unchecked_background: 0xF2F2F7,
+ checked_background: APP_TEXT_ACCENT,
+ unchecked_background: APP_SURFACE_CARD_BACKGROUND,
unchecked_border: 0xD1D1D6,
- check_foreground: 0xFFFFFF,
+ check_foreground: APP_SURFACE_WINDOW_BACKGROUND,
},
- status_indicator: StatusIndicatorTokens {
+ app_status_indicator: AppStatusIndicatorTokens {
size_px: 12.0,
- online: 0x34C759,
- offline: 0xFFD60A,
- attention: 0xFF3B30,
+ online: APP_STATUS_ONLINE,
+ offline: APP_STATUS_OFFLINE,
+ attention: APP_STATUS_ATTENTION,
},
},
+ shells: AppShellTokens {
+ home_min_width_px: 1284.0,
+ home_min_height_px: 795.0,
+ settings_width_px: 600.0,
+ settings_height_px: 540.0,
+ home_window_padding_px: APP_SPACING_XLARGE_PX,
+ home_sidebar_width_px: 240.0,
+ home_card_max_width_px: 1080.0,
+ home_card_padding_px: APP_SPACING_XLARGE_PX,
+ home_stack_gap_px: APP_SPACING_MEDIUM_PX,
+ startup_stack_gap_px: APP_SPACING_TIGHT_PX,
+ metadata_row_gap_px: APP_SPACING_MEDIUM_PX,
+ utility_title_row_height_px: 24.0,
+ settings_chrome_height_px: 88.0,
+ settings_navigation_width_px: 216.0,
+ settings_section_gap_px: APP_SPACING_SMALL_PX,
+ settings_navigation_row_padding_px: APP_SPACING_SMALL_PX,
+ settings_navigation_row_gap_px: APP_SPACING_SMALL_PX,
+ settings_content_padding_px: APP_SPACING_XLARGE_PX,
+ settings_account_sidebar_width_px: 200.0,
+ settings_account_sidebar_padding_px: APP_SPACING_SMALL_PX,
+ settings_account_sidebar_button_height_px: 42.0,
+ settings_account_sidebar_button_padding_px: APP_SPACING_MICRO_PX,
+ settings_account_sidebar_button_corner_radius_px: APP_RADIUS_MEDIUM_PX,
+ settings_account_sidebar_button_gap_px: APP_SPACING_SMALL_PX,
+ settings_account_sidebar_avatar_size_px: 32.0,
+ settings_account_identity_text_gap_px: 0.0,
+ settings_account_sidebar_footer_padding_top_px: APP_SPACING_SMALL_PX,
+ settings_account_sidebar_footer_row_gap_px: APP_SPACING_SMALL_PX,
+ settings_account_sidebar_footer_button_gap_px: APP_SPACING_SMALL_PX,
+ settings_account_main_padding_px: APP_SPACING_XLARGE_PX,
+ settings_account_content_max_width_px: 260.0,
+ settings_account_main_stack_gap_px: APP_SPACING_LARGE_PX,
+ settings_account_profile_avatar_size_px: 64.0,
+ settings_account_detail_row_gap_px: APP_SPACING_LARGE_PX,
+ settings_account_detail_value_gap_px: APP_SPACING_MEDIUM_PX,
+ settings_checkbox_label_gap_px: APP_SPACING_SMALL_PX,
+ settings_account_status_gap_px: APP_SPACING_MICRO_PX,
+ settings_account_action_row_gap_px: APP_SPACING_SMALL_PX,
+ },
};
#[cfg(test)]
@@ -314,34 +374,45 @@ mod tests {
#[test]
fn paperwhite_shell_layers_are_distinct() {
- assert_eq!(APP_UI_THEME.surfaces.window_background, 0xFFFFFF);
- assert_eq!(APP_UI_THEME.surfaces.chrome_background, 0xF5F5F7);
- assert_eq!(APP_UI_THEME.surfaces.card_background, 0xF2F2F7);
- assert_eq!(APP_UI_THEME.surfaces.divider, 0xD2D2D7);
+ assert_eq!(APP_UI_THEME.foundation.surfaces.window_background, 0xFFFFFF);
+ assert_eq!(APP_UI_THEME.foundation.surfaces.chrome_background, 0xF5F5F7);
+ assert_eq!(APP_UI_THEME.foundation.surfaces.card_background, 0xF2F2F7);
+ assert_eq!(APP_UI_THEME.foundation.surfaces.divider, 0xD2D2D7);
assert_ne!(
- APP_UI_THEME.surfaces.window_background,
- APP_UI_THEME.surfaces.card_background
+ APP_UI_THEME.foundation.surfaces.window_background,
+ APP_UI_THEME.foundation.surfaces.card_background
);
}
#[test]
+ fn foundation_scales_are_explicit() {
+ assert_eq!(APP_UI_THEME.foundation.spacing.micro_px, 4.0);
+ assert_eq!(APP_UI_THEME.foundation.spacing.tight_px, 6.0);
+ assert_eq!(APP_UI_THEME.foundation.spacing.xlarge_px, 24.0);
+ assert_eq!(APP_UI_THEME.foundation.radii.small_px, 5.0);
+ assert_eq!(APP_UI_THEME.foundation.radii.medium_px, 8.0);
+ assert_eq!(APP_UI_THEME.foundation.radii.large_px, 10.0);
+ assert_eq!(APP_UI_THEME.foundation.borders.divider_thickness_px, 1.0);
+ }
+
+ #[test]
fn home_window_minimums_match_the_upgraded_shell_budget() {
- assert_eq!(APP_UI_THEME.windows.home_min_width_px, 1284.0);
- assert_eq!(APP_UI_THEME.windows.home_min_height_px, 795.0);
- assert_eq!(APP_UI_THEME.layout.home_sidebar_width_px, 240.0);
- assert_eq!(APP_UI_THEME.layout.home_window_padding_px, 24.0);
+ assert_eq!(APP_UI_THEME.shells.home_min_width_px, 1284.0);
+ assert_eq!(APP_UI_THEME.shells.home_min_height_px, 795.0);
+ assert_eq!(APP_UI_THEME.shells.home_sidebar_width_px, 240.0);
+ assert_eq!(APP_UI_THEME.shells.home_window_padding_px, 24.0);
}
#[test]
fn settings_shell_layout_contract_is_explicit() {
- assert_eq!(APP_UI_THEME.windows.settings_width_px, 600.0);
- assert_eq!(APP_UI_THEME.windows.settings_height_px, 540.0);
- assert_eq!(APP_UI_THEME.layout.settings_chrome_height_px, 88.0);
- assert_eq!(APP_UI_THEME.layout.settings_content_padding_px, 24.0);
- assert_eq!(APP_UI_THEME.layout.settings_account_sidebar_width_px, 200.0);
+ assert_eq!(APP_UI_THEME.shells.settings_width_px, 600.0);
+ assert_eq!(APP_UI_THEME.shells.settings_height_px, 540.0);
+ assert_eq!(APP_UI_THEME.shells.settings_chrome_height_px, 88.0);
+ assert_eq!(APP_UI_THEME.shells.settings_content_padding_px, 24.0);
+ assert_eq!(APP_UI_THEME.shells.settings_account_sidebar_width_px, 200.0);
assert_eq!(
APP_UI_THEME
- .layout
+ .shells
.settings_account_sidebar_button_height_px,
42.0
);
@@ -349,11 +420,11 @@ mod tests {
#[test]
fn control_tokens_match_the_frozen_budget() {
- let segmented = APP_UI_THEME.controls.icon_segment_button.sizing;
- let action = APP_UI_THEME.controls.action_button.sizing;
- let text_input = APP_UI_THEME.controls.text_input;
- let checkbox = APP_UI_THEME.controls.checkbox;
- let status = APP_UI_THEME.controls.status_indicator;
+ let segmented = APP_UI_THEME.components.app_segment_button_icon.sizing;
+ let action = APP_UI_THEME.components.app_button.sizing;
+ let text_input = APP_UI_THEME.components.app_input_text;
+ let checkbox = APP_UI_THEME.components.app_checkbox_field;
+ let status = APP_UI_THEME.components.app_status_indicator;
assert_eq!(segmented.height_px, 44.0);
assert_eq!(segmented.corner_radius_px, 8.0);
@@ -371,26 +442,33 @@ mod tests {
#[test]
fn accent_and_status_colors_match_the_current_shell_contract() {
- assert_eq!(APP_UI_THEME.text.accent, 0x0A84FF);
+ assert_eq!(APP_UI_THEME.foundation.text.accent, 0x0A84FF);
assert_eq!(
- APP_UI_THEME
- .controls
- .action_button
- .primary_colors
- .background,
+ APP_UI_THEME.components.app_button.primary_colors.background,
0x0A84FF
);
assert_eq!(
- APP_UI_THEME
- .controls
- .action_button
- .primary_colors
- .foreground,
+ APP_UI_THEME.components.app_button.primary_colors.foreground,
0xFFFFFF
);
- assert_eq!(APP_UI_THEME.controls.checkbox.checked_background, 0x0A84FF);
- assert_eq!(APP_UI_THEME.controls.status_indicator.online, 0x34C759);
- assert_eq!(APP_UI_THEME.controls.status_indicator.offline, 0xFFD60A);
- assert_eq!(APP_UI_THEME.controls.status_indicator.attention, 0xFF3B30);
+ assert_eq!(
+ APP_UI_THEME
+ .components
+ .app_checkbox_field
+ .checked_background,
+ 0x0A84FF
+ );
+ assert_eq!(
+ APP_UI_THEME.components.app_status_indicator.online,
+ 0x34C759
+ );
+ assert_eq!(
+ APP_UI_THEME.components.app_status_indicator.offline,
+ 0xFFD60A
+ );
+ assert_eq!(
+ APP_UI_THEME.components.app_status_indicator.attention,
+ 0xFF3B30
+ );
}
}