Skip to content

Instantly share code, notes, and snippets.

@Codelaby
Last active January 24, 2025 12:01
Show Gist options
  • Select an option

  • Save Codelaby/815725f1828a2ecdd2bedc2370686a53 to your computer and use it in GitHub Desktop.

Select an option

Save Codelaby/815725f1828a2ecdd2bedc2370686a53 to your computer and use it in GitHub Desktop.
Floating Label input field by SwiftUI
import SwiftUI
fileprivate extension View {
@ViewBuilder func reverseMask<Mask: View>(
alignment: Alignment = .center,
@ViewBuilder _ mask: () -> Mask
) -> some View {
self.mask {
Rectangle()
.overlay(alignment: alignment) {
mask()
.blendMode(.destinationOut)
}
}
}
}
struct CustomTextField: View {
@Binding var text: String
let placeholder: String
@FocusState var focused: Bool
let fgColor = Color.primary
let placeholderColor = Color.secondary
let outlineNotFocused = Color.secondary.opacity(0.28)
let labelColor = Color.primary
var body: some View {
let isFilled = text.count > 0
ZStack {
TextField("", text: $text)
.frame(height: 24)
.focused($focused)
.padding(.horizontal)
.foregroundStyle(fgColor)
}
.frame(height: 56) //size component
.background {
RoundedRectangle(cornerRadius: 12)
.stroke(focused ? Color.accentColor : outlineNotFocused, lineWidth: 2)
.padding(2)
.reverseMask(alignment: .leading) {
Text(placeholder)
.frame(height: 16)
.font(isFilled ? .caption : .body)
.background { // for label padding
Rectangle()
.fill()
.stroke(.red, lineWidth: 8)
}
.padding(.leading)
.offset(y: isFilled ? -28 : 0)
}
.overlay(alignment: .leading) {
Text(placeholder)
.frame(height: 16)
.padding(.leading)
.font(isFilled ? .caption : .body)
//.font(.system(size: isFilled ? 12 : 16, weight: .regular))
.offset(y: isFilled ? -28 : 0)
.foregroundStyle(isFilled ? labelColor : placeholderColor)
}
}
.onTapGesture {
focused = true
}
.animation(.smooth, value: isFilled)
}
}
#Preview {
struct PreviewWrapper: View {
@State private var username: String = ""
@State private var password: String = ""
var body: some View {
VStack {
CustomTextField(text: $username, placeholder: "Username")
CustomTextField(text: $password, placeholder: "Password")
}
.accentColor(.primary) // change color highlight outline
.padding()
}
}
return PreviewWrapper()
.background(.brown.tertiary)
//.environment(\.layoutDirection, .rightToLeft)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment