diff --git a/NucleicRemote/NucleicRemote/Views/Theme.swift b/NucleicRemote/NucleicRemote/Views/Theme.swift index feff49f..0efe699 100644 --- a/NucleicRemote/NucleicRemote/Views/Theme.swift +++ b/NucleicRemote/NucleicRemote/Views/Theme.swift @@ -103,6 +103,26 @@ extension Risk { } } +/// Adds a "Done" button to the keyboard's accessory toolbar so any focused composer can always +/// dismiss the keyboard. The multiline composers (`axis: .vertical`) turn Return into a newline, +/// so without this there's no way to release the keyboard once it opens. The modifier carries its +/// own `@FocusState` and binds it to the field, keeping callers to a single `.keyboardDismissable()`. +struct KeyboardDismissable: ViewModifier { + @FocusState private var focused: Bool + func body(content: Content) -> some View { + content + .focused($focused) + .toolbar { + ToolbarItemGroup(placement: .keyboard) { + Spacer() + Button { focused = false } label: { + Label("Done", systemImage: "keyboard.chevron.compact.down") + } + } + } + } +} + /// A lifted card surface with a hairline border — the mobile echo of `AppTheme.surface`. struct CardBackground: ViewModifier { var padding: CGFloat = 14