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

[CheckboxGroup#864] Fix disable checkbox group issue #867

Merged
merged 12 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from 11 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
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ public struct CheckboxGroupView: View {
isEnabled: item.isEnabled.wrappedValue,
selectionState: item.selectionState
)
.disabled(!item.isEnabled.wrappedValue)
.accessibilityIdentifier(identifier)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,20 @@ public final class CheckboxGroupUIView: UIControl {
self.itemsStackView.arrangedSubviews.compactMap { $0 as? CheckboxUIView }
}

/// A Boolean value indicating whether the component is in the enabled state.
public override var isEnabled: Bool {
didSet{
guard isEnabled != oldValue else { return }
if isEnabled {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure of the logic here. Why can't all the checkboxes be set to enabled as in the disabled states?
If someone enables the whole component, shouldn't it override the status of each single component?

self.checkboxes.forEach { $0.isEnabled == isEnabled }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ex; Checkbox group has 3 item and first item is disable then consumer wants to disable all and enable all in this case first item will be enable but it should be disable

self.checkboxes.enumerated().forEach { index, item in
item.isEnabled = self.items.indices.contains(index) ? self.items[index].isEnabled : true
}
} else {
self.checkboxes.forEach { $0.isEnabled = false }
}
}
}

// MARK: - Initialization

/// Not implemented. Please use another init.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import SwiftUI
private enum Constants {
static let pressedLineWidth: CGFloat = 4
static let lineWidth: CGFloat = 2
static let size: CGFloat = 20
static let filledSize: CGFloat = 10
static let size: CGFloat = 24
static let filledSize: CGFloat = 12
}
/// RadioButtonView is a single radio button control.
/// Radio buttons are used for selecting a single value from a selection of values.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ import UIKit

// MARK: - Constants
private enum Constants {
static let toggleViewHeight: CGFloat = 28
static let toggleViewSpacing: CGFloat = 4
static let textLabelTopSpacing: CGFloat = 3
static let toggleViewHeight: CGFloat = 32
static let textLabelTopSpacing: CGFloat = 5
static let haloWidth: CGFloat = 4
}

Expand Down
4 changes: 2 additions & 2 deletions core/Sources/Components/Slider/Constant/SliderConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import Foundation

enum SliderConstants {
static let handleSize = CGSize(width: 24, height: 24)
static let activeIndicatorSize = CGSize(width: 32, height: 32)
static let handleSize = CGSize(width: 32, height: 32)
static let activeIndicatorSize = CGSize(width: 40, height: 40)
static let barHeight: CGFloat = 4.0
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ final class CheckboxGroupComponentUIView: ComponentUIView {
self.componentView.title = showGroupTitle ? viewModel.title : ""
}

self.viewModel.$isEnabled.subscribe(in: &self.cancellables) { [weak self] isEnabled in
guard let self = self else { return }
self.componentView.isEnabled = isEnabled
}

self.viewModel.$groupType.subscribe(in: &self.cancellables) { [weak self] type in
guard let self = self else { return }
self.viewModel.groupTypeConfigurationItemViewModel.buttonTitle = type.name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ final class CheckboxGroupComponentUIViewModel: ComponentUIViewModel {
)
}()

lazy var isEnableConfigurationItemViewModel: ComponentsConfigurationItemUIViewModel = {
return .init(
name: "Is Enable",
type: .toggle(isOn: self.isEnabled),
target: (source: self, action: #selector(self.toggleIsEnable))
)
}()

lazy var iconConfigurationItemViewModel: ComponentsConfigurationItemUIViewModel = {
return .init(
name: "Icons",
Expand Down Expand Up @@ -142,6 +150,7 @@ final class CheckboxGroupComponentUIViewModel: ComponentUIViewModel {
@Published var isAlignmentLeft: Bool
@Published var isLayoutVertical: Bool
@Published var showGroupTitle: Bool
@Published var isEnabled: Bool
@Published var icon: [String: UIImage]
@Published var groupType: CheckboxGroupType

Expand All @@ -151,6 +160,7 @@ final class CheckboxGroupComponentUIViewModel: ComponentUIViewModel {
isAlignmentLeft: Bool = true,
isLayoutVertical: Bool = false,
showGroupTitle: Bool = false,
isEnabled: Bool = true,
icon: [String: UIImage] = ["Checkmark": DemoIconography.shared.checkmark.uiImage],
groupType: CheckboxGroupType = .doubleMix
) {
Expand All @@ -159,6 +169,7 @@ final class CheckboxGroupComponentUIViewModel: ComponentUIViewModel {
self.isAlignmentLeft = isAlignmentLeft
self.isLayoutVertical = isLayoutVertical
self.showGroupTitle = showGroupTitle
self.isEnabled = isEnabled
self.icon = icon
self.groupType = groupType
super.init(identifier: "Checkbox Group")
Expand All @@ -169,6 +180,7 @@ final class CheckboxGroupComponentUIViewModel: ComponentUIViewModel {
self.alignmentConfigurationItemViewModel,
self.layoutConfigurationItemViewModel,
self.titleConfigurationItemViewModel,
self.isEnableConfigurationItemViewModel,
self.iconConfigurationItemViewModel,
self.groupTypeConfigurationItemViewModel,
self.itemsSelectionStateConfigurationItemViewModel
Expand Down Expand Up @@ -199,6 +211,10 @@ extension CheckboxGroupComponentUIViewModel {
self.showGroupTitle.toggle()
}

@objc func toggleIsEnable() {
self.isEnabled.toggle()
}

@objc func presentIconSheet() {
self.showIconSheetSubject.send(icons)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//
// RadioCheckboxUIViewController.swift
// SparkDemo
//
// Created by alican.aycil on 22.03.24.
// Copyright © 2024 Adevinta. All rights reserved.
//

import UIKit
import SparkCore
import Combine

final class RadioCheckboxUIViewController: UIViewController {

private let theme = SparkThemePublisher.shared.theme
private var cancellables = Set<AnyCancellable>()

private lazy var alignment: CheckboxUIView = {
let view = CheckboxUIView(
theme: self.theme,
text: "Alignment: Click to change postion.",
checkedImage: DemoIconography.shared.checkmark.uiImage,
isEnabled: true,
selectionState: .selected,
alignment: .left
)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()

private lazy var lineView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.lightGray
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()

private lazy var checkboxGroup: CheckboxGroupUIView = {
var items = [
CheckboxGroupItemDefault(title: "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.", id: "1", selectionState: .selected, isEnabled: true),
CheckboxGroupItemDefault(title: "Hello World", id: "2", selectionState: .selected, isEnabled: true)
]
let view = CheckboxGroupUIView(
checkedImage: DemoIconography.shared.checkmark.uiImage,
items: items,
alignment: alignment.isSelected ? CheckboxAlignment.left : CheckboxAlignment.right,
theme: self.theme,
intent: .main,
accessibilityIdentifierPrefix: "Checkbox"
)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()

private lazy var radioButtonGroup: RadioButtonUIGroupView = {
var items = [
RadioButtonUIItem(id: 0, label: "Hello World"),
RadioButtonUIItem(id: 1, label: "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.")
]
let view = RadioButtonUIGroupView(
theme: self.theme,
intent: .main,
selectedID: 0,
items: items,
labelAlignment: alignment.isSelected ? RadioButtonLabelAlignment.trailing : RadioButtonLabelAlignment.leading,
groupLayout: .vertical
)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()

override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "Radio Checkbox UIKit"

self.setupView()
self.subscribe()
}

private func setupView() {
self.view.backgroundColor = UIColor.systemBackground

self.view.addSubview(alignment)
self.view.addSubview(lineView)
self.view.addSubview(checkboxGroup)
self.view.addSubview(radioButtonGroup)

NSLayoutConstraint.activate([

self.alignment.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 16),
self.alignment.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16),
self.alignment.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -16),

self.lineView.topAnchor.constraint(equalTo: self.alignment.bottomAnchor, constant: 32),
self.lineView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16),
self.lineView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -16),
self.lineView.heightAnchor.constraint(equalToConstant: 1),

self.checkboxGroup.topAnchor.constraint(equalTo: self.lineView.bottomAnchor, constant: 32),
self.checkboxGroup.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16),
self.checkboxGroup.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -16),

self.radioButtonGroup.topAnchor.constraint(equalTo: self.checkboxGroup.bottomAnchor, constant: 16),
self.radioButtonGroup.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16),
self.radioButtonGroup.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -16)
])
}

private func subscribe() {
self.alignment.publisher.subscribe(in: &self.cancellables) { [weak self] isSelected in
self?.radioButtonGroup.labelAlignment = isSelected == .selected ? RadioButtonLabelAlignment.trailing : RadioButtonLabelAlignment.leading
self?.checkboxGroup.alignment = isSelected == .selected ? CheckboxAlignment.left : CheckboxAlignment.right
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// RadioCheckboxView.swift
// SparkDemo
//
// Created by alican.aycil on 22.03.24.
// Copyright © 2024 Adevinta. All rights reserved.
//

import Spark
import SparkCore
import SwiftUI

struct RadioCheckboxView: View {

// MARK: - Properties
@State private var theme: Theme = SparkThemePublisher.shared.theme
@State private var alignment: CheckboxAlignment = .left
@State private var selectedIcon = CheckboxListView.Icons.checkedImage
@State private var selectedID: Int? = 0
@State private var items: [any CheckboxGroupItemProtocol] = [
CheckboxGroupItemDefault(title: "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.", id: "1", selectionState: .selected, isEnabled: true),
CheckboxGroupItemDefault(title: "Hello World", id: "2", selectionState: .selected, isEnabled: true)
]
@State private var radioGroupItems: [RadioButtonItem<Int>] = [
RadioButtonItem(id: 0, label: "Hello World"),
RadioButtonItem(id: 1, label: "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.")
]


// MARK: - View
var body: some View {
Component(
name: "Radio Checkbox SwiftUI",
configuration: {

EnumSelector(
title: "Alignment",
dialogTitle: "Select a Alignment",
values: CheckboxAlignment.allCases,
value: self.$alignment
)
},
integration: {
VStack(alignment: .leading) {
CheckboxGroupView(
checkedImage: self.selectedIcon.image,
items: self.$items,
layout: .vertical,
alignment: self.alignment,
theme: self.theme,
intent: .main,
accessibilityIdentifierPrefix: "checkbox-group"
)

RadioButtonGroupView(
theme: self.theme,
intent: .main,
selectedID: self.$selectedID,
items: self.radioGroupItems,
labelAlignment: self.alignment == .left ? .trailing : .leading,
groupLayout: .vertical
)
}
}
)
}
}
Loading
Loading