Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prerelease 0 16 1 #994

Merged
merged 36 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
e1d6dc6
[Accessibility] Updated progress bar accessibility
LouisBorleeAdevinta Apr 8, 2024
9221431
[Checkbox#866] Fix extanding content issue in stack for single checkbox
aycil-alican Mar 25, 2024
f629dac
[Checkboxr#876] Fix single checkbox accesibility
aycil-alican Apr 4, 2024
7ab7fcb
[Checkboxr#876] Fix checkbox group accesibility
aycil-alican Apr 4, 2024
fcc3df9
[Checkboxr#876] Add accessibilityLabel for checkbox group on demo pro…
aycil-alican Apr 4, 2024
bb7fb7c
[Checkboxr#876] Fix texts
aycil-alican Apr 5, 2024
b0aafaf
[Checkboxr#876] Fix accessibilty traits as a button
aycil-alican Apr 5, 2024
986e898
[Checkbox#876] remove unnecessary command lines
aycil-alican Apr 5, 2024
7e0ff66
[Checkbox#876] fix pr comments
aycil-alican Apr 8, 2024
49a4783
[Checkbox#876] Fix typo issues
aycil-alican Apr 12, 2024
24b75fc
[CheckboxGroup#864] Add isDisabled parameter to uikit checkbox group
aycil-alican Mar 25, 2024
5cd4a60
[CheckboxGroup#864] Fix partially disable issue on swiftui checkbox g…
aycil-alican Mar 25, 2024
c5ff815
[Checkbox#876] Fix wrong accessibility value
aycil-alican Apr 29, 2024
79016e3
[CheckboxGroup#939] Fix layout update issue after change alignment
aycil-alican May 15, 2024
f902bc2
[Chip#950] Remove if modifier.
michael-zimmermann May 24, 2024
178d802
[ProgressBar#951] Remove if modifier.
michael-zimmermann May 24, 2024
53772af
[RadioButton#968] Fix color.
michael-zimmermann May 29, 2024
6fe8982
[CheckBox#949] Remove if view modifier.
michael-zimmermann May 27, 2024
7d83efa
[Switch#950] Remove if modifier.
michael-zimmermann May 24, 2024
d4e1e35
[Tag#1939] Use default text font of tag if not overwritten by attribu…
michael-zimmermann May 29, 2024
80465f5
[TextFieldAddons#980] Fix SwiftUI layering issue
LouisBorleeAdevinta May 30, 2024
d7c5f3e
[Accessibility] Make Rating Input (UIKit) adjustable to enable the ra…
xavier-daleau Feb 5, 2024
45bdeea
[Accessibility] Turn UIKit Tab into an accessibility container
xavier-daleau Jan 22, 2024
ea24309
[Tab] Fix merge conflicts.
michael-zimmermann May 30, 2024
375a9d4
[Tab] Accessibility. Fix unit tests.
michael-zimmermann May 31, 2024
913f947
[Formfield#987] Removed component isAccessibility setting
LouisBorleeAdevinta Jun 4, 2024
3c72a33
[Accessibility] Add link accessibility trait to the text link (uikit …
xavier-daleau Feb 5, 2024
4e552d2
[TextLink] set isAccesibilityElement to true.
michael-zimmermann May 31, 2024
1c346f4
[TextLink] update accessibility attributes.
michael-zimmermann May 31, 2024
819f73d
[TextLink] Accessibility. Revert to previous logic setting text.
michael-zimmermann May 31, 2024
4720751
[TextLink] Add accessibility trait Image to swiftui component.
michael-zimmermann May 31, 2024
22c0e91
[Chip#990] Add touchesCancelled to chip.
michael-zimmermann Jun 7, 2024
dde2a7f
[Chip#990] Update colors when dark/light mode change.
michael-zimmermann Jun 7, 2024
92dad13
[Tab#509] Fix flickering in demo and warning 'Modifying state during …
michael-zimmermann Jun 6, 2024
ecc010b
Fix merge conflicts.
michael-zimmermann Jun 7, 2024
c1650fe
Added deprecated label to 'if' modifier.
michael-zimmermann Jun 7, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import SwiftUI

extension View {
@available(*, deprecated, message: "Will be removed soon")
func `if`<Content: View>(_ conditional: Bool, content: (Self) -> Content) -> some View {
if conditional {
return AnyView(content(self))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,20 @@ import Foundation

/// The accessibility identifiers for the checkbox.
public enum CheckboxAccessibilityIdentifier {
/// The default accessibility identifier. Can be changed by the consumer
/// The default checkbox accessibility identifier.
public static let checkbox = "spark-check-box"
/// The default accessibility identifier. Can be changed by the consumer
/// The default checkbox group accessibility identifier.
public static let checkboxGroup = "spark-check-box-group"
/// The identifier of checkbox group ui view title
public static let checkboxGroupTitle = "spark-check-box-group-title"
/// The default checkbox group item accessibility identifier.
public static func checkboxGroupItem(_ id: String) -> String {
Self.checkbox + "-\(id)"
}
}

public enum CheckboxAccessibilityValue {
public static let checked = "1"
public static let indeterminate = "0.5"
public static let unchecked = "0"
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ final class CheckboxGroupViewModel: ObservableObject {
@Published var checkedImage: Image
@Published var layout: CheckboxGroupLayout
@Published var spacing: LayoutSpacing
@Published var accessibilityIdentifierPrefix: String
@Published var titleFont: TypographyFontToken
@Published var titleColor: any ColorToken
@Published var intent: CheckboxIntent
Expand All @@ -28,7 +27,6 @@ final class CheckboxGroupViewModel: ObservableObject {
init(
title: String?,
checkedImage: Image,
accessibilityIdentifierPrefix: String,
theme: Theme,
intent: CheckboxIntent = .main,
alignment: CheckboxAlignment = .left,
Expand All @@ -43,7 +41,6 @@ final class CheckboxGroupViewModel: ObservableObject {
self.spacing = theme.layout.spacing
self.titleFont = theme.typography.subhead
self.titleColor = theme.colors.base.onSurface
self.accessibilityIdentifierPrefix = accessibilityIdentifierPrefix
}

func calculateSingleCheckboxWidth(string: String?) -> CGFloat {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ final class CheckboxGroupViewModelTests: XCTestCase {
self.sut = CheckboxGroupViewModel(
title: "Title",
checkedImage: Image(uiImage: self.checkedImage),
accessibilityIdentifierPrefix: "id",
theme: self.theme
)
}
Expand All @@ -45,7 +44,6 @@ final class CheckboxGroupViewModelTests: XCTestCase {
XCTAssertEqual(sut.intent, .main, "Intent does not match")
XCTAssertEqual(sut.titleFont.uiFont, self.theme.typography.subhead.uiFont, "Title font does not match" )
XCTAssertEqual(sut.titleColor.uiColor, self.theme.colors.base.onSurface.uiColor, "Title color does not match" )
XCTAssertEqual(sut.accessibilityIdentifierPrefix, "id", "Accessibility identifier does not match" )
}

func test_singleCheckbox_width() throws {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public struct CheckboxGroupView: View {
/// - checkboxAlignment: The checkbox is positioned on the leading or trailing edge of the view.
/// - theme: The Spark-Theme.
/// - accessibilityIdentifierPrefix: All checkbox-views are prefixed by this identifier followed by the `CheckboxGroupItemProtocol`-identifier.
@available(*, deprecated, message: "Please use init without accessibilityIdentifierPrefix. It was given as a static string.")
public init(
title: String? = nil,
checkedImage: Image,
Expand All @@ -47,11 +48,38 @@ public struct CheckboxGroupView: View {
theme: Theme,
intent: CheckboxIntent = .main,
accessibilityIdentifierPrefix: String
) {
self.init(
title: title,
checkedImage: checkedImage,
items: items,
layout: layout,
alignment: alignment,
theme: theme,
intent: intent
)
}

/// Initialize a group of one or multiple checkboxes.
/// - Parameters:
/// - title: An optional group title displayed on top of the checkbox group..
/// - checkedImage: The tick-checkbox image for checked-state.
/// - items: An array containing of multiple `CheckboxGroupItemProtocol`. Each array item is used to render a single checkbox.
/// - layout: The layout of the group can be horizontal or vertical.
/// - checkboxAlignment: The checkbox is positioned on the leading or trailing edge of the view.
/// - theme: The Spark-Theme.
public init(
title: String? = nil,
checkedImage: Image,
items: Binding<[any CheckboxGroupItemProtocol]>,
layout: CheckboxGroupLayout = .vertical,
alignment: CheckboxAlignment,
theme: Theme,
intent: CheckboxIntent = .main
) {
let viewModel = CheckboxGroupViewModel(
title: title,
checkedImage: checkedImage,
accessibilityIdentifierPrefix: accessibilityIdentifierPrefix,
theme: theme,
intent: intent,
alignment: alignment,
Expand Down Expand Up @@ -94,10 +122,21 @@ public struct CheckboxGroupView: View {
.onChange(of: self.itemContents) { newValue in
self.isScrollableHStack = true
}
.accessibilityIdentifier("\(self.viewModel.accessibilityIdentifierPrefix).\(CheckboxAccessibilityIdentifier.checkboxGroup)")
.accessibilityElement(children: .contain)
.accessibilityIdentifier(CheckboxAccessibilityIdentifier.checkboxGroup)
}

@ViewBuilder
private func makeHStackView() -> some View {
if self.isScrollableHStack {
self.makeScrollHStackView()
} else {
self.makeDefaultHStackView()
}
}

@ViewBuilder
private func makeScrollHStackView() -> some View {
ScrollView (.horizontal, showsIndicators: false) {
HStack(alignment: .top, spacing: self.spacingLarge) {
self.makeContentView(maxWidth: self.viewWidth)
Expand All @@ -114,11 +153,6 @@ public struct CheckboxGroupView: View {
.padding(checkboxSelectedBorderWidth)
}
.padding(-checkboxSelectedBorderWidth)
.if(!self.isScrollableHStack) { _ in
makeDefaultHStackView()
} else: { view in
view
}
}

@ViewBuilder
Expand Down Expand Up @@ -156,7 +190,6 @@ public struct CheckboxGroupView: View {
}

private func checkBoxView(item: Binding<any CheckboxGroupItemProtocol>) -> some View {
let identifier = "\(self.viewModel.accessibilityIdentifierPrefix).\(item.id.wrappedValue)"
return CheckboxView(
text: item.title.wrappedValue,
checkedImage: self.viewModel.checkedImage,
Expand All @@ -166,7 +199,8 @@ public struct CheckboxGroupView: View {
isEnabled: item.isEnabled.wrappedValue,
selectionState: item.selectionState
)
.accessibilityIdentifier(identifier)
.disabled(!item.isEnabled.wrappedValue)
.accessibilityIdentifier(CheckboxAccessibilityIdentifier.checkboxGroupItem(item.id.wrappedValue))
}
}

Expand Down
79 changes: 58 additions & 21 deletions core/Sources/Components/Checkbox/View/SwiftUI/CheckboxView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,33 +104,41 @@ public struct CheckboxView: View {
}
)
.buttonStyle(PressedButtonStyle(isPressed: self.$isPressed))
.accessibilityIdentifier(CheckboxAccessibilityIdentifier.checkbox)
.isEnabledChanged { isEnabled in
self.viewModel.isEnabled = isEnabled
}
.fixedSize(horizontal: false, vertical: true)
.accessibilityIdentifier(CheckboxAccessibilityIdentifier.checkbox)
.accessibilityValue(setAccessibilityValue(selectionState: self.viewModel.selectionState))
.accessibilityRemoveTraits(.isSelected)
}

private func setAccessibilityValue(selectionState: CheckboxSelectionState) -> String {
switch selectionState {
case .selected:
return CheckboxAccessibilityValue.checked
case .indeterminate:
return CheckboxAccessibilityValue.indeterminate
case .unselected:
return CheckboxAccessibilityValue.unchecked
}
}

@ViewBuilder
private var checkboxView: some View {
let tintColor = self.viewModel.colors.tintColor.color
if self.selectionState == .selected {
self.checkbox().accessibilityAddTraits(.isSelected)
} else {
self.checkbox()
}
}

@ViewBuilder
private func checkbox() -> some View {
let iconColor = self.viewModel.colors.iconColor.color
let borderColor = self.viewModel.colors.borderColor.color

ZStack {
RoundedRectangle(cornerRadius: self.checkboxBorderRadius)
.if(self.selectionState == .selected || self.selectionState == .indeterminate) {
$0.fill(tintColor)
} else: {
$0.strokeBorder(borderColor, lineWidth: self.checkboxBorderWidth)
}
.frame(width: self.checkboxSize, height: self.checkboxSize)
.if(self.isPressed && self.viewModel.isEnabled) {
$0.overlay(
RoundedRectangle(cornerRadius: self.checkboxBorderRadius)
.inset(by: -self.checkboxSelectedBorderWidth / 2)
.stroke(self.viewModel.colors.pressedBorderColor.color, lineWidth: self.checkboxSelectedBorderWidth)
.animation(.easeInOut(duration: 0.1), value: self.isPressed)
)
}
self.stateFullCheckboxRectangle()

switch self.selectionState {
case .selected:
Expand All @@ -148,13 +156,42 @@ public struct CheckboxView: View {
.frame(width: self.checkboxIndeterminateWidth, height: self.checkboxIndeterminateHeight)
}
}
.if(self.selectionState == .selected) {
$0.accessibilityAddTraits(.isSelected)
}
.id(Identifier.checkbox.rawValue)
.matchedGeometryEffect(id: Identifier.checkbox.rawValue, in: self.namespace)
}

@ViewBuilder
private func stateFullCheckboxRectangle() -> some View {
if self.isPressed && self.viewModel.isEnabled {
self.checkboxRectangle()
.overlay(
RoundedRectangle(cornerRadius: self.checkboxBorderRadius)
.inset(by: -self.checkboxSelectedBorderWidth / 2)
.stroke(self.viewModel.colors.pressedBorderColor.color, lineWidth: self.checkboxSelectedBorderWidth)
.animation(.easeInOut(duration: 0.1), value: self.isPressed)
)
} else {
self.checkboxRectangle()
}
}

@ViewBuilder
private func checkboxRectangle() -> some View {
let tintColor = self.viewModel.colors.tintColor.color
let borderColor = self.viewModel.colors.borderColor.color

if self.selectionState == .selected || self.selectionState == .indeterminate {
RoundedRectangle(cornerRadius: self.checkboxBorderRadius)
.fill(tintColor)
.frame(width: self.checkboxSize, height: self.checkboxSize)

} else {
RoundedRectangle(cornerRadius: self.checkboxBorderRadius)
.strokeBorder(borderColor, lineWidth: self.checkboxBorderWidth)
.frame(width: self.checkboxSize, height: self.checkboxSize)
}
}

@ViewBuilder
private var contentView: some View {
HStack(spacing: 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ final class CheckboxViewSnapshotTests: SwiftUIComponentSnapshotTestCase {
for configuration in configurations {
self.selectionState = configuration.selectionState

let view = CheckboxView(
let checkboxView = CheckboxView(
text: configuration.text,
checkedImage: Image(uiImage: configuration.image),
alignment: configuration.alignment,
Expand All @@ -48,14 +48,8 @@ final class CheckboxViewSnapshotTests: SwiftUIComponentSnapshotTestCase {
selectionState: self._selectionState
)
.background(Color.systemBackground)
.if(configuration.text != "Hello World") { view in
VStack {
view
}
.frame(width: UIScreen.main.bounds.width)
} else: { view in
view.fixedSize()
}

let view = self.view(text: configuration.text, checkbox: checkboxView)

self.assertSnapshot(
matching: view,
Expand All @@ -66,4 +60,15 @@ final class CheckboxViewSnapshotTests: SwiftUIComponentSnapshotTestCase {
}
}
}

func view(text: String, checkbox: some View) -> AnyView {
if text != "Hello World" {
let view = VStack { checkbox }
.frame(width: UIScreen.main.bounds.width)
return AnyView(view)
} else {
return AnyView(checkbox.fixedSize())
}

}
}
Loading
Loading