Another project
0

Configure Feed

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

dropdown, visuals & theme color

Lewis: May this revision serve well! <lu5a@proton.me>

Lewis (Jul 3, 2026, 11:19 PM +0300) 7add0d5e 36a06d1d

+65 -6
+3 -1
crates/bone-ui/src/hit_test.rs
··· 77 77 ); 78 78 assert!( 79 79 self.seen.insert(item.id), 80 - "duplicate WidgetId in HitFrame: {:?}", 80 + "duplicate WidgetId in HitFrame: {:?} rect={:?} sense={:?}", 81 81 item.id, 82 + item.rect, 83 + item.sense, 82 84 ); 83 85 self.items.push(item); 84 86 }
+2
crates/bone-ui/src/hotkey.rs
··· 42 42 FeatureTree, 43 43 Sketch, 44 44 Extrude, 45 + Revolve, 46 + Datum, 45 47 Modal, 46 48 TextInput, 47 49 }
+20
crates/bone-ui/src/theme/color.rs
··· 97 97 } 98 98 99 99 #[must_use] 100 + pub fn srgb_f32(self) -> [f32; 3] { 101 + let alpha = self.0[3]; 102 + let inv = if alpha > 0.0 { 1.0 / alpha } else { 0.0 }; 103 + [ 104 + encode_srgb_channel(self.0[0] * inv), 105 + encode_srgb_channel(self.0[1] * inv), 106 + encode_srgb_channel(self.0[2] * inv), 107 + ] 108 + } 109 + 110 + #[must_use] 100 111 pub fn alpha(self) -> f32 { 101 112 self.0[3] 102 113 } ··· 144 155 } 145 156 146 157 const CONTRAST_LUMINANCE_THRESHOLD: f32 = 0.179; 158 + 159 + fn encode_srgb_channel(channel: f32) -> f32 { 160 + let channel = channel.clamp(0.0, 1.0); 161 + if channel <= 0.003_130_8 { 162 + 12.92 * channel 163 + } else { 164 + 1.055f32.mul_add(channel.powf(1.0 / 2.4), -0.055) 165 + } 166 + } 147 167 148 168 impl core::fmt::Debug for Color { 149 169 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+19 -2
crates/bone-ui/src/widgets/dropdown.rs
··· 574 574 Step12::BORDER 575 575 }), 576 576 }; 577 + let chevron_width = trigger_rect 578 + .size 579 + .height 580 + .value() 581 + .min(trigger_rect.size.width.value()); 582 + let label_width = (trigger_rect.size.width.value() - chevron_width).max(0.0); 583 + let label_rect = LayoutRect::new( 584 + trigger_rect.origin, 585 + LayoutSize::new(LayoutPx::new(label_width), trigger_rect.size.height), 586 + ); 587 + let chevron_rect = LayoutRect::new( 588 + LayoutPos::new( 589 + LayoutPx::new(trigger_rect.origin.x.value() + label_width), 590 + trigger_rect.origin.y, 591 + ), 592 + LayoutSize::new(LayoutPx::new(chevron_width), trigger_rect.size.height), 593 + ); 577 594 let mut paint = vec![ 578 595 WidgetPaint::Surface { 579 596 rect: trigger_rect, ··· 583 600 elevation: None, 584 601 }, 585 602 WidgetPaint::Label { 586 - rect: trigger_rect, 603 + rect: label_rect, 587 604 text: LabelText::Key(label_text), 588 605 color: if disabled { 589 606 ctx.theme().colors.text_disabled() ··· 593 610 role: ctx.theme().typography.body, 594 611 }, 595 612 WidgetPaint::Mark { 596 - rect: trigger_rect, 613 + rect: chevron_rect, 597 614 kind: GlyphMark::Chevron, 598 615 color: ctx.theme().colors.text_secondary(), 599 616 },
+21 -3
crates/bone-ui/src/widgets/visuals.rs
··· 2 2 3 3 use crate::frame::FrameCtx; 4 4 use crate::hit_test::Interaction; 5 - use crate::layout::LayoutRect; 5 + use crate::layout::{LayoutPos, LayoutPx, LayoutRect, LayoutSize}; 6 6 use crate::strings::StringKey; 7 7 use crate::theme::{ 8 8 Border, Color, ElevationLevel, Radius, Spacing, Step12, StrokeWidth, Theme, TypographyRole, ··· 156 156 }); 157 157 if let Some(mark) = mark { 158 158 let color = ctx.theme().colors.contrast_text(fill); 159 + let mark_rect = leading_mark_rect(rect); 159 160 paint.push(match mark { 160 161 IndicatorMark::Check => WidgetPaint::Icon { 161 - rect, 162 + rect: mark_rect, 162 163 icon: IconId::Check, 163 164 tint: IconTint::Solid(color), 164 165 }, 165 - IndicatorMark::Glyph(kind) => WidgetPaint::Mark { rect, kind, color }, 166 + IndicatorMark::Glyph(kind) => WidgetPaint::Mark { 167 + rect: mark_rect, 168 + kind, 169 + color, 170 + }, 166 171 }); 167 172 } 168 173 push_focus_ring(ctx, paint, rect, radius, live_focused); 169 174 } 175 + 176 + fn leading_mark_rect(rect: LayoutRect) -> LayoutRect { 177 + let side = rect.size.height.value(); 178 + let inset = side * 0.22; 179 + let box_side = (side - 2.0 * inset).max(0.0); 180 + LayoutRect::new( 181 + LayoutPos::new( 182 + LayoutPx::new(rect.origin.x.value() + inset), 183 + LayoutPx::new(rect.origin.y.value() + inset), 184 + ), 185 + LayoutSize::new(LayoutPx::new(box_side), LayoutPx::new(box_side)), 186 + ) 187 + }
crates/bone-ui/tests/snapshots/gallery_dark.png

This is a binary file and will not be displayed.

crates/bone-ui/tests/snapshots/gallery_light.png

This is a binary file and will not be displayed.