Skip to content

Commit

Permalink
feat(Button): Added accesibility to right image (chevron)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanegon authored Sep 25, 2023
1 parent ca9008c commit 05d77d9
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ class UICatalogButtonsViewController: UITableViewController {
Style(buttonStyle: .secondary, title: "Secondary S", isInverse: false, isSmall: true),
Style(buttonStyle: .danger, title: "Danger S", isInverse: false, isSmall: true),
Style(buttonStyle: .primaryInverse, title: "Primary Inverse S", isInverse: true, isSmall: true),
Style(buttonStyle: .secondaryInverse, title: "Secondary Inverse S", isInverse: true, isSmall: true)
Style(buttonStyle: .secondaryInverse, title: "Secondary Inverse S", isInverse: true, isSmall: true),

// Chevron

Style(buttonStyle: .link, title: "Chevron", isInverse: false, isSmall: false, rightImage: .chevron)
]
}

Expand All @@ -52,10 +56,7 @@ class UICatalogButtonsViewController: UITableViewController {
Button(style: .primary, title: "OK"),
Button(style: .primary, title: "OK", isSmall: true),
Button(style: .link, title: "OK")
], .right),
("Chevron", [
Button(style: .link, title: "Button Link", rightImage: .chevron)
], .center)
], .right)
]
}

Expand All @@ -64,6 +65,19 @@ class UICatalogButtonsViewController: UITableViewController {
let title: String
let isInverse: Bool
let isSmall: Bool
let rightImage: Button.RightImage?

init(buttonStyle: Button.Style,
title: String,
isInverse: Bool,
isSmall: Bool,
rightImage: Button.RightImage? = nil) {
self.buttonStyle = buttonStyle
self.title = title
self.isInverse = isInverse
self.isSmall = isSmall
self.rightImage = rightImage
}
}

init() {
Expand Down Expand Up @@ -112,7 +126,7 @@ class UICatalogButtonsViewController: UITableViewController {

let cell = UITableViewCell()

let button = state.makeButton(style: style.buttonStyle, title: "Title", loadingTitle: "Loading Title", isSmall: style.isSmall)
let button = state.makeButton(style: style.buttonStyle, title: "Title", loadingTitle: "Loading Title", isSmall: style.isSmall, rightImage: style.rightImage)
cell.configure(with: button)
cell.contentView.backgroundColor = style.isInverse ? .navigationBarBackground : .backgroundContainer

Expand Down Expand Up @@ -175,23 +189,23 @@ private class LoadSimulationButton: Button {
}

private extension Button.State {
func makeButton(style: Button.Style, title _: String, loadingTitle _: String, isSmall: Bool) -> Button {
func makeButton(style: Button.Style, title _: String, loadingTitle _: String, isSmall: Bool, rightImage: Button.RightImage?) -> Button {
let button: Button

switch self {
case .selected:
button = Button(style: style, title: "Title", loadingTitle: "Loading Title", isSmall: isSmall)
button = Button(style: style, title: "Title", rightImage: rightImage, loadingTitle: "Loading Title", isSmall: isSmall)
button.title = "Selected"
button.isSelected = true
button.isUserInteractionEnabled = false
case .disabled:
button = Button(style: style, title: "Title", loadingTitle: "Loading Title", isSmall: isSmall)
button = Button(style: style, title: "Title", rightImage: rightImage, loadingTitle: "Loading Title", isSmall: isSmall)
button.title = "Disabled"
button.isEnabled = false
case .loading:
button = LoadSimulationButton(style: style, title: "Loading", loadingTitle: "Loading Title", isSmall: isSmall)
button = LoadSimulationButton(style: style, title: "Loading", rightImage: rightImage, loadingTitle: "Loading Title", isSmall: isSmall)
case .normal:
button = Button(style: style, title: "Title", loadingTitle: "Loading Title", isSmall: isSmall)
button = Button(style: style, title: "Title", rightImage: rightImage, loadingTitle: "Loading Title", isSmall: isSmall)
button.title = "Normal"
default:
fatalError("Unknown state")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ struct ButtonsCatalogView: View {
Style(buttonStyle: .misticaSecondaryInverse(small: true), title: "Secondary Inverse Small", inverse: true),
Style(buttonStyle: .misticaLink(small: true), title: "Link Small", inverse: false),
Style(buttonStyle: .misticaLinkInverse(small: true), title: "Link Inverse Small", inverse: true),
Style(buttonStyle: .misticaLink(withChevron: true), title: "Link Chevron", inverse: false)
Style(buttonStyle: .misticaLink(withChevron: true), title: "Link Chevron", inverse: false),
Style(buttonStyle: .misticaLinkInverse(withChevron: true), title: "Link Chevron Inverse", inverse: true)
]
}
}
Expand Down
2 changes: 2 additions & 0 deletions Sources/Mistica/Components/Button/ButtonContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class ButtonContentView: UIView {

private let rightImageView: UIImageView = {
let imageView = UIImageView()
imageView.adjustsImageSizeForAccessibilityContentSizeCategory = true
imageView.contentMode = .scaleAspectFit
imageView.isHidden = true
return imageView
Expand Down Expand Up @@ -138,6 +139,7 @@ class ButtonContentView: UIView {
addSubview(constrainedToLayoutMarginsGuideOf: loadingStackView)

rightImageHeightConstraint.isActive = true
rightImageHeightConstraint.priority = .defaultLow
}

override var intrinsicContentSize: CGSize {
Expand Down
58 changes: 46 additions & 12 deletions Sources/MisticaSwiftUI/Components/Button/MisticaButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ enum MisticaButtonRightImage {

var image: some View {
switch self {
case .chevron: return Image.chevron
case let .custom(image): return image
case .chevron: return
Image.chevron
.resizable()
.scaledToFit()
.frame(idealWidth: 8, idealHeight: 20)
.eraseToAnyView()
case let .custom(image):
return image
.eraseToAnyView()
}
}

Expand Down Expand Up @@ -89,6 +96,43 @@ struct MisticaButton: View {
@Environment(\.isEnabled) private var isEnabled

public var body: some View {
if #available(iOS 14, *) {
ScaledMisticaButton(
height: height,
small: small,
minWidth: minWidth,
verticalPadding: verticalPadding,
horizontalPadding: horizontalPadding,
backgroundColor: backgroundColor,
foregroundColor: foregroundColor,
borderColor: borderColor,
leadingInset: leadingInset,
trailingInset: trailingInset
) {
content
}
.allowsHitTesting(!loadingInfo.isLoading)
} else {
content
.frame(height: height)
.if(!small) { $0.expandHorizontally() }
.frame(minWidth: minWidth)
.padding(.vertical, verticalPadding)
.padding(.horizontal, Constants.horizontalPadding)
.background(backgroundColor)
.foregroundColor(foregroundColor)
.border(radiusStyle: .button, borderColor: borderColor)
.padding(EdgeInsets(top: 0, leading: leadingInset, bottom: 0, trailing: trailingInset))
.allowsHitTesting(!loadingInfo.isLoading)
.accessibilityElement()
}
}
}

// MARK: Private extension

private extension MisticaButton {
@ViewBuilder private var content: some View {
ZStack {
loadingView
.offset(x: 0, y: loadingInfo.isLoading ? 0 : Constants.transitionOffset)
Expand All @@ -110,16 +154,6 @@ struct MisticaButton: View {
.animation(.misticaTimingCurve, value: loadingInfo.isLoading)
.misticaBackport.accesibilityHidden(loadingInfo.isLoading)
}
.frame(height: height)
.if(!small) { $0.expandHorizontally() }
.frame(minWidth: minWidth)
.padding(.vertical, verticalPadding)
.padding(.horizontal, Constants.horizontalPadding)
.background(backgroundColor)
.foregroundColor(foregroundColor)
.border(radiusStyle: .button, borderColor: borderColor)
.padding(EdgeInsets(top: 0, leading: leadingInset, bottom: 0, trailing: trailingInset))
.allowsHitTesting(!loadingInfo.isLoading)
}

@ViewBuilder private var loadingView: some View {
Expand Down
65 changes: 65 additions & 0 deletions Sources/MisticaSwiftUI/Components/Button/ScaledMisticaButton.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// ScaledMisticaButton.swift
//
// Made with ❤️ by Novum
//
// Copyright © Telefonica. All rights reserved.
//

import SwiftUI

@available(iOS 14.0, *)
struct ScaledMisticaButton<Content: View>: View {
let content: () -> Content
let height: CGFloat
let small: Bool
let minWidth: CGFloat
let verticalPadding: CGFloat
let horizontalPadding: CGFloat
let backgroundColor: Color
let foregroundColor: Color
let borderColor: Color
let leadingInset: CGFloat
let trailingInset: CGFloat

@ScaledMetric var scale: CGFloat = 1

init(
height: CGFloat,
small: Bool,
minWidth: CGFloat,
verticalPadding: CGFloat,
horizontalPadding: CGFloat,
backgroundColor: Color,
foregroundColor: Color,
borderColor: Color,
leadingInset: CGFloat,
trailingInset: CGFloat,
@ViewBuilder content: @escaping () -> Content
) {
self.height = height
self.small = small
self.minWidth = minWidth
self.content = content
self.verticalPadding = verticalPadding
self.horizontalPadding = horizontalPadding
self.backgroundColor = backgroundColor
self.foregroundColor = foregroundColor
self.borderColor = borderColor
self.leadingInset = leadingInset
self.trailingInset = trailingInset
}

var body: some View {
content()
.frame(height: height * scale)
.if(!small) { $0.expandHorizontally() }
.frame(minWidth: minWidth * scale)
.padding(.vertical, verticalPadding)
.padding(.horizontal, horizontalPadding)
.background(backgroundColor)
.foregroundColor(foregroundColor)
.border(radiusStyle: .button, borderColor: borderColor)
.padding(EdgeInsets(top: 0, leading: leadingInset, bottom: 0, trailing: trailingInset))
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 05d77d9

Please sign in to comment.