소스 검색

Enhance tile hover interactions and spacing polish.

Improve tile hover/press feedback with smoother motion and visual emphasis, and add dedicated spacing between the promo strip and first tile row to prevent hover overlap.

Made-with: Cursor
huzaifahayat12 4 달 전
부모
커밋
ba4ca6d6bc
2개의 변경된 파일50개의 추가작업 그리고 5개의 파일을 삭제
  1. 47 5
      google_apps/AppTileView.swift
  2. 3 0
      google_apps/LauncherRootView.swift

+ 47 - 5
google_apps/AppTileView.swift

@@ -6,35 +6,77 @@ struct AppTileView: View {
     let onTap: () -> Void
 
     @State private var isHovering = false
+    @State private var isPressing = false
 
     var body: some View {
         Button(action: onTap) {
             VStack(spacing: 11) {
                 AppIconView(app: app, size: 64)
-                    .shadow(color: .black.opacity(0.2), radius: 8, x: 0, y: 5)
+                    .shadow(
+                        color: .black.opacity(isHovering ? 0.34 : 0.2),
+                        radius: isHovering ? 14 : 8,
+                        x: 0,
+                        y: isHovering ? 10 : 5
+                    )
+                    .scaleEffect(isPressing ? 0.96 : 1.0)
+                    .offset(y: isHovering ? -1 : 0)
 
                 Text(app.name)
                     .font(.system(size: 13, weight: .medium))
-                    .foregroundStyle(.white.opacity(0.95))
+                    .foregroundStyle(.white.opacity(isHovering ? 1.0 : 0.95))
                     .lineLimit(1)
                     .truncationMode(.tail)
                     .frame(maxWidth: .infinity)
+                    .offset(y: isHovering ? -0.5 : 0)
             }
             .padding(.horizontal, 7)
             .padding(.vertical, 10)
             .background(
                 RoundedRectangle(cornerRadius: 14, style: .continuous)
-                    .fill(isHovering ? Color.white.opacity(0.08) : Color.clear)
+                    .fill(
+                        LinearGradient(
+                            colors: isHovering
+                                ? [Color.white.opacity(0.14), Color.white.opacity(0.06)]
+                                : [Color.clear, Color.clear],
+                            startPoint: .topLeading,
+                            endPoint: .bottomTrailing
+                        )
+                    )
             )
             .overlay(
                 RoundedRectangle(cornerRadius: 14, style: .continuous)
-                    .stroke(isHovering ? Color.white.opacity(0.16) : Color.clear, lineWidth: 1)
+                    .stroke(
+                        isHovering ? Color.white.opacity(0.24) : Color.clear,
+                        lineWidth: isHovering ? 1.2 : 1
+                    )
+            )
+            .scaleEffect(isPressing ? 0.98 : (isHovering ? 1.025 : 1.0))
+            .offset(y: isPressing ? 0 : (isHovering ? -2 : 0))
+            .shadow(
+                color: .black.opacity(isHovering ? 0.22 : 0),
+                radius: isHovering ? 16 : 0,
+                x: 0,
+                y: isHovering ? 10 : 0
             )
-            .animation(.easeOut(duration: 0.15), value: isHovering)
+            .contentShape(RoundedRectangle(cornerRadius: 14, style: .continuous))
+            .animation(.spring(response: 0.24, dampingFraction: 0.88), value: isHovering)
+            .animation(.easeOut(duration: 0.12), value: isPressing)
         }
         .buttonStyle(.plain)
+        .simultaneousGesture(
+            DragGesture(minimumDistance: 0)
+                .onChanged { _ in
+                    isPressing = true
+                }
+                .onEnded { _ in
+                    isPressing = false
+                }
+        )
         .onHover { hovering in
             isHovering = hovering
+            if !hovering {
+                isPressing = false
+            }
         }
     }
 }

+ 3 - 0
google_apps/LauncherRootView.swift

@@ -53,6 +53,8 @@ struct LauncherRootView: View {
                     onCloseTap: { showingPremiumScreen = true },
                     onUpgradeTap: { showingPremiumScreen = true }
                 )
+                .padding(.bottom, 8)
+                .zIndex(1)
 
                 if filteredApps.isEmpty {
                     VStack(spacing: 10) {
@@ -81,6 +83,7 @@ struct LauncherRootView: View {
                                     }
                                 }
                             }
+                            .padding(.top, 10)
                             .padding(.horizontal, 14)
                             .padding(.bottom, 18)
                         }