Skip to content

Commit

Permalink
[CAT-202] SelectButton, SelectListButton (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
devMinseok authored Aug 12, 2024
1 parent 44ce8ef commit 6560bbd
Show file tree
Hide file tree
Showing 11 changed files with 361 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,67 @@ struct ButtonDetailView: View {
.buttonStyle(.round(level: .secondary))
}
}

VStack(spacing: 40) {
Text("Select")
.font(.title)
HStack {
Button(
title: "Title",
subtitle: "subTitle",
leftIcon: Image(systemName: "left"),
rightIcon: Image(systemName: "right"),
action: {
/*action*/
}
)
.buttonStyle(.select(isSelected: true))
Button(
title: "Title",
subtitle: "subTitle",
leftIcon: Image(systemName: "left"),
rightIcon: Image(systemName: "right"),
action: { /*action*/ }
)
.buttonStyle(.select(isSelected: false))
Button(
title: "Title",
subtitle: "subTitle",
leftIcon: Image(systemName: "left"),
rightIcon: Image(systemName: "right"),
action: { /*action*/ }
)
.buttonStyle(.select(isSelected: false))
.disabled(true)
}
}
.padding(.horizontal, 20)

VStack(spacing: 40) {
Text("Select List")
.font(.title)
VStack {
Button(
title: "Title",
subtitle: "subTitle",
leftIcon: Image(systemName: "left"),
rightIcon: Image(systemName: "right"),
action: {
/*action*/
}
)
.buttonStyle(.selectList(isSelected: true))
Button(
title: "Title",
subtitle: "subTitle",
leftIcon: Image(systemName: "left"),
rightIcon: Image(systemName: "right"),
action: { /*action*/ }
)
.buttonStyle(.selectList(isSelected: false))
}
}
.padding(.horizontal, 20)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ public struct BoxButtonStyle: ButtonStyle {
.foregroundStyle(
getForegroundColor(isPressed: configuration.isPressed)
)
.labelStyle(DefaultBarButtonLabelStyle())
.barButtonDetailStyle(DefaultBarButtonDetailStyle())
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,3 @@ struct DefaultBarButtonDetailStyle: BarButtonDetailStyle {
}
}
}

struct DefaultBarButtonLabelStyle: LabelStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.title
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
//
// SelectButtonDetail.swift
// DesignSystem
//
// Created by devMinseok on 8/13/24.
// Copyright © 2024 PomoNyang. All rights reserved.
//

import SwiftUI

extension Button where Label == SelectButtonDetail<Text, Text, Image?, Image?> {
public init(
title: LocalizedStringKey,
subtitle: LocalizedStringKey,
leftIcon: Image? = nil,
rightIcon: Image? = nil,
action: @escaping () -> Void
) {
self.init(action: action) {
SelectButtonDetail {
Text(title)
} subtitle: {
Text(subtitle)
} leftIcon: {
leftIcon
} rightIcon: {
rightIcon
}
}
}
}

public struct SelectButtonDetail<Title: View, Subtitle: View, LeftIcon: View, RightIcon: View>: View {
@Environment(\.selectButtonDetailStyle) private var style
private let title: Title
private let subtitle: Subtitle
private let leftIcon: LeftIcon
private let rightIcon: RightIcon

init(
@ViewBuilder title: () -> Title,
@ViewBuilder subtitle: () -> Subtitle,
@ViewBuilder leftIcon: () -> LeftIcon,
@ViewBuilder rightIcon: () -> RightIcon
) {
self.title = title()
self.subtitle = subtitle()
self.leftIcon = leftIcon()
self.rightIcon = rightIcon()
}

public var body: some View {
let configuration = SelectButtonDetailConfiguration(
title: title,
subtitle: subtitle,
leftIcon: leftIcon,
rightIcon: rightIcon
)
AnyView(style.resolve(configuration: configuration))
}
}

struct SelectButtonDetailConfiguration {
struct Title: View {
let body: AnyView
}

struct Subtitle: View {
let body: AnyView
}

struct LeftIcon: View {
let body: AnyView
}

struct RightIcon: View {
let body: AnyView
}

let title: Title
let subtitle: Subtitle
let leftIcon: LeftIcon
let rightIcon: RightIcon

fileprivate init(
title: some View,
subtitle: some View,
leftIcon: some View,
rightIcon: some View
) {
self.title = Title(body: AnyView(title))
self.subtitle = Subtitle(body: AnyView(subtitle))
self.leftIcon = LeftIcon(body: AnyView(leftIcon))
self.rightIcon = RightIcon(body: AnyView(rightIcon))
}
}

protocol SelectButtonDetailStyle: DynamicProperty {
typealias Configuration = SelectButtonDetailConfiguration
associatedtype Body: View

@ViewBuilder func makeBody(configuration: Configuration) -> Body
}

extension SelectButtonDetailStyle {
fileprivate func resolve(configuration: Configuration) -> some View {
SelectButtonResolvedDetailStyle(style: self, configuration: configuration)
}
}

private struct SelectButtonResolvedDetailStyle<Style: SelectButtonDetailStyle>: View {
let style: Style
let configuration: Style.Configuration

var body: some View {
style.makeBody(configuration: configuration)
}
}

struct SelectButtonDetailStyleKey: EnvironmentKey {
static var defaultValue: any SelectButtonDetailStyle = DefaultSelectButtonDetailStyle()
}

extension EnvironmentValues {
fileprivate var selectButtonDetailStyle: any SelectButtonDetailStyle {
get { self[SelectButtonDetailStyleKey.self] }
set { self[SelectButtonDetailStyleKey.self] = newValue }
}
}

extension View {
func selectButtonDetailStyle(_ style: some SelectButtonDetailStyle) -> some View {
environment(\.selectButtonDetailStyle, style)
}
}

struct DefaultSelectButtonDetailStyle: SelectButtonDetailStyle {
func makeBody(configuration: Configuration) -> some View {
HStack {
configuration.title
configuration.subtitle
configuration.leftIcon
configuration.rightIcon
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,3 @@ struct DefaultSingleIconButtonDetailStyle: SingleIconButtonDetailStyle {
configuration.icon
}
}

struct SingleIconButtonLabelStyle: LabelStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.title
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public struct IconButtonStyle: ButtonStyle {
.foregroundColor(
getForegroundColor(isFilled: isFilled)
)
.labelStyle(SingleIconButtonLabelStyle())
.singleIconButtonDetailStyle(DefaultSingleIconButtonDetailStyle())
.opacity(isEnabled ? 1 : 0.6)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ public struct RoundButtonStyle: ButtonStyle {
in: RoundedRectangle(cornerRadius: 44)
)
.foregroundColor(Global.Color.white)
.labelStyle(SingleIconButtonLabelStyle())
.singleIconButtonDetailStyle(DefaultSingleIconButtonDetailStyle())
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//
// SelectButtonStyle.swift
// DesignSystem
//
// Created by devMinseok on 8/13/24.
// Copyright © 2024 PomoNyang. All rights reserved.
//

import SwiftUI

public struct SelectButtonStyle: ButtonStyle {
@Environment(\.isEnabled) var isEnabled
let isSelected: Bool

public init(isSelected: Bool) {
self.isSelected = isSelected
}

public func makeBody(configuration: Configuration) -> some View {
configuration.label
.selectButtonDetailStyle(
SelectButtonDetailStyleImpl(
isSelected: isSelected,
isDisabled: !isEnabled
)
)
}
}

extension ButtonStyle where Self == SelectButtonStyle {
public static func select(
isSelected: Bool
) -> Self {
return SelectButtonStyle(isSelected: isSelected)
}
}

struct SelectButtonDetailStyleImpl: SelectButtonDetailStyle {
let isSelected: Bool
let isDisabled: Bool

func makeBody(configuration: Configuration) -> some View {
VStack(spacing: Alias.Spacing.xSmall) {
HStack(spacing: Alias.Spacing.xSmall) {
configuration.leftIcon
configuration.subtitle
.font(Typography.subBodyR)
.foregroundStyle(getSubtitleForegourndColor())
configuration.rightIcon
}
configuration.title
.font(Typography.header5)
.foregroundStyle(getTitleForegourndColor())
}
.padding(.vertical, 16)
.frame(maxWidth: .infinity)
.background(
RoundedRectangle(cornerRadius: Alias.BorderRadius.small)
.fill(getBackgroundColor())
.strokeBorder(isSelected ? Alias.Color.Background.accent1 : .clear, lineWidth: 1)
)
}

func getTitleForegourndColor() -> Color {
if isDisabled {
return Alias.Color.Text.disabled
} else {
if isSelected {
return Alias.Color.Text.primary
} else {
return Alias.Color.Text.secondary
}
}
}

func getSubtitleForegourndColor() -> Color {
if isDisabled {
return Alias.Color.Text.disabled
} else {
return Alias.Color.Text.tertiary
}
}

func getBackgroundColor() -> Color {
if isSelected {
return Alias.Color.Background.accent2
} else {
return Alias.Color.Background.secondary
}
}
}
Loading

0 comments on commit 6560bbd

Please sign in to comment.