Files
sodalive-ios/SodaLive/Sources/V2/Component/AudioContentCard.swift

155 lines
3.9 KiB
Swift

//
// AudioContentCard.swift
// SodaLive
//
import SwiftUI
enum AudioContentCardSize {
case large
case medium
case small
var width: CGFloat {
switch self {
case .large:
return 185
case .medium:
return 163
case .small:
return 122
}
}
var labelWidth: CGFloat {
width - (labelHorizontalPadding * 2)
}
var labelHorizontalPadding: CGFloat {
switch self {
case .large:
return 0
case .medium:
return SodaSpacing.s6
case .small:
return SodaSpacing.s4
}
}
var titleTypography: SodaTypography {
switch self {
case .large, .medium:
return .heading4
case .small:
return .body1
}
}
var subtitleTypography: SodaTypography {
switch self {
case .large, .medium:
return .body5
case .small:
return .caption2
}
}
}
struct AudioContentCard<Thumbnail: View>: View {
let size: AudioContentCardSize
let title: String
let subtitle: String
private let thumbnail: Thumbnail
init(
size: AudioContentCardSize,
title: String,
subtitle: String,
@ViewBuilder thumbnail: () -> Thumbnail
) {
self.size = size
self.title = title
self.subtitle = subtitle
self.thumbnail = thumbnail()
}
var body: some View {
VStack(alignment: .leading, spacing: SodaSpacing.s8) {
thumbnailContent
labelContent
}
.frame(width: size.width, alignment: .leading)
}
private var thumbnailContent: some View {
thumbnail
.frame(width: size.width, height: size.width)
.clipped()
.frame(width: size.width, height: size.width)
.clipShape(RoundedRectangle(cornerRadius: SodaSpacing.s14, style: .continuous))
}
private var labelContent: some View {
VStack(alignment: .leading, spacing: 2) {
Text(title)
.appFont(size.titleTypography)
.foregroundColor(.white)
.lineLimit(1)
.truncationMode(.tail)
Text(subtitle)
.appFont(size.subtitleTypography)
.foregroundColor(Color.gray500)
.lineLimit(1)
.truncationMode(.tail)
}
.frame(width: size.labelWidth, alignment: .leading)
.padding(.horizontal, size.labelHorizontalPadding)
.frame(width: size.width, alignment: .leading)
}
}
struct AudioContentCard_Previews: PreviewProvider {
static var previews: some View {
HStack(alignment: .top, spacing: SodaSpacing.s20) {
AudioContentCard(
size: .large,
title: "오디오 콘텐츠 제목입니다",
subtitle: "크리에이터명"
) {
previewThumbnail(Color.gray800)
}
AudioContentCard(
size: .medium,
title: "긴 제목은 한 줄로 말줄임 처리됩니다",
subtitle: "긴 부제목도 한 줄로 말줄임 처리됩니다"
) {
previewThumbnail(Color.gray700)
}
AudioContentCard(
size: .small,
title: "스몰 카드",
subtitle: "오디오"
) {
previewThumbnail(Color.gray900)
}
}
.padding(SodaSpacing.s20)
.background(Color.black)
.previewLayout(.sizeThatFits)
}
private static func previewThumbnail(_ color: Color) -> some View {
ZStack {
color
Image(systemName: "waveform")
.font(.system(size: 32, weight: .bold))
.foregroundColor(Color.gray500)
}
}
}