|
|
@@ -205,11 +205,12 @@ private struct SettingsActionRow: View {
|
|
|
var isActionEnabled = true
|
|
|
let action: () -> Void
|
|
|
|
|
|
+ @State private var isRowHovered = false
|
|
|
@State private var isActionHovered = false
|
|
|
|
|
|
var body: some View {
|
|
|
HStack(spacing: 12) {
|
|
|
- SettingsRowIcon(systemName: iconName)
|
|
|
+ SettingsRowIcon(systemName: iconName, isHighlighted: isRowHovered)
|
|
|
|
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
|
Text(title)
|
|
|
@@ -243,7 +244,8 @@ private struct SettingsActionRow: View {
|
|
|
.opacity(isActionEnabled ? 1 : 0.45)
|
|
|
.onHover { isActionHovered = $0 }
|
|
|
}
|
|
|
- .padding(.vertical, 4)
|
|
|
+ .settingsRowHover(isHovered: isRowHovered)
|
|
|
+ .onHover { isRowHovered = $0 }
|
|
|
}
|
|
|
|
|
|
private var actionForeground: Color {
|
|
|
@@ -283,11 +285,11 @@ private struct SettingsLinkRow: View {
|
|
|
AppLinks.open(url)
|
|
|
} label: {
|
|
|
HStack(spacing: 12) {
|
|
|
- SettingsRowIcon(systemName: iconName)
|
|
|
+ SettingsRowIcon(systemName: iconName, isHighlighted: isHovered)
|
|
|
|
|
|
Text(title)
|
|
|
.font(.system(size: 14, weight: .semibold))
|
|
|
- .foregroundStyle(AppTheme.textPrimary)
|
|
|
+ .foregroundStyle(isHovered ? AppTheme.teal : AppTheme.textPrimary)
|
|
|
|
|
|
Spacer()
|
|
|
|
|
|
@@ -295,7 +297,7 @@ private struct SettingsLinkRow: View {
|
|
|
.font(.system(size: 11, weight: .semibold))
|
|
|
.foregroundStyle(isHovered ? AppTheme.teal : AppTheme.textMuted)
|
|
|
}
|
|
|
- .padding(.vertical, 4)
|
|
|
+ .settingsRowHover(isHovered: isHovered)
|
|
|
.contentShape(Rectangle())
|
|
|
}
|
|
|
.buttonStyle(.plain)
|
|
|
@@ -305,16 +307,18 @@ private struct SettingsLinkRow: View {
|
|
|
|
|
|
private struct SettingsRowIcon: View {
|
|
|
let systemName: String
|
|
|
+ var isHighlighted: Bool = false
|
|
|
|
|
|
var body: some View {
|
|
|
RoundedRectangle(cornerRadius: 8, style: .continuous)
|
|
|
- .fill(AppTheme.tealLight)
|
|
|
+ .fill(isHighlighted ? AppTheme.tealLight.opacity(0.85) : AppTheme.tealLight)
|
|
|
.frame(width: 32, height: 32)
|
|
|
.overlay(
|
|
|
Image(systemName: systemName)
|
|
|
.font(.system(size: 13, weight: .semibold))
|
|
|
- .foregroundStyle(AppTheme.teal)
|
|
|
+ .foregroundStyle(isHighlighted ? AppTheme.tealDark : AppTheme.teal)
|
|
|
)
|
|
|
+ .animation(.easeOut(duration: 0.15), value: isHighlighted)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -324,14 +328,16 @@ private struct SettingsToggleRow: View {
|
|
|
let subtitle: String
|
|
|
@Binding var isOn: Bool
|
|
|
|
|
|
+ @State private var isHovered = false
|
|
|
+
|
|
|
var body: some View {
|
|
|
HStack(spacing: 12) {
|
|
|
- SettingsRowIcon(systemName: iconName)
|
|
|
+ SettingsRowIcon(systemName: iconName, isHighlighted: isHovered)
|
|
|
|
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
|
Text(title)
|
|
|
.font(.system(size: 14, weight: .semibold))
|
|
|
- .foregroundStyle(AppTheme.textPrimary)
|
|
|
+ .foregroundStyle(isHovered ? AppTheme.teal : AppTheme.textPrimary)
|
|
|
|
|
|
Text(subtitle)
|
|
|
.font(.system(size: 12))
|
|
|
@@ -345,7 +351,8 @@ private struct SettingsToggleRow: View {
|
|
|
.toggleStyle(.switch)
|
|
|
.tint(AppTheme.teal)
|
|
|
}
|
|
|
- .padding(.vertical, 4)
|
|
|
+ .settingsRowHover(isHovered: isHovered)
|
|
|
+ .onHover { isHovered = $0 }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -358,3 +365,15 @@ private struct SettingsRowDivider: View {
|
|
|
.padding(.vertical, 10)
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+private extension View {
|
|
|
+ func settingsRowHover(isHovered: Bool) -> some View {
|
|
|
+ padding(.horizontal, 8)
|
|
|
+ .padding(.vertical, 6)
|
|
|
+ .background(
|
|
|
+ RoundedRectangle(cornerRadius: 8, style: .continuous)
|
|
|
+ .fill(isHovered ? AppTheme.tealLight.opacity(0.55) : Color.clear)
|
|
|
+ )
|
|
|
+ .animation(.easeOut(duration: 0.15), value: isHovered)
|
|
|
+ }
|
|
|
+}
|