diff --git a/BrowserKit/Sources/ComponentLibrary/Buttons/LinkButton.swift b/BrowserKit/Sources/ComponentLibrary/Buttons/LinkButton.swift new file mode 100644 index 000000000000..8841ec58147e --- /dev/null +++ b/BrowserKit/Sources/ComponentLibrary/Buttons/LinkButton.swift @@ -0,0 +1,44 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Common +import UIKit + +public class LinkButton: ResizableButton, ThemeApplicable { + private struct UX { + static let buttonCornerRadius: CGFloat = 13 + static let buttonVerticalInset: CGFloat = 12 + static let buttonHorizontalInset: CGFloat = 16 + } + + override init(frame: CGRect) { + super.init(frame: frame) + + backgroundColor = .clear + titleLabel?.adjustsFontForContentSizeCategory = true + contentEdgeInsets = UIEdgeInsets(top: UX.buttonVerticalInset, + left: UX.buttonHorizontalInset, + bottom: UX.buttonVerticalInset, + right: UX.buttonHorizontalInset) + } + + public func configure(viewModel: LinkButtonViewModel) { + accessibilityIdentifier = viewModel.a11yIdentifier + setTitle(viewModel.title, for: .normal) + titleLabel?.font = DefaultDynamicFontHelper.preferredFont(withTextStyle: .body, + size: viewModel.fontSize) + titleLabel?.textAlignment = viewModel.textAlignment + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: ThemeApplicable + + public func applyTheme(theme: Theme) { + setTitleColor(theme.colors.textAccent, for: .normal) + setTitleColor(theme.colors.actionPrimaryHover, for: .highlighted) + } +} diff --git a/BrowserKit/Sources/ComponentLibrary/Buttons/LinkButtonViewModel.swift b/BrowserKit/Sources/ComponentLibrary/Buttons/LinkButtonViewModel.swift new file mode 100644 index 000000000000..21cf25e5020a --- /dev/null +++ b/BrowserKit/Sources/ComponentLibrary/Buttons/LinkButtonViewModel.swift @@ -0,0 +1,24 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import UIKit +import Foundation + +/// The view model used to configure a `LinkButton` +public struct LinkButtonViewModel { + public let title: String + public let a11yIdentifier: String + public let fontSize: CGFloat + public let textAlignment: NSTextAlignment + + public init(title: String, + a11yIdentifier: String, + fontSize: CGFloat = 16, + textAlignment: NSTextAlignment = .left) { + self.title = title + self.a11yIdentifier = a11yIdentifier + self.fontSize = fontSize + self.textAlignment = textAlignment + } +} diff --git a/BrowserKit/Sources/ComponentLibrary/Documentation.docc/General Components/LinkButton.md b/BrowserKit/Sources/ComponentLibrary/Documentation.docc/General Components/LinkButton.md new file mode 100644 index 000000000000..fc4fba174d62 --- /dev/null +++ b/BrowserKit/Sources/ComponentLibrary/Documentation.docc/General Components/LinkButton.md @@ -0,0 +1,19 @@ +# ``ComponentLibrary/LinkButton`` + +The button which is used for actions that looks like a webview link. + +## Overview + +The `LinkButton` is a subclass of the `UIButton`. This means properties of the `UIButton` are accessible, but for easy conveniance it's recommended to configure the button title, font and accessibility identifier through it's' view model ``LinkButtonViewModel``. The colors and spacing of the button although accessible shouldn't be adjusted and should be used as is. + +## Illustration + +> This image is illustrative only. For precise examples of iOS implementation, please run the SampleApplication. + +![The LinkButton on iOS]LinkButton + +## Topics + +### View Model + +- ``LinkButtonViewModel`` diff --git a/BrowserKit/Sources/ComponentLibrary/Documentation.docc/Resources/LinkButton.png b/BrowserKit/Sources/ComponentLibrary/Documentation.docc/Resources/LinkButton.png new file mode 100644 index 000000000000..6d0c89540682 Binary files /dev/null and b/BrowserKit/Sources/ComponentLibrary/Documentation.docc/Resources/LinkButton.png differ diff --git a/BrowserKit/Sources/ComponentLibrary/Documentation.docc/Resources/LinkButton~dark.png b/BrowserKit/Sources/ComponentLibrary/Documentation.docc/Resources/LinkButton~dark.png new file mode 100644 index 000000000000..08b35a732c67 Binary files /dev/null and b/BrowserKit/Sources/ComponentLibrary/Documentation.docc/Resources/LinkButton~dark.png differ diff --git a/SampleComponentLibraryApp/SampleComponentLibraryApp/Buttons/ButtonsViewController.swift b/SampleComponentLibraryApp/SampleComponentLibraryApp/Buttons/ButtonsViewController.swift index 420cdbd7a56e..e5c970101d19 100644 --- a/SampleComponentLibraryApp/SampleComponentLibraryApp/Buttons/ButtonsViewController.swift +++ b/SampleComponentLibraryApp/SampleComponentLibraryApp/Buttons/ButtonsViewController.swift @@ -14,6 +14,7 @@ class ButtonsViewController: UIViewController, Themeable { private lazy var primaryButton: PrimaryRoundedButton = .build { _ in } private lazy var secondaryButton: SecondaryRoundedButton = .build { _ in } + private lazy var linkButton: LinkButton = .build { _ in } private lazy var buttonStackView: UIStackView = .build { stackView in stackView.distribution = .fillEqually @@ -46,14 +47,20 @@ class ButtonsViewController: UIViewController, Themeable { a11yIdentifier: "a11ySecondary") secondaryButton.configure(viewModel: secondaryViewModel) + let linkButtonViewModel = LinkButtonViewModel(title: "This is a link", + a11yIdentifier: "a11yLink") + linkButton.configure(viewModel: linkButtonViewModel) + primaryButton.applyTheme(theme: themeManager.currentTheme) secondaryButton.applyTheme(theme: themeManager.currentTheme) + linkButton.applyTheme(theme: themeManager.currentTheme) } private func setupView() { view.addSubview(buttonStackView) buttonStackView.addArrangedSubview(primaryButton) buttonStackView.addArrangedSubview(secondaryButton) + buttonStackView.addArrangedSubview(linkButton) NSLayoutConstraint.activate([ buttonStackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),