Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
@@ -0,0 +1,96 @@
//
// ChipButton.swift
// AppProduct
//
// Created by 이예지 on 1/3/26.
//

import SwiftUI

// MARK: - ChipButton

struct ChipButton: View {

// MARK: - Properties
private let title: String
private let isSelected: Bool
private let action: () -> Void

@Environment(\.chipButtonSize) private var size

// MARK: - Initializer

/// ChipButton 생성자
/// - Parameters:
/// - title: 버튼 텍스트
/// - icon: 버튼 체크 아이콘
init(_ title: String, isSelected: Bool, action: @escaping () -> Void) {
self.title = title
self.isSelected = isSelected
self.action = action
}

// MARK: - Body

var body: some View {
Button(action: action) {
ChipButtonContent(
title: title,
size: size,
isSelected: isSelected
)
.equatable()
}
.buttonStyle(.plain)
}
}

// MARK: - ChipButtonContent (Presenter)

private struct ChipButtonContent: View, Equatable {
let title: String
let size: ChipButtonSize
let isSelected: Bool

static func == (lhs: ChipButtonContent, rhs: ChipButtonContent) -> Bool {
lhs.title == rhs.title &&
lhs.size == rhs.size &&
lhs.isSelected == rhs.isSelected
}

var body: some View {
Text(title)
.foregroundStyle(Color.neutral900)
.font(size.font)
.padding(.horizontal, 8)
.frame(height: size.height)
.background(
Capsule()
.fill(isSelected ? Color.primary400 : Color.primary100)
)
}
}

// MARK: - ChipButton + AnyChipButton

extension ChipButton: AnyChipButton { }

// MARK: - Preview

#Preview("ChipButton") {
struct Demo: View {
@State private var selected = false

var body: some View {
VStack(spacing: 15) {
HStack(spacing: 8) {
ChipButton("chip", isSelected: selected) {
selected.toggle()
}
.buttonSize(.large)
}
}
}
}
return Demo()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// ChipButtonEnvironment.swift
// AppProduct
//
// Created by 이예지 on 1/3/26.
//

import SwiftUI

// MARK: - Environment Keys

struct ChipButtonSizeKey: EnvironmentKey {
static let defaultValue: ChipButtonSize = .medium
}

// MARK: - EnvironmentValues Extension

extension EnvironmentValues {
var chipButtonSize: ChipButtonSize {
get { self[ChipButtonSizeKey.self] }
set { self[ChipButtonSizeKey.self] = newValue }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// ChipButtonModifiers.swift
// AppProduct
//
// Created by 이예지 on 1/3/26.
//

import SwiftUI

// MARK: - AnyChipButton Protocol

/// ChipButton 전용 프로토콜
protocol AnyChipButton: View { }

// MARK: - ViewModifiers

struct ChipButtonSizeModifier: ViewModifier {
let size: ChipButtonSize

func body(content: Content) -> some View {
content.environment(\.chipButtonSize, size)
}
}

// MARK: - AnyChipButton Extension

extension AnyChipButton {

/// 버튼 사이즈 설정
/// - Parameter size: small, medium, large
func buttonSize(_ size: ChipButtonSize) -> some View {
self.modifier(ChipButtonSizeModifier(size: size))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// ChipButtonSize.swift
// AppProduct
//
// Created by 이예지 on 1/3/26.
//

import SwiftUI

// MARK: - ChipButtonSize

/// ChipButton 사이즈 유형
enum ChipButtonSize {
case small
case medium
case large

var height: CGFloat {
switch self {
case .small:
return 25
case .medium:
return 29
case .large:
return 32
}
}

var font: Font {
switch self {
case .small:
return .app(.caption2, weight: .bold)
case .medium:
return .app(.caption1, weight: .bold)
case .large:
return .app(.footnote, weight: .bold)
}
}
}