style(ui): fade touchpad navigation indicator
- commit
- e5d60196ab9d79fcd9ca48d4112fddd96072eabe
- author
- brice · · 2026-06-18 10:09 UTC
- parent
- 0d3b8ed
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
3 files · +39 -3
M internal/ui/component/touchpad_navigation_indicator.go +5 -0
| @@ -120,6 +120,7 @@ func (i *TouchpadNavigationIndicator) ShowGesture(gesture port.TouchpadNavigatio | |||
| 120 | 120 | } | |
| 121 | 121 | i.cancelHideTimer() | |
| 122 | 122 | ||
| 123 | + | i.container.RemoveCssClass("hiding") | |
| 123 | 124 | i.container.RemoveCssClass("back") | |
| 124 | 125 | i.container.RemoveCssClass("forward") | |
| 125 | 126 | if gesture.Action == port.TouchpadNavigationForward { | |
| @@ -173,6 +174,9 @@ func (i *TouchpadNavigationIndicator) scheduleHide(triggered bool) { | |||
| 173 | 174 | i.hide() | |
| 174 | 175 | return | |
| 175 | 176 | } | |
| 177 | + | if i.container != nil { | |
| 178 | + | i.container.AddCssClass("hiding") | |
| 179 | + | } | |
| 176 | 180 | cb := glib.SourceFunc(func(_ uintptr) bool { | |
| 177 | 181 | i.hideTimer = 0 | |
| 178 | 182 | i.hide() | |
| @@ -184,6 +188,7 @@ func (i *TouchpadNavigationIndicator) scheduleHide(triggered bool) { | |||
| 184 | 188 | func (i *TouchpadNavigationIndicator) hide() { | |
| 185 | 189 | i.cancelHideTimer() | |
| 186 | 190 | if i.container != nil { | |
| 191 | + | i.container.RemoveCssClass("hiding") | |
| 187 | 192 | i.container.RemoveCssClass("threshold-reached") | |
| 188 | 193 | i.container.RemoveCssClass("back") | |
| 189 | 194 | i.container.RemoveCssClass("forward") | |
| @@ -120,6 +120,7 @@ func (i *TouchpadNavigationIndicator) ShowGesture(gesture port.TouchpadNavigatio | |||||
| 120 | } | 120 | } | ||
| 121 | i.cancelHideTimer() | 121 | i.cancelHideTimer() | ||
| 122 | 122 | ||||
| 123 | + | i.container.RemoveCssClass("hiding") | |||
| 123 | i.container.RemoveCssClass("back") | 124 | i.container.RemoveCssClass("back") | ||
| 124 | i.container.RemoveCssClass("forward") | 125 | i.container.RemoveCssClass("forward") | ||
| 125 | if gesture.Action == port.TouchpadNavigationForward { | 126 | if gesture.Action == port.TouchpadNavigationForward { | ||
| @@ -173,6 +174,9 @@ func (i *TouchpadNavigationIndicator) scheduleHide(triggered bool) { | |||||
| 173 | i.hide() | 174 | i.hide() | ||
| 174 | return | 175 | return | ||
| 175 | } | 176 | } | ||
| 177 | + | if i.container != nil { | |||
| 178 | + | i.container.AddCssClass("hiding") | |||
| 179 | + | } | |||
| 176 | cb := glib.SourceFunc(func(_ uintptr) bool { | 180 | cb := glib.SourceFunc(func(_ uintptr) bool { | ||
| 177 | i.hideTimer = 0 | 181 | i.hideTimer = 0 | ||
| 178 | i.hide() | 182 | i.hide() | ||
| @@ -184,6 +188,7 @@ func (i *TouchpadNavigationIndicator) scheduleHide(triggered bool) { | |||||
| 184 | func (i *TouchpadNavigationIndicator) hide() { | 188 | func (i *TouchpadNavigationIndicator) hide() { | ||
| 185 | i.cancelHideTimer() | 189 | i.cancelHideTimer() | ||
| 186 | if i.container != nil { | 190 | if i.container != nil { | ||
| 191 | + | i.container.RemoveCssClass("hiding") | |||
| 187 | i.container.RemoveCssClass("threshold-reached") | 192 | i.container.RemoveCssClass("threshold-reached") | ||
| 188 | i.container.RemoveCssClass("back") | 193 | i.container.RemoveCssClass("back") | ||
| 189 | i.container.RemoveCssClass("forward") | 194 | i.container.RemoveCssClass("forward") | ||
M internal/ui/theme/css.go +16 -3
| @@ -770,16 +770,22 @@ func generateTouchpadNavigationIndicatorCSS(p Palette) string { | |||
| 770 | 770 | return `/* ===== Touchpad Navigation Indicator Styling ===== */ | |
| 771 | 771 | ||
| 772 | 772 | .touchpad-navigation-indicator { | |
| 773 | - | background-color: alpha(var(--surface), 0.94); | |
| 773 | + | background-color: alpha(var(--surface), 0.90); | |
| 774 | 774 | color: var(--text); | |
| 775 | 775 | border: 0.0625em solid alpha(var(--border), 0.72); | |
| 776 | 776 | border-radius: 1.125em; | |
| 777 | 777 | padding: 0.75em 0.875em 0.8125em; | |
| 778 | + | opacity: 1; | |
| 779 | + | filter: blur(0px); | |
| 780 | + | backdrop-filter: blur(0.75em); | |
| 778 | 781 | box-shadow: 0 1em 2.25em alpha(black, 0.30), | |
| 779 | 782 | 0 0.0625em 0 alpha(white, 0.06) inset; | |
| 780 | - | transition: background-color 140ms ease-out, | |
| 783 | + | transition: opacity 220ms ease-out, | |
| 784 | + | filter 220ms ease-out, | |
| 785 | + | backdrop-filter 220ms ease-out, | |
| 786 | + | background-color 140ms ease-out, | |
| 781 | 787 | border-color 140ms ease-out, | |
| 782 | - | box-shadow 140ms ease-out; | |
| 788 | + | box-shadow 220ms ease-out; | |
| 783 | 789 | } | |
| 784 | 790 | ||
| 785 | 791 | .touchpad-navigation-indicator.back { | |
| @@ -797,6 +803,13 @@ func generateTouchpadNavigationIndicatorCSS(p Palette) string { | |||
| 797 | 803 | 0 0 0 0.0625em alpha(var(--accent), 0.24) inset; | |
| 798 | 804 | } | |
| 799 | 805 | ||
| 806 | + | .touchpad-navigation-indicator.hiding { | |
| 807 | + | opacity: 0; | |
| 808 | + | filter: blur(0.0625em); | |
| 809 | + | box-shadow: 0 0.375em 0.875em alpha(black, 0.10), | |
| 810 | + | 0 0 0 0.0625em alpha(var(--accent), 0.04) inset; | |
| 811 | + | } | |
| 812 | + | ||
| 800 | 813 | .touchpad-navigation-header { | |
| 801 | 814 | min-width: 9.75em; | |
| 802 | 815 | } | |
| @@ -770,16 +770,22 @@ func generateTouchpadNavigationIndicatorCSS(p Palette) string { | |||||
| 770 | return `/* ===== Touchpad Navigation Indicator Styling ===== */ | 770 | return `/* ===== Touchpad Navigation Indicator Styling ===== */ | ||
| 771 | 771 | ||||
| 772 | .touchpad-navigation-indicator { | 772 | .touchpad-navigation-indicator { | ||
| 773 | - | background-color: alpha(var(--surface), 0.94); | 773 | + | background-color: alpha(var(--surface), 0.90); |
| 774 | color: var(--text); | 774 | color: var(--text); | ||
| 775 | border: 0.0625em solid alpha(var(--border), 0.72); | 775 | border: 0.0625em solid alpha(var(--border), 0.72); | ||
| 776 | border-radius: 1.125em; | 776 | border-radius: 1.125em; | ||
| 777 | padding: 0.75em 0.875em 0.8125em; | 777 | padding: 0.75em 0.875em 0.8125em; | ||
| 778 | + | opacity: 1; | |||
| 779 | + | filter: blur(0px); | |||
| 780 | + | backdrop-filter: blur(0.75em); | |||
| 778 | box-shadow: 0 1em 2.25em alpha(black, 0.30), | 781 | box-shadow: 0 1em 2.25em alpha(black, 0.30), | ||
| 779 | 0 0.0625em 0 alpha(white, 0.06) inset; | 782 | 0 0.0625em 0 alpha(white, 0.06) inset; | ||
| 780 | - | transition: background-color 140ms ease-out, | 783 | + | transition: opacity 220ms ease-out, |
| 784 | + | filter 220ms ease-out, | |||
| 785 | + | backdrop-filter 220ms ease-out, | |||
| 786 | + | background-color 140ms ease-out, | |||
| 781 | border-color 140ms ease-out, | 787 | border-color 140ms ease-out, | ||
| 782 | - | box-shadow 140ms ease-out; | 788 | + | box-shadow 220ms ease-out; |
| 783 | } | 789 | } | ||
| 784 | 790 | ||||
| 785 | .touchpad-navigation-indicator.back { | 791 | .touchpad-navigation-indicator.back { | ||
| @@ -797,6 +803,13 @@ func generateTouchpadNavigationIndicatorCSS(p Palette) string { | |||||
| 797 | 0 0 0 0.0625em alpha(var(--accent), 0.24) inset; | 803 | 0 0 0 0.0625em alpha(var(--accent), 0.24) inset; | ||
| 798 | } | 804 | } | ||
| 799 | 805 | ||||
| 806 | + | .touchpad-navigation-indicator.hiding { | |||
| 807 | + | opacity: 0; | |||
| 808 | + | filter: blur(0.0625em); | |||
| 809 | + | box-shadow: 0 0.375em 0.875em alpha(black, 0.10), | |||
| 810 | + | 0 0 0 0.0625em alpha(var(--accent), 0.04) inset; | |||
| 811 | + | } | |||
| 812 | + | ||||
| 800 | .touchpad-navigation-header { | 813 | .touchpad-navigation-header { | ||
| 801 | min-width: 9.75em; | 814 | min-width: 9.75em; | ||
| 802 | } | 815 | } | ||
M internal/ui/theme/css_test.go +18 -0
| @@ -235,6 +235,24 @@ func cssRuleBlock(t *testing.T, css, selector string) string { | |||
| 235 | 235 | return matches[1] | |
| 236 | 236 | } | |
| 237 | 237 | ||
| 238 | + | func TestGenerateCSS_TouchpadNavigationIndicatorFadesWholeOverlay(t *testing.T) { | |
| 239 | + | css := GenerateCSS(DefaultDarkPalette()) | |
| 240 | + | ||
| 241 | + | baseBlock := cssRuleBlock(t, css, ".touchpad-navigation-indicator") | |
| 242 | + | assert.Contains(t, baseBlock, "opacity: 1;") | |
| 243 | + | assert.Contains(t, baseBlock, "filter: blur(0px);") | |
| 244 | + | assert.Contains(t, baseBlock, "backdrop-filter: blur(0.75em);") | |
| 245 | + | assert.Contains(t, baseBlock, "transition: opacity 220ms ease-out,") | |
| 246 | + | assert.Contains(t, baseBlock, "filter 220ms ease-out,") | |
| 247 | + | assert.Contains(t, baseBlock, "backdrop-filter 220ms ease-out,") | |
| 248 | + | assert.Contains(t, baseBlock, "box-shadow 220ms ease-out;") | |
| 249 | + | ||
| 250 | + | hidingBlock := cssRuleBlock(t, css, ".touchpad-navigation-indicator.hiding") | |
| 251 | + | assert.Contains(t, hidingBlock, "opacity: 0;") | |
| 252 | + | assert.Contains(t, hidingBlock, "filter: blur(0.0625em);") | |
| 253 | + | assert.Contains(t, hidingBlock, "box-shadow:") | |
| 254 | + | } | |
| 255 | + | ||
| 238 | 256 | func TestGenerateCSS_DoesNotEmitUnsupportedGTKProperties(t *testing.T) { | |
| 239 | 257 | css := GenerateCSS(DefaultDarkPalette()) | |
| 240 | 258 | ||
| @@ -235,6 +235,24 @@ func cssRuleBlock(t *testing.T, css, selector string) string { | |||||
| 235 | return matches[1] | 235 | return matches[1] | ||
| 236 | } | 236 | } | ||
| 237 | 237 | ||||
| 238 | + | func TestGenerateCSS_TouchpadNavigationIndicatorFadesWholeOverlay(t *testing.T) { | |||
| 239 | + | css := GenerateCSS(DefaultDarkPalette()) | |||
| 240 | + | ||||
| 241 | + | baseBlock := cssRuleBlock(t, css, ".touchpad-navigation-indicator") | |||
| 242 | + | assert.Contains(t, baseBlock, "opacity: 1;") | |||
| 243 | + | assert.Contains(t, baseBlock, "filter: blur(0px);") | |||
| 244 | + | assert.Contains(t, baseBlock, "backdrop-filter: blur(0.75em);") | |||
| 245 | + | assert.Contains(t, baseBlock, "transition: opacity 220ms ease-out,") | |||
| 246 | + | assert.Contains(t, baseBlock, "filter 220ms ease-out,") | |||
| 247 | + | assert.Contains(t, baseBlock, "backdrop-filter 220ms ease-out,") | |||
| 248 | + | assert.Contains(t, baseBlock, "box-shadow 220ms ease-out;") | |||
| 249 | + | ||||
| 250 | + | hidingBlock := cssRuleBlock(t, css, ".touchpad-navigation-indicator.hiding") | |||
| 251 | + | assert.Contains(t, hidingBlock, "opacity: 0;") | |||
| 252 | + | assert.Contains(t, hidingBlock, "filter: blur(0.0625em);") | |||
| 253 | + | assert.Contains(t, hidingBlock, "box-shadow:") | |||
| 254 | + | } | |||
| 255 | + | ||||
| 238 | func TestGenerateCSS_DoesNotEmitUnsupportedGTKProperties(t *testing.T) { | 256 | func TestGenerateCSS_DoesNotEmitUnsupportedGTKProperties(t *testing.T) { | ||
| 239 | css := GenerateCSS(DefaultDarkPalette()) | 257 | css := GenerateCSS(DefaultDarkPalette()) | ||
| 240 | 258 | ||||