Skip to content

Instantly share code, notes, and snippets.

@zachgibson
Created October 25, 2025 16:58
Show Gist options
  • Select an option

  • Save zachgibson/ac8591934cdb37b05c281e0ecf023e50 to your computer and use it in GitHub Desktop.

Select an option

Save zachgibson/ac8591934cdb37b05c281e0ecf023e50 to your computer and use it in GitHub Desktop.
This is mimics a keyboard toolbar, but uses safeAreaBar instead. This allows the bar to have custom layout properties (like bottom padding). iOS 26.0.1 has a bug where toolbar items with keyboard placement sit directly on the keyboard with no bottom padding whatsoever.
import Combine
import SwiftUI
struct ContentView: View {
@State var text = ""
@State var keyboardObserver = KeyboardObserver()
@Namespace var union
var body: some View {
VStack {
TextField("Search", text: $text)
.textFieldStyle(.roundedBorder)
.padding()
Spacer()
}
.safeAreaBar(edge: .bottom) {
HStack {
GlassEffectContainer {
HStack(spacing: 0) {
Button {
print("bold pressed")
} label: {
Image(systemName: "bold")
.font(.system(size: 22))
.padding(4)
}
.buttonStyle(.glass)
.glassEffectUnion(id: "union", namespace: union)
Button {
print("italic pressed")
} label: {
Image(systemName: "italic")
.font(.system(size: 22))
.padding(4)
}
.buttonStyle(.glass)
.glassEffectUnion(id: "union", namespace: union)
Button {
print("underline pressed")
} label: {
Image(systemName: "underline")
.font(.system(size: 22))
.padding(4)
}
.buttonStyle(.glass)
.glassEffectUnion(id: "union", namespace: union)
}
}
Spacer()
Button {
UIApplication.shared.sendAction(
#selector(UIResponder.resignFirstResponder),
to: nil,
from: nil,
for: nil
)
} label: {
Image(systemName: "keyboard.chevron.compact.down")
.font(.system(size: 22))
.padding(4)
}
.buttonStyle(.glass)
}
.padding()
.opacity(keyboardObserver.isVisible ? 1 : 0)
}
}
}
@Observable
class KeyboardObserver {
var isVisible: Bool = false
var height: CGFloat = 0
private var cancellables = Set<AnyCancellable>()
init() {
NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)
.map { notif -> (Bool, CGFloat) in
let endFrame = (notif.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect) ?? .zero
return (true, endFrame.height)
}
.merge(
with: NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)
.map { _ -> (Bool, CGFloat) in (false, 0) }
)
.receive(on: RunLoop.main)
.sink { [weak self] (visible, height) in
self?.isVisible = visible
self?.height = height
}
.store(in: &cancellables)
}
}
#Preview {
ContentView()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment