Created
June 11, 2018 16:53
-
-
Save dchohfi/eed0c804e94bb51681d31f53fdd0c498 to your computer and use it in GitHub Desktop.
Apple custom typography
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
// swiftlint:disable file_length | |
extension UIColor { | |
static var link: UIColor { | |
return UIColor(r: 0, g: 152, b: 238) | |
} | |
static var toastNotification: UIColor { | |
return .white | |
} | |
static var mapMarker: UIColor { | |
return .black | |
} | |
static var titleNavigationBar: UIColor { | |
return .white | |
} | |
static var title1: UIColor { | |
return .black | |
} | |
static var title2: UIColor { | |
return .black | |
} | |
static var title3: UIColor { | |
return .black | |
} | |
static var headline: UIColor { | |
return .black | |
} | |
static var body: UIColor { | |
return .black | |
} | |
static var callout: UIColor { | |
return .black | |
} | |
static var subheadline: UIColor { | |
return .darkGray | |
} | |
static var footnote: UIColor { | |
return .darkGray | |
} | |
static var caption1: UIColor { | |
return UIColor.nn.gray.warm | |
} | |
static var caption2: UIColor { | |
return .black | |
} | |
static var mainButton: UIColor { | |
return .black | |
} | |
} | |
// swiftlint:disable line_length | |
extension String { | |
func attributedOf(size: CGFloat = 12, color: UIColor = .black) -> NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: size), | |
NSForegroundColorAttributeName: color]) | |
} | |
var placeholder: NSAttributedString { | |
return self.body(weight: UIFontWeightLight, | |
color: .lightGray) | |
} | |
var link: NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.link, | |
NSForegroundColorAttributeName: UIColor.link]) | |
} | |
func link(_ color: UIColor = .link) -> NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.link, | |
NSForegroundColorAttributeName: color]) | |
} | |
var toastNotification: NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.toastNotification, | |
NSForegroundColorAttributeName: UIColor.toastNotification]) | |
} | |
var mapMarker: NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.mapMarker, | |
NSForegroundColorAttributeName: UIColor.mapMarker]) | |
} | |
func titleNavigationBar(_ color: UIColor = .titleNavigationBar) -> NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.titleNavigationBar, | |
NSForegroundColorAttributeName: color]) | |
} | |
func title1(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightLight, | |
color: UIColor = .title1) -> NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.title1(minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory, | |
weight: weight), | |
NSForegroundColorAttributeName: color]) | |
} | |
func title2(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightSemibold, | |
color: UIColor = .title2) -> NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.title2(minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory, | |
weight: weight), | |
NSForegroundColorAttributeName: color]) | |
} | |
func title3(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightSemibold, | |
color: UIColor = .title3) -> NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.title3(minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory, | |
weight: weight), | |
NSForegroundColorAttributeName: color]) | |
} | |
func headline(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightSemibold, | |
color: UIColor = .headline) -> NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.headline(minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory, | |
weight: weight), | |
NSForegroundColorAttributeName: color]) | |
} | |
func body(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightRegular, | |
color: UIColor = .body) -> NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.body(minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory, | |
weight: weight), | |
NSForegroundColorAttributeName: color]) | |
} | |
func callout(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightSemibold, | |
color: UIColor = .callout) -> NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.callout(minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory, | |
weight: weight), | |
NSForegroundColorAttributeName: color]) | |
} | |
func subheadline(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightRegular, | |
color: UIColor = .subheadline) -> NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.subheadline(minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory, | |
weight: weight), | |
NSForegroundColorAttributeName: color]) | |
} | |
func footnote(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightRegular, | |
color: UIColor = .footnote) -> NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.footnote(minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory, | |
weight: weight), | |
NSForegroundColorAttributeName: color]) | |
} | |
func caption1(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightRegular, | |
color: UIColor = .caption1) -> NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.caption1(minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory, | |
weight: weight), | |
NSForegroundColorAttributeName: color]) | |
} | |
func caption2(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightBold, | |
color: UIColor = .caption2) -> NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.caption2(minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory, | |
weight: weight), | |
NSForegroundColorAttributeName: color]) | |
} | |
func mainButton(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightSemibold) -> NSAttributedString { | |
return NSAttributedString(string: self, attributes: [NSFontAttributeName: UIFont.mainButton(minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory, | |
weight: weight), | |
NSForegroundColorAttributeName: UIColor.mainButton]) | |
} | |
} | |
extension UIFont { | |
static var link: UIFont { | |
return .systemFont(ofSize: 15, weight: UIFontWeightMedium) | |
} | |
static var toastNotification: UIFont { | |
return .systemFont(ofSize: 14, weight: UIFontWeightMedium) | |
} | |
static var mapMarker: UIFont { | |
return .systemFont(ofSize: 13, weight: UIFontWeightMedium) | |
} | |
static var titleNavigationBar: UIFont { | |
return .boldSystemFont(ofSize: 17) | |
} | |
static func title1(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightLight) -> UIFont { | |
let pointSize = UIFontDescriptor.currentPreferredSize(textStyle: .title1, | |
minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory) | |
return .systemFont(ofSize: pointSize, weight: weight) | |
} | |
static func title2(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightSemibold) -> UIFont { | |
let pointSize = UIFontDescriptor.currentPreferredSize(textStyle: .title2, | |
minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory) | |
return .systemFont(ofSize: pointSize, weight: weight) | |
} | |
static func title3(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightSemibold) -> UIFont { | |
let pointSize = UIFontDescriptor.currentPreferredSize(textStyle: .title3, | |
minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory) | |
return .systemFont(ofSize: pointSize, weight: weight) | |
} | |
static func headline(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightSemibold) -> UIFont { | |
let pointSize = UIFontDescriptor.currentPreferredSize(textStyle: .headline, | |
minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory) | |
return .systemFont(ofSize: pointSize, weight: weight) | |
} | |
static func body(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightRegular) -> UIFont { | |
let pointSize = UIFontDescriptor.currentPreferredSize(textStyle: .headline, | |
minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory) | |
return .systemFont(ofSize: pointSize, weight: weight) | |
} | |
static func callout(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightSemibold) -> UIFont { | |
let pointSize = UIFontDescriptor.currentPreferredSize(textStyle: .callout, | |
minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory) | |
return .systemFont(ofSize: pointSize, weight: weight) | |
} | |
static func subheadline(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightRegular) -> UIFont { | |
let pointSize = UIFontDescriptor.currentPreferredSize(textStyle: .subheadline, | |
minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory) | |
return .systemFont(ofSize: pointSize, weight: weight) | |
} | |
static func footnote(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightRegular) -> UIFont { | |
let pointSize = UIFontDescriptor.currentPreferredSize(textStyle: .footnote, | |
minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory) | |
return .systemFont(ofSize: pointSize, weight: weight) | |
} | |
static func caption1(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightRegular) -> UIFont { | |
let pointSize = UIFontDescriptor.currentPreferredSize(textStyle: .caption1, | |
minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory) | |
return .systemFont(ofSize: pointSize, weight: weight) | |
} | |
static func caption2(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightBold) -> UIFont { | |
let pointSize = UIFontDescriptor.currentPreferredSize(textStyle: .caption2, | |
minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory) | |
return .systemFont(ofSize: pointSize, weight: weight) | |
} | |
static func mainButton(minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge, | |
weight: CGFloat = UIFontWeightSemibold) -> UIFont { | |
let pointSize = UIFontDescriptor.currentPreferredSize(textStyle: .mainButton, | |
minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory) | |
return .systemFont(ofSize: pointSize, weight: weight) | |
} | |
} | |
extension UIFontDescriptor { | |
private static var contentSizeLargeHeightIndex = 3 // this is the index for .large size on the array bellow | |
private static var contentSizesHeight: [UIContentSizeCategory] = | |
[.extraSmall, | |
.small, | |
.medium, | |
.large, | |
.extraLarge, | |
.extraExtraLarge, | |
.extraExtraExtraLarge, | |
.accessibilityMedium, | |
.accessibilityLarge, | |
.accessibilityExtraLarge, | |
.accessibilityExtraExtraLarge, | |
.accessibilityExtraExtraExtraLarge] | |
static func currentPreferredSize(textStyle: UIFontTextStyle = .body, | |
minimumContentSizeCategory: UIContentSizeCategory = .extraSmall, | |
maximumContentSizeCategory: UIContentSizeCategory = .accessibilityExtraExtraExtraLarge) -> CGFloat { | |
let contentSize = self.preferredContentSizeCategoryInBoundries(minimumContentSizeCategory: minimumContentSizeCategory, | |
maximumContentSizeCategory: maximumContentSizeCategory) | |
guard let style = self.fontSizeTable[textStyle], let fontSize = style[contentSize] else { return 17 } | |
return fontSize | |
} | |
private static func preferredContentSizeCategoryInBoundries(minimumContentSizeCategory: UIContentSizeCategory, | |
maximumContentSizeCategory: UIContentSizeCategory) -> UIContentSizeCategory { | |
let contentSize = UIApplication.shared.preferredContentSizeCategory | |
let preferredContentSizeHeight = self.contentSizesHeight.index(of: contentSize) ?? self.contentSizeLargeHeightIndex | |
let minimumContentSizeHeight = self.contentSizesHeight.index(of: minimumContentSizeCategory) ?? 0 | |
let maximumContentSizeHeight = self.contentSizesHeight.index(of: maximumContentSizeCategory) ?? self.contentSizesHeight.count | |
if preferredContentSizeHeight < minimumContentSizeHeight { | |
return self.contentSizesHeight[minimumContentSizeHeight] | |
} else if preferredContentSizeHeight > maximumContentSizeHeight { | |
return self.contentSizesHeight[maximumContentSizeHeight] | |
} | |
return contentSize | |
} | |
private static var fontSizeTable: [UIFontTextStyle: [UIContentSizeCategory: CGFloat]] = { | |
return [ | |
.title1: [ | |
.accessibilityExtraExtraExtraLarge: 34, | |
.accessibilityExtraExtraLarge: 34, | |
.accessibilityExtraLarge: 34, | |
.accessibilityLarge: 34, | |
.accessibilityMedium: 34, | |
.extraExtraExtraLarge: 34, | |
.extraExtraLarge: 32, | |
.extraLarge: 30, | |
.large: 28, | |
.medium: 27, | |
.small: 26, | |
.extraSmall: 25], | |
.title2: [ | |
.accessibilityExtraExtraExtraLarge: 28, | |
.accessibilityExtraExtraLarge: 28, | |
.accessibilityExtraLarge: 28, | |
.accessibilityLarge: 28, | |
.accessibilityMedium: 28, | |
.extraExtraExtraLarge: 28, | |
.extraExtraLarge: 26, | |
.extraLarge: 24, | |
.large: 22, | |
.medium: 21, | |
.small: 20, | |
.extraSmall: 19], | |
.title3: [ | |
.accessibilityExtraExtraExtraLarge: 26, | |
.accessibilityExtraExtraLarge: 26, | |
.accessibilityExtraLarge: 26, | |
.accessibilityLarge: 26, | |
.accessibilityMedium: 26, | |
.extraExtraExtraLarge: 26, | |
.extraExtraLarge: 24, | |
.extraLarge: 22, | |
.large: 20, | |
.medium: 19, | |
.small: 18, | |
.extraSmall: 17], | |
.headline: [ | |
.accessibilityExtraExtraExtraLarge: 23, | |
.accessibilityExtraExtraLarge: 23, | |
.accessibilityExtraLarge: 23, | |
.accessibilityLarge: 23, | |
.accessibilityMedium: 23, | |
.extraExtraExtraLarge: 23, | |
.extraExtraLarge: 21, | |
.extraLarge: 19, | |
.large: 17, | |
.medium: 16, | |
.small: 15, | |
.extraSmall: 14], | |
.body: [ | |
.accessibilityExtraExtraExtraLarge: 22, | |
.accessibilityExtraExtraLarge: 22, | |
.accessibilityExtraLarge: 22, | |
.accessibilityLarge: 22, | |
.accessibilityMedium: 22, | |
.extraExtraExtraLarge: 22, | |
.extraExtraLarge: 20, | |
.extraLarge: 18, | |
.large: 16, | |
.medium: 15, | |
.small: 14, | |
.extraSmall: 13], | |
.callout: [ | |
.accessibilityExtraExtraExtraLarge: 22, | |
.accessibilityExtraExtraLarge: 22, | |
.accessibilityExtraLarge: 22, | |
.accessibilityLarge: 22, | |
.accessibilityMedium: 22, | |
.extraExtraExtraLarge: 22, | |
.extraExtraLarge: 20, | |
.extraLarge: 18, | |
.large: 16, | |
.medium: 15, | |
.small: 14, | |
.extraSmall: 13], | |
.subheadline: [ | |
.accessibilityExtraExtraExtraLarge: 20, | |
.accessibilityExtraExtraLarge: 20, | |
.accessibilityExtraLarge: 20, | |
.accessibilityLarge: 20, | |
.accessibilityMedium: 20, | |
.extraExtraExtraLarge: 20, | |
.extraExtraLarge: 18, | |
.extraLarge: 16, | |
.large: 14, | |
.medium: 13, | |
.small: 12, | |
.extraSmall: 11], | |
.footnote: [ | |
.accessibilityExtraExtraExtraLarge: 19, | |
.accessibilityExtraExtraLarge: 19, | |
.accessibilityExtraLarge: 19, | |
.accessibilityLarge: 19, | |
.accessibilityMedium: 19, | |
.extraExtraExtraLarge: 19, | |
.extraExtraLarge: 17, | |
.extraLarge: 15, | |
.large: 13, | |
.medium: 12, | |
.small: 12, | |
.extraSmall: 12], | |
.caption1: [ | |
.accessibilityExtraExtraExtraLarge: 18, | |
.accessibilityExtraExtraLarge: 18, | |
.accessibilityExtraLarge: 18, | |
.accessibilityLarge: 18, | |
.accessibilityMedium: 18, | |
.extraExtraExtraLarge: 18, | |
.extraExtraLarge: 16, | |
.extraLarge: 14, | |
.large: 12, | |
.medium: 11, | |
.small: 11, | |
.extraSmall: 11], | |
.caption2: [ | |
.accessibilityExtraExtraExtraLarge: 17, | |
.accessibilityExtraExtraLarge: 17, | |
.accessibilityExtraLarge: 17, | |
.accessibilityLarge: 17, | |
.accessibilityMedium: 17, | |
.extraExtraExtraLarge: 17, | |
.extraExtraLarge: 15, | |
.extraLarge: 13, | |
.large: 11, | |
.medium: 10, | |
.small: 10, | |
.extraSmall: 10], | |
.mainButton: [ | |
.accessibilityExtraExtraExtraLarge: 22, | |
.accessibilityExtraExtraLarge: 22, | |
.accessibilityExtraLarge: 22, | |
.accessibilityLarge: 22, | |
.accessibilityMedium: 22, | |
.extraExtraExtraLarge: 22, | |
.extraExtraLarge: 20, | |
.extraLarge: 18, | |
.large: 16, | |
.medium: 15, | |
.small: 14, | |
.extraSmall: 13] | |
] | |
}() | |
} | |
extension UIFontTextStyle { | |
public static let mainButton: UIFontTextStyle = UIFontTextStyle(rawValue: "main button") | |
} | |
// swiftlint:enable line_length | |
// swiftlint:enable file_length |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment