Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- `password input` component to version 1.3.1 (Orange-OpenSource/ouds-ios#1526)
- `text input` component to version 1.4.1 (Orange-OpenSource/ouds-ios#1524)
- `text area` component to version 1.2.1 (Orange-OpenSource/ouds-ios#1527)
- themes tunings values (Orange-OpenSource/ouds-ios#1669)
- `button` component to version 3.3.0 (Orange-OpenSource/ouds-ios#1583)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ import SwiftUI
///
/// ![A text input component in light and dark modes with Wireframe theme](component_passwordInput_Wireframe)
///
/// - Version: 1.3.0 (Figma component design version)
/// - Version: 1.3.1 (Figma component design version)
/// - Since: 1.2.0
@available(iOS 15, macOS 13, visionOS 1, *)
public struct OUDSPasswordInput: View {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,19 @@ struct InputText: View {
.multilineTextAlignment(.leading)
.foregroundColor(inputTextColor)
.tint(cursorColor.color(for: colorScheme))
.disabled(status == .disabled || status == .readOnly || status == .loading)
.disabled(disabled)
}

// MARK: - Helper
// MARK: - Helpers

private var disabled: Bool {
switch status {
case .disabled, .readOnly, .loading:
true
default:
false
}
}

private var labelColor: MultipleColorSemanticToken {
switch status {
Expand Down Expand Up @@ -106,7 +115,7 @@ private struct SecureTextFieldModifier: ViewModifier {
.textContentType(.password)
.autocorrectionDisabled(true)
#if !os(macOS)
.textInputAutocapitalization(.never)
.textInputAutocapitalization(.never)
#endif
} else {
content
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,25 @@ struct TextInputContainer: View {
HStack(alignment: .center, spacing: theme.textInput.spaceColumnGapDefault) {
HStack(alignment: .center, spacing: theme.textInput.spaceColumnGapDefault) {
// Leading icon container
LeadingIconContainer(leadingIcon: leadingIcon, status: status)
TextInputLeadingIconContainer(leadingIcon: leadingIcon, status: status)

// ZStack here to add the label above the textField when
// the text is empty, the placeholder is empty and not focused
// Otherwise the label is placed at the top
ZStack {
if labelPosition == .middle {
LabelContainer(label: label,
status: status,
interactionState: interactionState,
position: .middle)
TextInputLabelContainer(label: label,
status: status,
interactionState: interactionState,
position: .middle)
}

VStack(alignment: .leading, spacing: theme.textInput.spaceRowGapLabelInput) {
if labelPosition == .top {
LabelContainer(label: label,
status: status,
interactionState: interactionState,
position: .top)
TextInputLabelContainer(label: label,
Comment thread
pylapp marked this conversation as resolved.
status: status,
interactionState: interactionState,
position: .top)
}

InputContainer(text: text,
Expand All @@ -81,8 +81,8 @@ struct TextInputContainer: View {
}
}

// Trailing action container
TrailingActionContainer(trailingAction: trailingAction, status: status, interactionState: interactionState)
// Trailing container
TextInputTrailingContainer(trailingAction: trailingAction, status: status, interactionState: interactionState)
}
.padding(.vertical, theme.textInput.spacePaddingBlockDefault)
.padding(.leading, theme.textInput.spacePaddingInlineDefault)
Expand All @@ -91,14 +91,14 @@ struct TextInputContainer: View {
.modifier(TextInputBackgroundModifier(status: status, isOutlined: isOutlined, interactionState: interactionState))
.modifier(TextInputBorderModifier(status: status, isOutlined: isOutlined, interactionState: interactionState))
#if !os(watchOS) && !os(tvOS)
.onHover { hover = $0 }
.onHover { hover = $0 }
#endif
// swiftlint:enable accessibility_trait_for_button
}

// MARK: - Helpers

private var labelPosition: LabelContainer.Position {
private var labelPosition: TextInputLabelContainer.Position {
if !text.wrappedValue.isEmpty || placeholder?.isEmpty == false || focused {
.top
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import OUDSTokensSemantic
import SwiftUI

struct LabelContainer: View {
struct TextInputLabelContainer: View {

// MARK: Properties

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import OUDSTokensSemantic
import SwiftUI

struct LeadingIconContainer: View {
struct TextInputLeadingIconContainer: View {

// MARK: - Properties

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import OUDSTokensSemantic
import SwiftUI

struct TrailingActionContainer: View {
struct TextInputTrailingContainer: View {

// MARK: - Properties

Expand Down Expand Up @@ -48,8 +48,10 @@ struct TrailingActionContainer: View {
trailingButton(for: trailingAction)
}
}
case .loading:
trailingButton(for: .init(image: OUDSImage(asset: Image(decorative: "ic_heart")), actionHint: "", action: {}))
case let .loading(progress):
TextInputCircularProgressIndicator(progress: progress)
.padding(.all, theme.button.spaceInsetProgressIndicatorOnlyDefault)
.padding(.all, theme.button.spaceInsetIconOnlyDefault)
Comment thread
pylapp marked this conversation as resolved.
.accessibilityHidden(true)
}
}
Expand Down Expand Up @@ -78,7 +80,7 @@ struct TrailingActionContainer: View {

return OUDSButton(image: imageWithA11y,
appearance: .minimal,
style: status == .loading ? .loading : .default,
style: .default,
action: trailingAction.action)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ import SwiftUI
///
/// ![A text input component in light and dark modes with Wireframe theme](component_textInput_Wireframe)
///
/// - Version: 1.4.0 (Figma component design version)
/// - Version: 1.4.1 (Figma component design version)
/// - Since: 0.20.0
@available(iOS 15, macOS 13, visionOS 1, *)
public struct OUDSTextInput: View {
Expand Down Expand Up @@ -262,6 +262,8 @@ public struct OUDSTextInput: View {
/// - actionHint: A string that describes the purpose of the button's `action`
/// - action: The action to perform when the user triggers the button
public init(image: OUDSImage, actionHint: String, action: @escaping () -> Void) {
precondition(image.asset != nil, "OUDSTextInput.TrailingAction.icon must be created with an asset Image")
Comment thread
pylapp marked this conversation as resolved.

if actionHint.isEmpty {
OL.warning("The accessibility action hint for the OUDSTextInput trailing action should not be empty, think about your disabled users!")
}
Expand Down Expand Up @@ -291,8 +293,11 @@ public struct OUDSTextInput: View {
case richError(message: AttributedString)

/// The `loading` state indicates that the system is processing or retrieving data related to the
/// text entered. A progress indicator appears to inform the user that an action is in progress.
case loading
/// text entered. A circular progress indicator appears to inform the user that an action is in progress.
/// The field remains editable while loading.
/// - Parameter progress: The loading progress, where 0.0 represents no progress and 1.0 represents full progress. Set this
/// value to `nil` to display a circular indeterminate progress indicator.
case loading(progress: Double? = nil)

/// The`readOnly`, lets the text visible but not editable
case readOnly
Expand All @@ -303,8 +308,10 @@ public struct OUDSTextInput: View {

public static func == (lhs: Self, rhs: Self) -> Bool {
switch (lhs, rhs) {
case (.enabled, .enabled), (.loading, .loading), (.readOnly, .readOnly), (.disabled, .disabled):
case (.enabled, .enabled), (.readOnly, .readOnly), (.disabled, .disabled):
true
case let (.loading(lhsProgress), .loading(rhsProgress)):
lhsProgress == rhsProgress
case let (.error(lhsMessage), .error(rhsMessage)):
lhsMessage == rhsMessage
case let (.richError(lhsMessage), .richError(rhsMessage)):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ import Testing

// MARK: - AttributedString Extensions Tests (foreground color only, tokens, and LocalizedStringKey overloads)

// swiftlint:disable force_unwrapping

struct AttributedStringColorExtensionsTests {

// MARK: - from(text:) - Foreground color only
Expand Down Expand Up @@ -85,17 +83,17 @@ struct AttributedStringColorExtensionsTests {

// MARK: - from(_:) - LocalizedStringKey, foreground color, font and URL configurations

@Test func `from localized key with font and URL configurations applies link style`() {
@Test func `from localized key with font and URL configurations applies link style`() throws {
let key: LocalizedStringKey = "Check the privacy policy"
let urlColor = Color.red
let urlFont = Font.system(size: 14, weight: .bold)
let textColor = Color.black
let textFont = Font.system(size: 12)

let configurations: [AttributedStringUrlConfiguration] = [
let configurations: [AttributedStringUrlConfiguration] = try [
AttributedStringUrlConfiguration(
text: "privacy policy",
urlToOpen: URL(string: "https://example.com/privacy")!,
urlToOpen: #require(URL(string: "https://example.com/privacy")),
color: urlColor,
font: urlFont),
]
Expand All @@ -113,17 +111,17 @@ struct AttributedStringColorExtensionsTests {
}
}

@Test func `from localized key with foreground color token, font and URL configurations applies link style`() {
@Test func `from localized key with foreground color token, font and URL configurations applies link style`() throws {
let key: LocalizedStringKey = "Check the privacy policy"
let token: ColorSemanticToken = "#000000FF"
let urlColor = Color.red
let urlFont = Font.system(size: 14, weight: .bold)
let textFont = Font.system(size: 12)

let configurations: [AttributedStringUrlConfiguration] = [
let configurations: [AttributedStringUrlConfiguration] = try [
AttributedStringUrlConfiguration(
text: "privacy policy",
urlToOpen: URL(string: "https://example.com/privacy")!,
urlToOpen: #require(URL(string: "https://example.com/privacy")),
color: urlColor,
font: urlFont),
]
Expand All @@ -142,17 +140,17 @@ struct AttributedStringColorExtensionsTests {

// MARK: - from(text:) - Foreground color token, font and URL configurations

@Test func `from text with foreground color token, font and URL configurations applies link style`() {
@Test func `from text with foreground color token, font and URL configurations applies link style`() throws {
let text = "Check the privacy policy"
let token: ColorSemanticToken = "#123456FF"
let urlColor = Color.purple
let urlFont = Font.system(size: 14)
let textFont = Font.system(size: 12)

let configurations: [AttributedStringUrlConfiguration] = [
let configurations: [AttributedStringUrlConfiguration] = try [
AttributedStringUrlConfiguration(
text: "privacy policy",
urlToOpen: URL(string: "https://example.com/privacy")!,
urlToOpen: #require(URL(string: "https://example.com/privacy")),
color: urlColor,
font: urlFont),
]
Expand Down Expand Up @@ -196,17 +194,17 @@ struct AttributedStringColorExtensionsTests {

// MARK: - from(markdown:) - Foreground color token, font and URL configurations

@Test func `from markdown with foreground color token, font and URL configurations applies link style`() {
@Test func `from markdown with foreground color token, font and URL configurations applies link style`() throws {
let markdown = "Check our [privacy policy](https://example.com/privacy)"
let token: ColorSemanticToken = "#654321FF"
let urlColor = Color.red
let urlFont = Font.system(size: 14, weight: .bold)
let textFont = Font.system(size: 12)

let configurations: [AttributedStringUrlConfiguration] = [
let configurations: [AttributedStringUrlConfiguration] = try [
AttributedStringUrlConfiguration(
text: "privacy policy",
urlToOpen: URL(string: "https://example.com/privacy")!,
urlToOpen: #require(URL(string: "https://example.com/privacy")),
color: urlColor,
font: urlFont),
]
Expand All @@ -226,9 +224,9 @@ struct AttributedStringColorExtensionsTests {

// MARK: - AttributedStringUrlConfiguration - LocalizedStringKey initializer

@Test func `configuration from localized key resolves text and stores url`() {
@Test func `configuration from localized key resolves text and stores url`() throws {
let key: LocalizedStringKey = "privacy policy"
let url = URL(string: "https://example.com/privacy")!
let url = try #require(URL(string: "https://example.com/privacy"))
let color = Color.red
let font = Font.system(size: 14)

Expand All @@ -248,5 +246,3 @@ struct AttributedStringColorExtensionsTests {
}
}
}

// swiftlint:enable force_unwrapping
Loading
Loading