File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -33,6 +33,7 @@ struct ArtistDetailView: View { // swiftlint:disable:this type_body_length
3333 . accentBackground ( from: self . viewModel. artistDetail? . thumbnailURL? . highQualityThumbnailURL)
3434 . navigationTitle ( self . artist. name)
3535 . toolbarBackgroundVisibility ( . hidden, for: . automatic)
36+ . topFade ( )
3637 . safeAreaInset ( edge: . bottom, spacing: 0 ) {
3738 if case . error = self . viewModel. loadingState { } else {
3839 PlayerBar ( )
Original file line number Diff line number Diff line change @@ -24,6 +24,7 @@ struct ArtistDiscographyView: View {
2424 }
2525 . navigationTitle ( self . viewModel. destination. sectionTitle)
2626 . toolbarBackgroundVisibility ( . hidden, for: . automatic)
27+ . topFade ( )
2728 . safeAreaInset ( edge: . bottom, spacing: 0 ) {
2829 if case . error = self . viewModel. loadingState { } else {
2930 PlayerBar ( )
Original file line number Diff line number Diff line change @@ -32,6 +32,7 @@ struct ArtistEpisodesListView: View {
3232 }
3333 . navigationTitle ( self . viewModel. destination. sectionTitle)
3434 . toolbarBackgroundVisibility ( . hidden, for: . automatic)
35+ . topFade ( )
3536 . safeAreaInset ( edge: . bottom, spacing: 0 ) {
3637 if case . error = self . viewModel. loadingState { } else {
3738 PlayerBar ( )
Original file line number Diff line number Diff line change @@ -64,6 +64,7 @@ struct PlaylistDetailView: View {
6464 )
6565 . navigationTitle ( self . playlist. title)
6666 . toolbarBackgroundVisibility ( . hidden, for: . automatic)
67+ . topFade ( )
6768 . safeAreaInset ( edge: . bottom, spacing: 0 ) {
6869 if case . error = self . viewModel. loadingState {
6970 } else {
Original file line number Diff line number Diff line change 1+ import SwiftUI
2+
3+ // MARK: - TopFade
4+
5+ /// A lightweight top overlay that fades scrolling content beneath hidden toolbar backgrounds.
6+ @available ( macOS 26 . 0 , * )
7+ struct TopFade : View {
8+ let height : CGFloat
9+
10+ var body : some View {
11+ LinearGradient (
12+ colors: [
13+ Color ( nsColor: . windowBackgroundColor) . opacity ( 0.98 ) ,
14+ Color ( nsColor: . windowBackgroundColor) . opacity ( 0.72 ) ,
15+ Color ( nsColor: . windowBackgroundColor) . opacity ( 0 ) ,
16+ ] ,
17+ startPoint: . top,
18+ endPoint: . bottom
19+ )
20+ . frame ( height: self . height)
21+ . frame ( maxWidth: . infinity)
22+ . ignoresSafeArea ( edges: . top)
23+ . allowsHitTesting ( false )
24+ . accessibilityHidden ( true )
25+ }
26+ }
27+
28+ // MARK: - TopFadeModifier
29+
30+ @available ( macOS 26 . 0 , * )
31+ struct TopFadeModifier : ViewModifier {
32+ let height : CGFloat
33+
34+ func body( content: Content ) -> some View {
35+ content
36+ . overlay ( alignment: . top) {
37+ TopFade ( height: self . height)
38+ }
39+ }
40+ }
41+
42+ @available ( macOS 26 . 0 , * )
43+ extension View {
44+ /// Adds the same top fade treatment used by toolbar-backed pages when the toolbar background is hidden.
45+ /// - Parameter height: The height of the fade overlay.
46+ /// - Returns: A view with a non-interactive top fade overlay.
47+ func topFade( height: CGFloat = 96 ) -> some View {
48+ modifier ( TopFadeModifier ( height: height) )
49+ }
50+ }
Original file line number Diff line number Diff line change @@ -38,6 +38,7 @@ struct TopSongsView: View {
3838 }
3939 . navigationTitle ( self . viewModel. title)
4040 . toolbarBackgroundVisibility ( . hidden, for: . automatic)
41+ . topFade ( )
4142 . safeAreaInset ( edge: . bottom, spacing: 0 ) {
4243 if case . error = self . viewModel. loadingState { } else {
4344 PlayerBar ( )
You can’t perform that action at this time.
0 commit comments