use super::semantic::SemanticTokens;
use crate::tokens::DESIGN_TOKENS;
use egui::{Color32, CornerRadius, Stroke, Vec2};
#[derive(Clone, Copy, Debug)]
pub struct BtnStyle {
pub bg: Color32,
pub bg_hover: Color32,
pub bg_active: Color32,
pub bg_disabled: Color32,
pub fg: Color32,
pub fg_hover: Color32,
pub fg_disabled: Color32,
pub border: Stroke,
pub border_hover: Stroke,
pub border_focus: Stroke,
pub rounding: CornerRadius,
pub padding: Vec2,
pub min_size: Vec2,
}
impl BtnStyle {
pub fn primary(semantic: &SemanticTokens) -> Self {
Self {
bg: semantic.ui.accent,
bg_hover: semantic.ui.accent_hover,
bg_active: semantic.ui.accent_active,
bg_disabled: semantic.ui.btn_bg_disabled,
fg: semantic.ui.accent_text,
fg_hover: semantic.ui.accent_text,
fg_disabled: semantic.ui.text_disabled,
border: Stroke::NONE,
border_hover: Stroke::NONE,
border_focus: Stroke::new(DESIGN_TOKENS.stroke.thick, semantic.ui.border_focus),
rounding: CornerRadius::same(DESIGN_TOKENS.rounding.md as u8),
padding: Vec2::new(DESIGN_TOKENS.spacing.lg, DESIGN_TOKENS.spacing.md),
min_size: Vec2::new(
DESIGN_TOKENS.sizing.dialog.button_min_width_xs,
DESIGN_TOKENS.sizing.button_md,
),
}
}
pub fn secondary(semantic: &SemanticTokens) -> Self {
Self {
bg: semantic.ui.btn_bg,
bg_hover: semantic.ui.btn_bg_hover,
bg_active: semantic.ui.btn_bg_active,
bg_disabled: semantic.ui.btn_bg_disabled,
fg: semantic.ui.text,
fg_hover: semantic.ui.text,
fg_disabled: semantic.ui.text_disabled,
border: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.ui.border),
border_hover: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.ui.border),
border_focus: Stroke::new(DESIGN_TOKENS.stroke.thick, semantic.ui.border_focus),
rounding: CornerRadius::same(DESIGN_TOKENS.rounding.md as u8),
padding: Vec2::new(DESIGN_TOKENS.spacing.lg, DESIGN_TOKENS.spacing.md),
min_size: Vec2::new(
DESIGN_TOKENS.sizing.dialog.button_min_width_xs,
DESIGN_TOKENS.sizing.button_md,
),
}
}
pub fn ghost(semantic: &SemanticTokens) -> Self {
Self {
bg: Color32::TRANSPARENT,
bg_hover: semantic.ui.btn_bg_hover,
bg_active: semantic.ui.btn_bg_active,
bg_disabled: Color32::TRANSPARENT,
fg: semantic.ui.text_secondary,
fg_hover: semantic.ui.text,
fg_disabled: semantic.ui.text_disabled,
border: Stroke::NONE,
border_hover: Stroke::NONE,
border_focus: Stroke::new(DESIGN_TOKENS.stroke.thick, semantic.ui.border_focus),
rounding: CornerRadius::same(DESIGN_TOKENS.rounding.md as u8),
padding: Vec2::new(DESIGN_TOKENS.spacing.md, DESIGN_TOKENS.spacing.sm),
min_size: Vec2::splat(DESIGN_TOKENS.sizing.button_sm),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct ToolbarStyle {
pub bg: Color32,
pub border: Color32,
pub separator: Color32,
pub icon_color: Color32,
pub icon_color_hover: Color32,
pub icon_color_active: Color32,
pub item_bg_hover: Color32,
pub item_bg_active: Color32,
pub item_rounding: CornerRadius,
pub item_padding: Vec2,
pub gap: f32,
pub height: f32,
}
impl ToolbarStyle {
pub fn from_semantic(semantic: &SemanticTokens) -> Self {
Self {
bg: semantic.ui.toolbar_bg,
border: semantic.ui.border,
separator: semantic.ui.toolbar_separator,
icon_color: semantic.ui.icon,
icon_color_hover: semantic.ui.icon_hover,
icon_color_active: semantic.ui.icon_active,
item_bg_hover: semantic.ui.btn_bg_hover,
item_bg_active: semantic.ui.btn_bg_active,
item_rounding: CornerRadius::same(DESIGN_TOKENS.rounding.sm as u8),
item_padding: Vec2::new(DESIGN_TOKENS.spacing.md, DESIGN_TOKENS.spacing.md),
gap: DESIGN_TOKENS.spacing.xs,
height: DESIGN_TOKENS.sizing.toolbar.top_height,
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct PanelStyle {
pub bg: Color32,
pub border: Stroke,
pub rounding: CornerRadius,
pub padding: Vec2,
pub shadow_color: Color32,
pub shadow_offset: Vec2,
pub shadow_blur: f32,
}
impl PanelStyle {
pub fn from_semantic(semantic: &SemanticTokens) -> Self {
Self {
bg: semantic.ui.panel_bg,
border: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.ui.border),
rounding: CornerRadius::same(DESIGN_TOKENS.rounding.lg as u8),
padding: Vec2::new(DESIGN_TOKENS.spacing.lg, DESIGN_TOKENS.spacing.lg),
shadow_color: Color32::from_black_alpha(40),
shadow_offset: Vec2::new(
DESIGN_TOKENS.layout.menu_shadow_offset_x,
DESIGN_TOKENS.shadow.offset_sm,
),
shadow_blur: 8.0,
}
}
pub fn floating(semantic: &SemanticTokens) -> Self {
Self {
bg: semantic.ui.panel_bg_floating,
border: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.ui.border),
rounding: CornerRadius::same(DESIGN_TOKENS.rounding.lg as u8),
padding: Vec2::new(DESIGN_TOKENS.spacing.lg, DESIGN_TOKENS.spacing.lg),
shadow_color: Color32::from_black_alpha(80),
shadow_offset: Vec2::new(
DESIGN_TOKENS.layout.menu_shadow_offset_x,
DESIGN_TOKENS.shadow.offset_md,
),
shadow_blur: 16.0,
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct MenuStyle {
pub bg: Color32,
pub border: Stroke,
pub rounding: CornerRadius,
pub item_height: f32,
pub item_padding: Vec2,
pub item_bg_hover: Color32,
pub item_bg_active: Color32,
pub text_color: Color32,
pub text_color_hover: Color32,
pub text_color_disabled: Color32,
pub shortcut_color: Color32,
pub separator_color: Color32,
pub icon_color: Color32,
pub check_color: Color32,
}
impl MenuStyle {
pub fn from_semantic(semantic: &SemanticTokens) -> Self {
Self {
bg: semantic.ui.panel_bg_floating,
border: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.ui.border),
rounding: CornerRadius::same(DESIGN_TOKENS.rounding.md as u8),
item_height: DESIGN_TOKENS.sizing.menu.item_height,
item_padding: Vec2::new(DESIGN_TOKENS.spacing.lg, DESIGN_TOKENS.spacing.sm),
item_bg_hover: semantic.ui.btn_bg_hover,
item_bg_active: semantic.ui.btn_bg_active,
text_color: semantic.ui.text,
text_color_hover: semantic.ui.text,
text_color_disabled: semantic.ui.text_disabled,
shortcut_color: semantic.ui.text_muted,
separator_color: semantic.ui.border_subtle,
icon_color: semantic.ui.icon,
check_color: semantic.ui.accent,
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct InputStyle {
pub bg: Color32,
pub bg_hover: Color32,
pub bg_focus: Color32,
pub bg_disabled: Color32,
pub text_color: Color32,
pub text_color_placeholder: Color32,
pub text_color_disabled: Color32,
pub border: Stroke,
pub border_hover: Stroke,
pub border_focus: Stroke,
pub border_error: Stroke,
pub rounding: CornerRadius,
pub padding: Vec2,
pub selection_bg: Color32,
pub cursor_color: Color32,
}
impl InputStyle {
pub fn from_semantic(semantic: &SemanticTokens) -> Self {
Self {
bg: semantic.ui.panel_bg,
bg_hover: semantic.ui.panel_bg,
bg_focus: semantic.ui.panel_bg,
bg_disabled: semantic.ui.btn_bg_disabled,
text_color: semantic.ui.text,
text_color_placeholder: semantic.ui.text_muted,
text_color_disabled: semantic.ui.text_disabled,
border: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.ui.border),
border_hover: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.ui.border),
border_focus: Stroke::new(DESIGN_TOKENS.stroke.thick, semantic.ui.border_focus),
border_error: Stroke::new(DESIGN_TOKENS.stroke.thick, semantic.ui.error),
rounding: CornerRadius::same(DESIGN_TOKENS.rounding.md as u8),
padding: Vec2::new(DESIGN_TOKENS.spacing.md, DESIGN_TOKENS.spacing.sm),
selection_bg: semantic.ui.selection_bg,
cursor_color: semantic.ui.accent,
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct ChartStyle {
pub bg: Color32,
pub axis_bg: Color32,
pub grid_line: Stroke,
pub grid_line_major: Stroke,
pub axis_text_color: Color32,
pub axis_text_size: f32,
pub crosshair_line: Stroke,
pub crosshair_label_bg: Color32,
pub crosshair_label_text: Color32,
pub crosshair_label_rounding: CornerRadius,
}
impl ChartStyle {
pub fn from_semantic(semantic: &SemanticTokens) -> Self {
Self {
bg: semantic.chart.bg,
axis_bg: semantic.chart.bg_axis,
grid_line: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.chart.grid_line),
grid_line_major: Stroke::new(
DESIGN_TOKENS.stroke.hairline,
semantic.chart.grid_line_major,
),
axis_text_color: semantic.chart.axis_text,
axis_text_size: DESIGN_TOKENS.typography.sm,
crosshair_line: Stroke::new(
DESIGN_TOKENS.stroke.hairline,
semantic.chart.crosshair_line,
),
crosshair_label_bg: semantic.chart.crosshair_label_bg,
crosshair_label_text: semantic.chart.crosshair_label_text,
crosshair_label_rounding: CornerRadius::same(DESIGN_TOKENS.rounding.sm as u8),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct CandleStyle {
pub bullish_fill: Color32,
pub bullish_border: Stroke,
pub bullish_wick: Stroke,
pub bearish_fill: Color32,
pub bearish_border: Stroke,
pub bearish_wick: Stroke,
pub min_body_height: f32,
}
impl CandleStyle {
pub fn from_semantic(semantic: &SemanticTokens) -> Self {
Self {
bullish_fill: semantic.chart.candle_up,
bullish_border: Stroke::new(
DESIGN_TOKENS.stroke.hairline,
semantic.chart.candle_up_border,
),
bullish_wick: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.chart.candle_up_wick),
bearish_fill: semantic.chart.candle_down,
bearish_border: Stroke::new(
DESIGN_TOKENS.stroke.hairline,
semantic.chart.candle_down_border,
),
bearish_wick: Stroke::new(
DESIGN_TOKENS.stroke.hairline,
semantic.chart.candle_down_wick,
),
min_body_height: 1.0,
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct VolumeStyle {
pub bullish: Color32,
pub bearish: Color32,
pub rounding: CornerRadius,
}
impl VolumeStyle {
pub fn from_semantic(semantic: &SemanticTokens) -> Self {
Self {
bullish: semantic.chart.volume_up,
bearish: semantic.chart.volume_down,
rounding: CornerRadius::same(DESIGN_TOKENS.rounding.none as u8),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct DialogStyle {
pub bg: Color32,
pub border: Stroke,
pub rounding: CornerRadius,
pub shadow_color: Color32,
pub title_bg: Color32,
pub title_text: Color32,
pub title_border: Color32,
pub close_button_bg: Color32,
pub close_button_bg_hover: Color32,
pub close_button_icon: Color32,
pub close_button_icon_hover: Color32,
}
impl DialogStyle {
pub fn from_semantic(semantic: &SemanticTokens) -> Self {
Self {
bg: semantic.ui.panel_bg_floating,
border: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.ui.border),
rounding: CornerRadius::same(DESIGN_TOKENS.rounding.lg as u8),
shadow_color: Color32::from_black_alpha(100),
title_bg: semantic.ui.panel_bg_floating,
title_text: semantic.ui.text,
title_border: semantic.ui.border_subtle,
close_button_bg: Color32::TRANSPARENT,
close_button_bg_hover: semantic.ui.btn_bg_hover,
close_button_icon: semantic.ui.text_muted,
close_button_icon_hover: semantic.ui.text,
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct SettingsDialogStyle {
pub dialog: DialogStyle,
pub sidebar_bg: Color32,
pub sidebar_border: Color32,
pub tab_bg: Color32,
pub tab_bg_hover: Color32,
pub tab_bg_active: Color32,
pub tab_text: Color32,
pub tab_text_hover: Color32,
pub tab_text_active: Color32,
pub tab_icon: Color32,
pub tab_icon_hover: Color32,
pub tab_icon_active: Color32,
pub content_bg: Color32,
pub section_header_text: Color32,
pub label_text: Color32,
pub val_text: Color32,
pub input_bg: Color32,
pub input_bg_hover: Color32,
pub input_bg_focus: Color32,
pub input_border: Stroke,
pub input_border_hover: Stroke,
pub input_border_focus: Stroke,
pub dropdown_bg: Color32,
pub dropdown_bg_hover: Color32,
pub dropdown_border: Stroke,
pub dropdown_arrow: Color32,
pub checkbox_bg: Color32,
pub checkbox_bg_checked: Color32,
pub checkbox_border: Stroke,
pub checkbox_check: Color32,
pub swatch_border: Color32,
pub swatch_border_hover: Color32,
pub footer_bg: Color32,
pub footer_border: Color32,
pub btn_primary_bg: Color32,
pub btn_primary_bg_hover: Color32,
pub btn_primary_text: Color32,
pub btn_secondary_bg: Color32,
pub btn_secondary_bg_hover: Color32,
pub btn_secondary_text: Color32,
pub btn_secondary_border: Stroke,
}
impl SettingsDialogStyle {
pub fn from_semantic(semantic: &SemanticTokens) -> Self {
Self {
dialog: DialogStyle::from_semantic(semantic),
sidebar_bg: semantic.ui.panel_bg_secondary,
sidebar_border: semantic.ui.border,
tab_bg: Color32::TRANSPARENT,
tab_bg_hover: semantic.ui.btn_bg_hover,
tab_bg_active: semantic.ui.btn_bg_active,
tab_text: semantic.ui.text_secondary,
tab_text_hover: semantic.ui.text,
tab_text_active: semantic.ui.text,
tab_icon: semantic.ui.icon,
tab_icon_hover: semantic.ui.icon_hover,
tab_icon_active: semantic.ui.icon_active,
content_bg: semantic.ui.panel_bg,
section_header_text: semantic.ui.text_muted,
label_text: semantic.ui.text_secondary,
val_text: semantic.ui.text,
input_bg: semantic.ui.btn_bg,
input_bg_hover: semantic.ui.btn_bg_hover,
input_bg_focus: semantic.ui.btn_bg_active,
input_border: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.ui.border),
input_border_hover: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.ui.border),
input_border_focus: Stroke::new(DESIGN_TOKENS.stroke.thick, semantic.ui.border_focus),
dropdown_bg: semantic.ui.btn_bg,
dropdown_bg_hover: semantic.ui.btn_bg_hover,
dropdown_border: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.ui.border),
dropdown_arrow: semantic.ui.icon,
checkbox_bg: Color32::TRANSPARENT,
checkbox_bg_checked: semantic.ui.accent,
checkbox_border: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.ui.border),
checkbox_check: semantic.ui.accent_text,
swatch_border: semantic.ui.border,
swatch_border_hover: semantic.ui.text_muted,
footer_bg: semantic.ui.panel_bg,
footer_border: semantic.ui.border,
btn_primary_bg: semantic.ui.accent,
btn_primary_bg_hover: semantic.ui.accent_hover,
btn_primary_text: semantic.ui.accent_text,
btn_secondary_bg: semantic.ui.btn_bg,
btn_secondary_bg_hover: semantic.ui.btn_bg_hover,
btn_secondary_text: semantic.ui.text,
btn_secondary_border: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.ui.border),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct ContextMenuStyle {
pub bg: Color32,
pub border: Stroke,
pub rounding: f32,
pub shadow_color: Color32,
pub item_bg: Color32,
pub item_bg_hover: Color32,
pub item_bg_active: Color32,
pub item_text: Color32,
pub item_text_hover: Color32,
pub item_text_disabled: Color32,
pub icon: Color32,
pub icon_hover: Color32,
pub shortcut_text: Color32,
pub separator: Color32,
pub submenu_arrow: Color32,
}
impl ContextMenuStyle {
pub fn from_semantic(semantic: &SemanticTokens) -> Self {
Self {
bg: semantic.ui.panel_bg_floating,
border: Stroke::new(DESIGN_TOKENS.stroke.hairline, semantic.ui.border),
rounding: DESIGN_TOKENS.rounding.md,
shadow_color: Color32::from_black_alpha(60),
item_bg: Color32::TRANSPARENT,
item_bg_hover: semantic.ui.btn_bg_hover,
item_bg_active: semantic.ui.btn_bg_active,
item_text: semantic.ui.text,
item_text_hover: semantic.ui.text,
item_text_disabled: semantic.ui.text_disabled,
icon: semantic.ui.icon,
icon_hover: semantic.ui.icon_hover,
shortcut_text: semantic.ui.text_muted,
separator: semantic.ui.border_subtle,
submenu_arrow: semantic.ui.icon,
}
}
}
#[derive(Clone, Debug)]
pub struct ComponentStyles {
pub btn_primary: BtnStyle,
pub btn_secondary: BtnStyle,
pub btn_ghost: BtnStyle,
pub toolbar: ToolbarStyle,
pub panel: PanelStyle,
pub panel_floating: PanelStyle,
pub menu: MenuStyle,
pub input: InputStyle,
pub dialog: DialogStyle,
pub settings_dialog: SettingsDialogStyle,
pub ctx_menu: ContextMenuStyle,
pub chart: ChartStyle,
pub candle: CandleStyle,
pub volume: VolumeStyle,
}
impl ComponentStyles {
pub fn from_semantic(semantic: &SemanticTokens) -> Self {
Self {
btn_primary: BtnStyle::primary(semantic),
btn_secondary: BtnStyle::secondary(semantic),
btn_ghost: BtnStyle::ghost(semantic),
toolbar: ToolbarStyle::from_semantic(semantic),
panel: PanelStyle::from_semantic(semantic),
panel_floating: PanelStyle::floating(semantic),
menu: MenuStyle::from_semantic(semantic),
input: InputStyle::from_semantic(semantic),
dialog: DialogStyle::from_semantic(semantic),
settings_dialog: SettingsDialogStyle::from_semantic(semantic),
ctx_menu: ContextMenuStyle::from_semantic(semantic),
chart: ChartStyle::from_semantic(semantic),
candle: CandleStyle::from_semantic(semantic),
volume: VolumeStyle::from_semantic(semantic),
}
}
}