Another project
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 4.3 kB View raw
1use serde::Serialize; 2 3use crate::frame::FrameCtx; 4use crate::hit_test::Interaction; 5use crate::layout::LayoutRect; 6use crate::strings::StringKey; 7use crate::theme::{ 8 Border, Color, ElevationLevel, Radius, Spacing, Step12, StrokeWidth, Theme, TypographyRole, 9}; 10 11use bone_types::IconId; 12 13use super::paint::{GlyphMark, IconTint, LabelText, WidgetPaint}; 14 15#[derive(Copy, Clone, Debug, PartialEq)] 16pub enum IndicatorMark { 17 Check, 18 Glyph(GlyphMark), 19} 20 21#[derive(Copy, Clone, Debug, PartialEq, Serialize)] 22pub struct SurfaceVisuals { 23 pub fill: Color, 24 pub border: Option<Border>, 25 pub radius: Radius, 26 pub elevation: Option<ElevationLevel>, 27} 28 29#[derive(Copy, Clone, Debug, PartialEq, Serialize)] 30pub struct TextVisuals { 31 pub color: Color, 32 pub role: TypographyRole, 33} 34 35#[derive(Copy, Clone, Debug, PartialEq, Serialize)] 36pub struct FieldVisuals { 37 pub surface: SurfaceVisuals, 38 pub text: TextVisuals, 39 pub placeholder: Color, 40 pub caret: Color, 41 pub selection: Color, 42} 43 44pub fn push_focus_ring( 45 ctx: &FrameCtx<'_>, 46 paint: &mut Vec<WidgetPaint>, 47 rect: LayoutRect, 48 radius: Radius, 49 live_focused: bool, 50) { 51 if live_focused && ctx.focus.focus_visible() { 52 paint.push(WidgetPaint::FocusRing { 53 rect, 54 color: ctx.theme().colors.focus_ring(), 55 radius, 56 thickness: Spacing::px(StrokeWidth::HAIRLINE.value_px() * 2.0), 57 }); 58 } 59} 60 61#[must_use] 62pub fn indicator_fill( 63 theme: &Theme, 64 active: bool, 65 disabled: bool, 66 interaction: Interaction, 67) -> Color { 68 let neutral = theme.colors.neutral; 69 let accent = theme.colors.accent; 70 let pressed = interaction.pressed(); 71 let hovered = interaction.hover(); 72 if disabled { 73 neutral.step(Step12::SUBTLE_BG) 74 } else if active { 75 if pressed || hovered { 76 accent.step(Step12::HOVER_SOLID) 77 } else { 78 accent.step(Step12::SOLID) 79 } 80 } else if pressed { 81 neutral.step(Step12::SELECTED_BG) 82 } else if hovered { 83 neutral.step(Step12::HOVER_BG) 84 } else { 85 neutral.step(Step12::ELEMENT_BG) 86 } 87} 88 89#[must_use] 90pub fn indicator_border(theme: &Theme, active: bool, hovered: bool) -> Option<Border> { 91 (!active).then(|| Border { 92 width: StrokeWidth::HAIRLINE, 93 color: theme.colors.neutral.step(if hovered { 94 Step12::HOVER_BORDER 95 } else { 96 Step12::BORDER 97 }), 98 }) 99} 100 101#[must_use] 102pub fn indicator_label_color( 103 theme: &Theme, 104 surface_fill: Color, 105 active: bool, 106 disabled: bool, 107) -> Color { 108 if disabled { 109 theme.colors.text_disabled() 110 } else if active { 111 theme.colors.contrast_text(surface_fill) 112 } else { 113 theme.colors.text_primary() 114 } 115} 116 117#[derive(Copy, Clone, Debug, PartialEq)] 118pub struct Indicator { 119 pub rect: LayoutRect, 120 pub label: StringKey, 121 pub mark: Option<IndicatorMark>, 122 pub active: bool, 123 pub disabled: bool, 124 pub radius: Radius, 125} 126 127pub fn push_indicator( 128 ctx: &FrameCtx<'_>, 129 paint: &mut Vec<WidgetPaint>, 130 indicator: Indicator, 131 interaction: Interaction, 132 live_focused: bool, 133) { 134 let Indicator { 135 rect, 136 label, 137 mark, 138 active, 139 disabled, 140 radius, 141 } = indicator; 142 let fill = indicator_fill(ctx.theme(), active, disabled, interaction); 143 let border = indicator_border(ctx.theme(), active, interaction.hover()); 144 paint.push(WidgetPaint::Surface { 145 rect, 146 fill, 147 border, 148 radius, 149 elevation: None, 150 }); 151 paint.push(WidgetPaint::Label { 152 rect, 153 text: LabelText::Key(label), 154 color: indicator_label_color(ctx.theme(), fill, active, disabled), 155 role: ctx.theme().typography.label, 156 }); 157 if let Some(mark) = mark { 158 let color = ctx.theme().colors.contrast_text(fill); 159 paint.push(match mark { 160 IndicatorMark::Check => WidgetPaint::Icon { 161 rect, 162 icon: IconId::Check, 163 tint: IconTint::Solid(color), 164 }, 165 IndicatorMark::Glyph(kind) => WidgetPaint::Mark { rect, kind, color }, 166 }); 167 } 168 push_focus_ring(ctx, paint, rect, radius, live_focused); 169}