-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #235 from adevinta/feature/component/icon
[Icon#205] Create UIKit icon component
- Loading branch information
Showing
12 changed files
with
864 additions
and
0 deletions.
There are no files selected for viewing
16 changes: 16 additions & 0 deletions
16
core/Sources/Components/Icon/AccessibilityIdentifier/IconAccessibilityIdentifier.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,16 @@ | ||
// | ||
// IconAccessibilityIdentifier.swift | ||
// SparkCore | ||
// | ||
// Created by Jacklyn Situmorang on 20.07.23. | ||
// Copyright © 2023 Adevinta. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
public enum IconAccessibilityIdentifier { | ||
|
||
// MARK: - Properties | ||
|
||
public static let view = "spark-icon-image" | ||
} |
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,19 @@ | ||
// | ||
// IconIntent.swift | ||
// Spark | ||
// | ||
// Created by Jacklyn Situmorang on 10.07.23. | ||
// Copyright © 2023 Adevinta. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
/// Intents of the icon. | ||
public enum IconIntent: CaseIterable { | ||
case alert | ||
case error | ||
case neutral | ||
case primary | ||
case secondary | ||
case success | ||
} |
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,48 @@ | ||
// | ||
// IconSize.swift | ||
// SparkCore | ||
// | ||
// Created by Jacklyn Situmorang on 11.07.23. | ||
// Copyright © 2023 Adevinta. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
/// Different sizes of icon. | ||
public enum IconSize: CaseIterable { | ||
/// Small icon with size of 16x16px | ||
case small | ||
|
||
/// Small icon with size of 24x24px | ||
case medium | ||
|
||
/// Small icon with size of 32x32px | ||
case large | ||
|
||
/// Small icon with size of 40x40px | ||
case extraLarge | ||
} | ||
|
||
// MARK: - Extension | ||
extension IconSize { | ||
public var value: CGFloat { | ||
switch self { | ||
case .small: | ||
return Constants.valueSmall | ||
case .medium: | ||
return Constants.valueMedium | ||
case .large: | ||
return Constants.valueLarge | ||
case .extraLarge: | ||
return Constants.valueExtraLarge | ||
} | ||
} | ||
} | ||
|
||
// MARK: - Constants | ||
private enum Constants { | ||
static var valueSmall: CGFloat = 16 | ||
static var valueMedium: CGFloat = 24 | ||
static var valueLarge: CGFloat = 32 | ||
static var valueExtraLarge: CGFloat = 40 | ||
} |
36 changes: 36 additions & 0 deletions
36
core/Sources/Components/Icon/UseCase/IconGetColorUseCase.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,36 @@ | ||
// | ||
// IconGetColorUseCase.swift | ||
// Spark | ||
// | ||
// Created by Jacklyn Situmorang on 10.07.23. | ||
// Copyright © 2023 Adevinta. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
// sourcery: AutoMockable | ||
protocol IconGetColorUseCaseable { | ||
func execute(for intent: IconIntent, colors: Colors) -> any ColorToken | ||
} | ||
|
||
struct IconGetColorUseCase: IconGetColorUseCaseable { | ||
|
||
// MARK: - Methods | ||
|
||
func execute(for intent: IconIntent, colors: Colors) -> any ColorToken { | ||
switch intent { | ||
case .alert : | ||
return colors.feedback.alert | ||
case .error: | ||
return colors.feedback.error | ||
case .neutral: | ||
return colors.feedback.neutral | ||
case .primary: | ||
return colors.primary.primary | ||
case .secondary: | ||
return colors.secondary.secondary | ||
case .success: | ||
return colors.feedback.success | ||
} | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
core/Sources/Components/Icon/UseCase/IconGetColorUseCaseTests.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,70 @@ | ||
// | ||
// IconGetColorUseCaseTests.swift | ||
// Spark | ||
// | ||
// Created by Jacklyn Situmorang on 10.07.23. | ||
// Copyright © 2023 Adevinta. All rights reserved. | ||
// | ||
|
||
import SwiftUI | ||
import XCTest | ||
|
||
@testable import SparkCore | ||
|
||
final class IconGetColorUseCaseTests: XCTestCase { | ||
|
||
// MARK: - Properties | ||
|
||
private let colorsMock = ColorsGeneratedMock.mocked() | ||
|
||
// MARK: - Tests | ||
|
||
func test_execute_when_icon_is_alert_case() { | ||
testExecute(givenIntent: .alert, expectedColorToken: self.colorsMock.feedback.alert) | ||
} | ||
|
||
func test_execute_when_icon_is_error_case() { | ||
testExecute(givenIntent: .error, expectedColorToken: self.colorsMock.feedback.error) | ||
} | ||
|
||
func test_execute_when_icon_is_neutral_case() { | ||
testExecute(givenIntent: .neutral, expectedColorToken: self.colorsMock.feedback.neutral) | ||
} | ||
|
||
func test_execute_when_icon_is_primary_case() { | ||
testExecute(givenIntent: .primary, expectedColorToken: self.colorsMock.primary.primary) | ||
} | ||
|
||
func test_execute_when_icon_is_secondary_case() { | ||
testExecute(givenIntent: .secondary, expectedColorToken: self.colorsMock.secondary.secondary) | ||
} | ||
|
||
func test_execute_when_icon_is_success_case() { | ||
testExecute(givenIntent: .success, expectedColorToken: self.colorsMock.feedback.success) | ||
} | ||
} | ||
|
||
// MARK: - Extension | ||
|
||
private extension IconGetColorUseCaseTests { | ||
func testExecute( | ||
givenIntent: IconIntent, | ||
expectedColorToken: any ColorToken | ||
) { | ||
// GIVEN | ||
let useCase = IconGetColorUseCase() | ||
|
||
// WHEN | ||
let colorToken = useCase.execute( | ||
for: givenIntent, | ||
colors: colorsMock | ||
) | ||
|
||
// THEN | ||
XCTAssertIdentical( | ||
colorToken as? ColorTokenGeneratedMock, | ||
expectedColorToken as? ColorTokenGeneratedMock, | ||
"Wrong color for .\(givenIntent) case" | ||
) | ||
} | ||
} |
64 changes: 64 additions & 0 deletions
64
core/Sources/Components/Icon/View/Model/IconViewModel.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,64 @@ | ||
// | ||
// IconViewModel.swift | ||
// SparkCore | ||
// | ||
// Created by Jacklyn Situmorang on 11.07.23. | ||
// Copyright © 2023 Adevinta. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
final class IconViewModel: ObservableObject { | ||
|
||
// MARK: - Properties | ||
|
||
private(set) var theme: Theme | ||
private(set) var intent: IconIntent | ||
private let getColorUseCase: IconGetColorUseCaseable | ||
|
||
// MARK: - Published properties | ||
|
||
@Published var color: any ColorToken | ||
@Published var size: IconSize | ||
|
||
// MARK: - Initializers | ||
|
||
init( | ||
theme: Theme, | ||
intent: IconIntent, | ||
size: IconSize, | ||
getColorUseCase: IconGetColorUseCaseable = IconGetColorUseCase() | ||
) { | ||
self.theme = theme | ||
self.intent = intent | ||
self.size = size | ||
self.getColorUseCase = getColorUseCase | ||
self.color = getColorUseCase.execute(for: intent, colors: theme.colors) | ||
} | ||
|
||
// MARK: - Setters | ||
|
||
func set(theme: Theme) { | ||
self.theme = theme | ||
self.updateColor() | ||
} | ||
|
||
func set(intent: IconIntent) { | ||
if self.intent != intent { | ||
self.intent = intent | ||
self.updateColor() | ||
} | ||
} | ||
|
||
func set(size: IconSize) { | ||
if self.size != size { | ||
self.size = size | ||
} | ||
} | ||
|
||
// MARK: - Private funcs | ||
|
||
private func updateColor() { | ||
self.color = self.getColorUseCase.execute(for: self.intent, colors: self.theme.colors) | ||
} | ||
} |
Oops, something went wrong.