Skip to content

Instantly share code, notes, and snippets.

@nikstar
Created September 13, 2024 09:50
Show Gist options
  • Save nikstar/c3539f20beaa14f3e41fc32f38cb3fd6 to your computer and use it in GitHub Desktop.
Save nikstar/c3539f20beaa14f3e41fc32f38cb3fd6 to your computer and use it in GitHub Desktop.
struct TabBar: View {
@State private var selectedTab: Tab = .overview
@Namespace private var ns
enum Tab {
case overview, data, graphs, settings
}
var body: some View {
HStack(spacing: 0) {
Button(action: { selectedTab = .overview }) {
Text("Overview")
}
.matchedGeometryEffect(id: Tab.overview, in: ns)
Button(action: { selectedTab = .data }) {
Text("Data")
}
.matchedGeometryEffect(id: Tab.data, in: ns)
Button(action: { selectedTab = .graphs }) {
Text("Graphs")
}
.matchedGeometryEffect(id: Tab.graphs, in: ns)
Button(action: { selectedTab = .settings }) {
Text("Settings")
}
.matchedGeometryEffect(id: Tab.settings, in: ns)
}
.overlay {
Capsule()
.fill(Color.red)
.matchedGeometryEffect(id: selectedTab, in: ns, isSource: false)
}
.overlay {
HStack(spacing: 0) {
Button(action: { selectedTab = .overview }) {
Text("Overview")
}
Button(action: { selectedTab = .data }) {
Text("Data")
}
Button(action: { selectedTab = .graphs }) {
Text("Graphs")
}
Button(action: { selectedTab = .settings }) {
Text("Settings")
}
}
.foregroundStyle(.white)
.mask {
Capsule()
.fill(Color.red)
.matchedGeometryEffect(id: selectedTab, in: ns, isSource: false)
}
.allowsHitTesting(false)
}
.buttonStyle(TabBarButtonStyle())
.animation(.snappy, value: selectedTab)
// .animation(.spring(duration: 2.3), value: selectedTab)
}
}
struct TabBarButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(.callout.weight(.semibold))
.padding(.horizontal, 16)
.padding(.vertical, 8)
.contentShape(.capsule)
.opacity(configuration.isPressed ? 0.75 : 1)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment