generated from bitwarden/template
-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PM-17001: Add BitwardenFloatingTextLabel
- Loading branch information
1 parent
883761a
commit ff68f0d
Showing
3 changed files
with
152 additions
and
89 deletions.
There are no files selected for viewing
143 changes: 143 additions & 0 deletions
143
BitwardenShared/UI/Platform/Application/Views/BitwardenFloatingTextLabel.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
import SwiftUI | ||
|
||
// MARK: - BitwardenFloatingTextLabel | ||
|
||
/// A component for displaying a floating text label for a text input field. The text label can | ||
/// display as a placeholder centered over the input field until the field either has focus or | ||
/// contains a value. At that point, the text label will float up above the input field. This is | ||
/// primarily meant to wrap a text field or view. | ||
/// | ||
struct BitwardenFloatingTextLabel<Content: View, TrailingContent: View>: View { | ||
// MARK: Properties | ||
|
||
/// The primary content containing the text input field for the label. | ||
let content: Content | ||
|
||
/// The title of the field. | ||
let title: String? | ||
|
||
/// Whether the title text should display as a placeholder centered over the field. | ||
let showPlaceholder: Bool | ||
|
||
/// Optional trailing content to display on the trailing edge of the label and text input field. | ||
let trailingContent: TrailingContent? | ||
|
||
// MARK: View | ||
|
||
var body: some View { | ||
HStack(spacing: 8) { | ||
ZStack(alignment: showPlaceholder ? .leading : .topLeading) { | ||
// The placeholder and title text which is vertically centered in the view when the | ||
// text field doesn't have focus and is empty and otherwise displays above the text field. | ||
titleText(showPlaceholder: showPlaceholder) | ||
.accessibilityHidden(true) | ||
|
||
// Since the title changes font size based on if it's the placeholder, this hidden | ||
// view preserves space to show the title in it's placeholder form. This prevents | ||
// the field from changing size when the placeholder's visibility changes. | ||
titleText(showPlaceholder: true) | ||
.hidden() | ||
|
||
VStack(alignment: .leading, spacing: 2) { | ||
// This preserves space for the title to lay out above the text field when | ||
// it transitions from the centered to top position. But it's always hidden and | ||
// the text above is the one that moves during the transition. | ||
titleText(showPlaceholder: false) | ||
.hidden() | ||
|
||
content | ||
} | ||
} | ||
|
||
trailingContent | ||
} | ||
.animation(.linear(duration: 0.1), value: showPlaceholder) | ||
.padding(.trailing, 16) | ||
.padding(.vertical, 12) | ||
.frame(minHeight: 64) | ||
} | ||
|
||
// MARK: Initialization | ||
|
||
/// Initialize a `BitwardenFloatingTextLabel`. | ||
/// | ||
/// - Parameters: | ||
/// - title: The title of the field. | ||
/// - showPlaceholder: Whether the title text should display as a placeholder centered over | ||
/// the field. | ||
/// - content: The primary content containing the text input field for the label. | ||
/// - trailingContent: Optional trailing content to display on the trailing edge of the label | ||
/// and text input field. | ||
/// | ||
init( | ||
title: String?, | ||
showPlaceholder: Bool, | ||
@ViewBuilder content: () -> Content, | ||
@ViewBuilder trailingContent: () -> TrailingContent | ||
) { | ||
self.content = content() | ||
self.showPlaceholder = showPlaceholder | ||
self.title = title | ||
self.trailingContent = trailingContent() | ||
} | ||
|
||
/// Initialize a `BitwardenFloatingTextLabel`. | ||
/// | ||
/// - Parameters: | ||
/// - title: The title of the field. | ||
/// - showPlaceholder: Whether the title text should display as a placeholder centered over | ||
/// the field. | ||
/// - content: The primary content containing the text input field for the label. | ||
/// | ||
init( | ||
title: String?, | ||
showPlaceholder: Bool, | ||
@ViewBuilder content: () -> Content | ||
) where TrailingContent == EmptyView { | ||
self.content = content() | ||
self.showPlaceholder = showPlaceholder | ||
self.title = title | ||
trailingContent = nil | ||
} | ||
|
||
// MARK: Private | ||
|
||
/// The title/placeholder text for the field. | ||
@ViewBuilder | ||
private func titleText(showPlaceholder: Bool) -> some View { | ||
if let title { | ||
Text(title) | ||
.styleGuide( | ||
showPlaceholder ? .body : .subheadline, | ||
weight: showPlaceholder ? .regular : .semibold, | ||
includeLinePadding: false, | ||
includeLineSpacing: false | ||
) | ||
.foregroundStyle(Asset.Colors.textSecondary.swiftUIColor) | ||
} | ||
} | ||
} | ||
|
||
// MARK: - Previews | ||
|
||
#if DEBUG | ||
#Preview { | ||
VStack { | ||
BitwardenFloatingTextLabel(title: "Title", showPlaceholder: true) { | ||
TextField("", text: .constant("")) | ||
} | ||
|
||
BitwardenFloatingTextLabel(title: "Title", showPlaceholder: false) { | ||
TextField("", text: .constant("Value")) | ||
} | ||
|
||
BitwardenFloatingTextLabel(title: "Title", showPlaceholder: false) { | ||
TextField("", text: .constant("Value")) | ||
} trailingContent: { | ||
Asset.Images.cog24.swiftUIImage | ||
.foregroundStyle(Asset.Colors.iconPrimary.swiftUIColor) | ||
} | ||
} | ||
.padding() | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters