Skip to content

Commit 5b990dd

Browse files
committed
Keep compact sidebar search above keyboard
1 parent f58a530 commit 5b990dd

3 files changed

Lines changed: 39 additions & 2 deletions

File tree

apple/src/bonsai_apple.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4216,7 +4216,7 @@ module For_testing = struct
42164216
^ " sidebar-safe-area-padding=swift top=max-safe-area-plus-5-or-54 \
42174217
bottom=max-safe-area-or-34"
42184218
^ " sidebar-shell-background=home-body-ignores-safe-area-outside-clip"
4219-
^ " sidebar-bottom-controls=safe-area-inset top-padding=10"
4219+
^ " sidebar-bottom-controls=safe-area-inset keyboard-aware top-padding=10"
42204220
^ " sidebar-scroll-disabled=dragging content-scroll-disabled=open-or-dragging"
42214221
^ " sidebar-route-selection-animation=swift-interactive-spring \
42224222
route-change-and-close"

apple/swiftui/BonsaiNativeSwiftUI.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,7 @@ private struct BonsaiNativeNodeView: View {
15361536
@State private var compactSidebarDragOffset: CGFloat = 0
15371537
@State private var compactSidebarDragAxis: DragAxis?
15381538
@State private var isCompactSidebarDragging = false
1539+
@State private var sidebarKeyboardBottomPadding: CGFloat = 0
15391540
@State private var toolbarExportFilename = "Export.txt"
15401541
@State private var toolbarExportContentType = "public.plain-text"
15411542
@State private var toolbarExportContent = ""
@@ -2194,6 +2195,16 @@ private struct BonsaiNativeNodeView: View {
21942195
.background(bonsaiHomeBodyBackground.ignoresSafeArea(.container, edges: .all))
21952196
.opacity(progress)
21962197
.scrollDisabled(isCompactSidebarDragging)
2198+
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillChangeFrameNotification)) { notification in
2199+
sidebarKeyboardBottomPadding = compactSidebarKeyboardBottomPadding(
2200+
notification: notification,
2201+
containerMaxY: proxy.frame(in: .global).maxY,
2202+
safeAreaBottom: proxy.safeAreaInsets.bottom
2203+
)
2204+
}
2205+
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in
2206+
sidebarKeyboardBottomPadding = 0
2207+
}
21972208

21982209
ZStack(alignment: .top) {
21992210
if node.sidebarCompactTopBarVisible {
@@ -2278,10 +2289,23 @@ private struct BonsaiNativeNodeView: View {
22782289
sidebarBottomControls
22792290
.padding(.horizontal, 12)
22802291
.padding(.top, 10)
2292+
.padding(.bottom, sidebarKeyboardBottomPadding)
2293+
.animation(.easeOut(duration: 0.2), value: sidebarKeyboardBottomPadding)
22812294
}
22822295
.frame(maxHeight: .infinity, alignment: .topLeading)
22832296
}
22842297

2298+
private func compactSidebarKeyboardBottomPadding(
2299+
notification: Notification,
2300+
containerMaxY: CGFloat,
2301+
safeAreaBottom: CGFloat
2302+
) -> CGFloat {
2303+
guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect
2304+
else { return 0 }
2305+
let overlap = max(0, containerMaxY - keyboardFrame.minY)
2306+
return max(0, overlap - safeAreaBottom)
2307+
}
2308+
22852309
private func compactSidebarVisibleWidth(revealWidth: CGFloat) -> CGFloat {
22862310
max(0, min(revealWidth, (isCompactSidebarOpen ? revealWidth : 0) + compactSidebarDragOffset))
22872311
}

apple/test/bonsai_apple_test.ml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ let test_compact_sidebar_top_bar_uses_system_toolbar_item_chrome () =
338338
require
339339
(contains
340340
rendered
341-
~substring:"sidebar-bottom-controls=safe-area-inset top-padding=10")
341+
~substring:"sidebar-bottom-controls=safe-area-inset keyboard-aware top-padding=10")
342342
"compact sidebar bottom controls should match the Swift safe-area inset layout";
343343
require
344344
(contains
@@ -366,6 +366,18 @@ let test_compact_sidebar_top_bar_uses_system_toolbar_item_chrome () =
366366
"compact sidebar should use the same open and close interaction behavior as Swift"
367367
;;
368368

369+
let test_compact_sidebar_bottom_search_tracks_keyboard () =
370+
let source = read_file swiftui_source_path in
371+
require
372+
(contains source ~substring:"sidebarKeyboardBottomPadding")
373+
"compact sidebar bottom search should add keyboard-aware bottom padding instead of \
374+
staying behind the keyboard";
375+
require
376+
(contains source ~substring:"keyboardWillChangeFrameNotification")
377+
"compact sidebar should observe keyboard frame changes for the custom full-screen \
378+
drawer"
379+
;;
380+
369381
let test_image_semantic_color_renders () =
370382
Backend.reset ();
371383
let component _graph =
@@ -1008,6 +1020,7 @@ let () =
10081020
test_sidebar_history_actions_are_separate_and_clickable ();
10091021
test_sidebar_actions_can_keep_compact_drawer_open ();
10101022
test_compact_sidebar_top_bar_uses_system_toolbar_item_chrome ();
1023+
test_compact_sidebar_bottom_search_tracks_keyboard ();
10111024
test_compact_sidebar_close_paths_share_swift_animation ();
10121025
test_navigation_value_links_keep_primary_tap_for_link ();
10131026
test_image_semantic_color_renders ();

0 commit comments

Comments
 (0)