Skip to content

Commit

Permalink
Add CompoundIcon.Size.
Browse files Browse the repository at this point in the history
  • Loading branch information
pixlwave committed Sep 20, 2023
1 parent 5629889 commit 1b2591d
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 23 deletions.
1 change: 0 additions & 1 deletion Sources/Compound/Form Styles/FormButtonStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ public enum FormRowAccessory: View {
case .selected(let isSelected):
if isSelected {
CompoundIcon(\.check)
.font(.system(size: 24))
.foregroundColor(.compound.iconPrimary)
.accessibilityAddTraits(.isSelected)
}
Expand Down
86 changes: 66 additions & 20 deletions Sources/Compound/Icons/CompoundIcon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,60 @@
import CompoundDesignTokens
import SwiftUI

/// A view that displays an icon from Compound. The icon behaves
/// similarly to an SF Symbol whereby it will scale to match the font
/// given to it by the `font` modifier, as well as with Dynamic Type.
/// A view that displays an icon from Compound. The icon defaults to a size of 24pt
/// and scales with Dynamic Type, relative to any font given to it by the `font` modifier.
public struct CompoundIcon: View {
/// The size of the icon.
public enum Size {
/// An icon size of 16pt.
case xSmall
/// An icon size of 20pt.
case small
/// An icon size of 24pt.
case medium
/// A custom icon size.
case custom(CGFloat)

var value: CGFloat {
switch self {
case .xSmall: return 16
case .small: return 20
case .medium: return 24
case .custom(let size): return size
}
}
}

private var size: Size
private var image: Image

/// Creates an icon using a key path from the Compound tokens.
public init(_ icon: KeyPath<CompoundIcons, Image>) {
///
/// - Parameters:
/// - icon: The icon to show.
/// - size: The size of the icon. Defaults to `.medium` (24pt).
public init(_ icon: KeyPath<CompoundIcons, Image>, size: Size = .medium) {
image = .compound[keyPath: icon]
self.size = size
}

/// Creates an icon using a custom image for preview purposes
/// in the Inspector app.
/// Creates an icon using a custom image to allow assets from outside
/// of Compound to scale in the same way as icons.
///
/// If using this initializer with any other image, make sure that its
/// dimensions match those of the compound icons otherwise it
/// will likely not behave as expected.
public init(customImage: Image) {
/// - Parameters:
/// - customImage: The image that should be displayed
/// - size: The size of the icon. Defaults to `.medium` (24pt).
///
/// ** Note:** The image should have a square frame or it may end up distorted.
public init(customImage: Image, size: Size = .medium) {
image = customImage
self.size = size
}

public var body: some View {
image
.resizable()
.modifier(CompoundIconStyle())
.modifier(CompoundIconStyle(size: size))
}
}

Expand All @@ -53,14 +82,16 @@ public struct CompoundIcon: View {
private struct CompoundIconStyle: ViewModifier {
@Environment(\.font) private var font

let size: CompoundIcon.Size

private var fontSize: FontSize {
FontSize.reflecting(font ?? .body) ?? .style(.body)
}

func body(content: Content) -> some View {
let fontSize = fontSize
content
.modifier(CompoundIconFrame(fontSize: fontSize.value, textStyle: fontSize.style))
.modifier(CompoundIconFrame(fontSize: size.value, textStyle: fontSize.style))
}
}

Expand All @@ -79,6 +110,21 @@ private struct CompoundIconFrame: ViewModifier {
}
}

public extension Label {
/// Creates a label with an icon from Compound and a title generated from a string.
/// - Parameters:
/// - title: A string used as the label’s title.
/// - icon: The icon to use from Compound.
/// - size: The size of the icon. Defaults to `.medium` (24pt).
init(_ title: some StringProtocol, icon: KeyPath<CompoundIcons, Image>, size: CompoundIcon.Size = .medium) where Title == Text, Icon == CompoundIcon {
self.init {
Text(title)
} icon: {
CompoundIcon(icon, size: size)
}
}
}

struct CompoundIcon_Previews: PreviewProvider {
static var previews: some View {
form
Expand Down Expand Up @@ -124,26 +170,26 @@ struct CompoundIcon_Previews: PreviewProvider {
static var buttons: some View {
VStack {
Button { } label: {
Label { Text("Heading Large") } icon: {
CompoundIcon(\.userProfile)
Label { Text("Body Large") } icon: {
CompoundIcon(\.userProfile, size: .medium)
}
}
.font(.compound.headingLG)
.buttonStyle(.borderedProminent)

Button { } label: {
Label { Text("Body Large") } icon: {
CompoundIcon(\.userProfile)
Label { Text("Body Small") } icon: {
CompoundIcon(\.userProfile, size: .small)
}
}
.font(.compound.bodySM)
.buttonStyle(.borderedProminent)

Button { } label: {
Label { Text("Body Small") } icon: {
CompoundIcon(\.userProfile)
Label { Text("Body xSmall") } icon: {
CompoundIcon(\.userProfile, size: .xSmall)
}
}
.font(.compound.bodySM)
.font(.compound.bodyXS)
.buttonStyle(.borderedProminent)
}
}
Expand Down
2 changes: 0 additions & 2 deletions Sources/Compound/List/ListRowAccessory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,10 @@ public enum ListRowAccessory: View {
switch self {
case .navigationLink:
CompoundIcon(\.chevronRight)
.font(.system(size: 24))
.foregroundColor(.compound.iconTertiaryAlpha)
.flipsForRightToLeftLayoutDirection(true)
case .selected:
CompoundIcon(\.check)
.font(.system(size: 24))
.foregroundColor(.compound.iconPrimary)
.accessibilityAddTraits(.isSelected)
.padding(.vertical, -4)
Expand Down

0 comments on commit 1b2591d

Please sign in to comment.