@@ -34,13 +34,25 @@ module Buttons =
3434 let private borderRect () =
3535 Rectangle().stroke(Colors.Black).strokeThickness (4.)
3636
37− let private textButton fontSize pressOffset restOffset margin priority (text: string) (msg: 'msg) =
38− Component(text) {
37+ let private textButton fontSize pressOffset restOffset margin priority (text: string) (msg: 'msg) disabled =
38+ // Start from the opposite state's offset so the transition animates
39+ let initialOffset = if disabled then restOffset else 0.
40+
41+ Component($"{text}-{disabled}") {
3942 let! pressed = Context.State(false)
40− let offset = if pressed.Current then pressOffset else restOffset
43+ let! animOffset = Context.State(initialOffset)
44+
45+ let target =
46+ if disabled then 0.
47+ elif pressed.Current then pressOffset
48+ else restOffset
49+
50+ do
51+ if animOffset.Current <> target then
52+ Avalonia.Threading.Dispatcher.UIThread.Post(fun () -> animOffset.Set target)
4153
4254 (Grid() {
43− shadowRect offset
55+ shadowRect animOffset.Current
4456
4557 Rectangle()
4658 .fill (
@@ -65,15 +77,17 @@ module Buttons =
6577 borderRect ()
6678 })
6779 .background(Brushes.Transparent)
68− .onPointerPressed(fun _ -> pressed.Set true)
80+ .onPointerPressed(fun _ -> if not disabled then pressed.Set true)
6981 .onPointerReleased(fun _ -> pressed.Set false)
7082 .onPointerExited(fun _ -> pressed.Set false)
7183 .margin(margin)
7284 .onTapped (fun _ -> msg)
7385 }
7486
75− let button priority = textButton 24. 4. 8. 16. priority
76− let smallButton priority = textButton 16. 2. 4. 8. priority
87+ let button priority text msg = textButton 24. 4. 8. 16. priority text msg false
88+ let smallButton priority text msg = textButton 16. 2. 4. 8. priority text msg false
89+ let disabledButton priority text msg = textButton 24. 4. 8. 16. priority text msg true
90+ let disabledSmallButton priority text msg = textButton 16. 2. 4. 8. priority text msg true
7791
7892 let imageButton (img: byte[] option) (msg: 'msg) =
7993 let key =