Native Liquid Glass Tab Bar Request
Nucleic-Session: 11F2B35E-E813-4A5E-AD28-9173ECC0B789 Co-authored-by: Nucleic <[email protected]>
This commit is contained in:
@@ -175,6 +175,10 @@ struct NucleicTabBar: View {
|
|||||||
@Binding var selection: Int
|
@Binding var selection: Int
|
||||||
/// Sessions blocking on a human — the red badge on the Sessions item (was the tab item badge).
|
/// Sessions blocking on a human — the red badge on the Sessions item (was the tab item badge).
|
||||||
var needsYou: Int
|
var needsYou: Int
|
||||||
|
@Environment(\.accessibilityReduceMotion) private var reduceMotion
|
||||||
|
/// Ties every item's selected-capsule to one shared geometry, so the "bubble" interpolates its
|
||||||
|
/// frame from the old tab to the new one instead of cross-fading — the native bar's slide.
|
||||||
|
@Namespace private var bubble
|
||||||
|
|
||||||
private struct Item { let index: Int; let title: String; let icon: String }
|
private struct Item { let index: Int; let title: String; let icon: String }
|
||||||
private let items = [
|
private let items = [
|
||||||
@@ -193,6 +197,10 @@ struct NucleicTabBar: View {
|
|||||||
.padding(.horizontal, 6)
|
.padding(.horizontal, 6)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
.glassBar()
|
.glassBar()
|
||||||
|
// Drive the bubble's slide (and the label/tint crossfade) off the selection itself, so any
|
||||||
|
// change — tap here or a programmatic jump from a notification — springs across.
|
||||||
|
.animation(reduceMotion ? nil : .spring(response: 0.32, dampingFraction: 0.78),
|
||||||
|
value: selection)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func itemButton(_ item: Item) -> some View {
|
private func itemButton(_ item: Item) -> some View {
|
||||||
@@ -220,11 +228,14 @@ struct NucleicTabBar: View {
|
|||||||
.foregroundStyle(selected ? Palette.accent : Color.secondary)
|
.foregroundStyle(selected ? Palette.accent : Color.secondary)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding(.vertical, 4)
|
.padding(.vertical, 4)
|
||||||
// The selected item rides a soft accent-tinted capsule, echoing the system floating
|
// The selected item rides a soft accent-tinted capsule that slides between tabs — only
|
||||||
// bar's highlighted tab.
|
// the selected item mounts it, and the shared `bubble` geometry makes the single capsule
|
||||||
|
// travel to the new tab, echoing the system floating bar's highlighted-tab indicator.
|
||||||
.background {
|
.background {
|
||||||
if selected {
|
if selected {
|
||||||
Capsule().fill(Palette.accent.opacity(0.15))
|
Capsule()
|
||||||
|
.fill(Palette.accent.opacity(0.15))
|
||||||
|
.matchedGeometryEffect(id: "selectionBubble", in: bubble)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
|
|||||||
Reference in New Issue
Block a user