|
|
@@ -0,0 +1,74 @@
|
|
|
+import SwiftUI
|
|
|
+
|
|
|
+protocol SegmentedTabItem: Hashable, Identifiable, CaseIterable {
|
|
|
+ var title: String { get }
|
|
|
+}
|
|
|
+
|
|
|
+extension CommentWriterTab: SegmentedTabItem {}
|
|
|
+extension PostGeneratorTab: SegmentedTabItem {}
|
|
|
+extension TitleOptimizerTab: SegmentedTabItem {}
|
|
|
+
|
|
|
+struct ToolSegmentedTabBar<Tab: SegmentedTabItem>: View {
|
|
|
+ @Binding var selection: Tab
|
|
|
+ var accentColor: Color
|
|
|
+ var width: CGFloat
|
|
|
+ var badgeCount: ((Tab) -> Int?)?
|
|
|
+
|
|
|
+ private let buttonCornerRadius: CGFloat = 8
|
|
|
+
|
|
|
+ var body: some View {
|
|
|
+ HStack(spacing: 6) {
|
|
|
+ ForEach(Array(Tab.allCases)) { tab in
|
|
|
+ tabButton(for: tab)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .frame(width: width)
|
|
|
+ }
|
|
|
+
|
|
|
+ private func tabButton(for tab: Tab) -> some View {
|
|
|
+ let isSelected = selection == tab
|
|
|
+
|
|
|
+ return Button {
|
|
|
+ withAnimation(.easeInOut(duration: 0.15)) {
|
|
|
+ selection = tab
|
|
|
+ }
|
|
|
+ } label: {
|
|
|
+ HStack(spacing: 4) {
|
|
|
+ Text(tab.title)
|
|
|
+ .font(.system(size: 11, weight: isSelected ? .bold : .medium))
|
|
|
+
|
|
|
+ if let count = badgeCount?(tab) {
|
|
|
+ Text("\(count)")
|
|
|
+ .font(.system(size: 9, weight: .bold))
|
|
|
+ .foregroundStyle(.white)
|
|
|
+ .padding(.horizontal, 5)
|
|
|
+ .padding(.vertical, 2)
|
|
|
+ .background(accentColor)
|
|
|
+ .clipShape(Capsule())
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .foregroundStyle(isSelected ? accentColor : AppTheme.textSecondary)
|
|
|
+ .frame(maxWidth: .infinity)
|
|
|
+ .padding(.vertical, 7)
|
|
|
+ .background(
|
|
|
+ RoundedRectangle(cornerRadius: buttonCornerRadius, style: .continuous)
|
|
|
+ .fill(isSelected ? accentColor.opacity(0.12) : AppTheme.cardBackground)
|
|
|
+ )
|
|
|
+ .overlay(
|
|
|
+ RoundedRectangle(cornerRadius: buttonCornerRadius, style: .continuous)
|
|
|
+ .stroke(
|
|
|
+ isSelected ? accentColor.opacity(0.5) : AppTheme.cardBorder,
|
|
|
+ lineWidth: isSelected ? 1.5 : 1
|
|
|
+ )
|
|
|
+ )
|
|
|
+ .shadow(
|
|
|
+ color: accentColor.opacity(isSelected ? 0.15 : 0),
|
|
|
+ radius: 2,
|
|
|
+ y: 1
|
|
|
+ )
|
|
|
+ }
|
|
|
+ .buttonStyle(.plain)
|
|
|
+ .hoverCursor()
|
|
|
+ .hoverOverlay(cornerRadius: buttonCornerRadius, isEnabled: !isSelected)
|
|
|
+ }
|
|
|
+}
|