Add better usage examples for Design Tokens
Родитель
2dc91ba435
Коммит
bfc478fb8e
154
Design-Tokens.md
154
Design-Tokens.md
|
@ -13,143 +13,47 @@ Design tokens come in three tiers.
|
|||
* Example: `button background = neutral background 2`
|
||||
Our Swift representation of tokens will reflect his hierarchy, with a unidirectional dependency hierarchy. Controls should only depend on Control tokens, without ever directly referring to an alias or global token.
|
||||
|
||||
For more information, see the official documentation for Fluent 2 design tokens here: https://fluent2.microsoft.design/design-tokens.
|
||||
|
||||
# APIs
|
||||
|
||||
## Global tokens
|
||||
|
||||
Let’s start with the basic definition of our global tokens. Below is a sample subset of various types of global tokens.
|
||||
Let’s start with the basic definition of our global tokens. Below is a sample subset of the usage of various types of global tokens.
|
||||
|
||||
```swift
|
||||
public final class GlobalTokens {
|
||||
import SwiftUI
|
||||
import FluentUI
|
||||
|
||||
// MARK: - NeutralColor
|
||||
|
||||
@objc(MSFGlobalTokensNeutralColor)
|
||||
public enum NeutralColorToken: Int, TokenSetKey {
|
||||
case black
|
||||
case grey2
|
||||
case grey4
|
||||
case grey6
|
||||
// ...
|
||||
case grey94
|
||||
case grey96
|
||||
case grey98
|
||||
case white
|
||||
}
|
||||
@objc(colorForNeutralColorToken:)
|
||||
public static func neutralColor(_ token: NeutralColorToken) -> UIColor {
|
||||
switch token {
|
||||
case .black:
|
||||
return UIColor(hexValue: 0x000000)
|
||||
case .grey2:
|
||||
return UIColor(hexValue: 0x050505)
|
||||
case .grey4:
|
||||
return UIColor(hexValue: 0x0A0A0A)
|
||||
case .grey6:
|
||||
return UIColor(hexValue: 0x0F0F0F)
|
||||
// ...
|
||||
case .grey94:
|
||||
return UIColor(hexValue: 0xF0F0F0)
|
||||
case .grey96:
|
||||
return UIColor(hexValue: 0xF5F5F5)
|
||||
case .grey98:
|
||||
return UIColor(hexValue: 0xFAFAFA)
|
||||
case .white:
|
||||
return UIColor(hexValue: 0xFFFFFF)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - BorderRadius
|
||||
|
||||
@objc(MSFGlobalTokensCornerRadius)
|
||||
public enum CornerRadiusToken: TokenSetKey {
|
||||
case radiusNone
|
||||
case radius20
|
||||
case radius40
|
||||
case radius60
|
||||
case radius80
|
||||
case radius120
|
||||
case radiusCircular
|
||||
}
|
||||
@objc(cornerForToken:)
|
||||
public static func corner(_ token: CornerRadiusToken) -> CGFloat {
|
||||
switch token {
|
||||
case .radiusNone:
|
||||
return 0
|
||||
case .radius20:
|
||||
return 2
|
||||
case .radius40:
|
||||
return 4
|
||||
case .radius60:
|
||||
return 6
|
||||
case .radius80:
|
||||
return 8
|
||||
case .radius120:
|
||||
return 12
|
||||
case .radiusCircular:
|
||||
return 9999
|
||||
}
|
||||
}
|
||||
}
|
||||
let darkGrey = GlobalTokens.neutralColor(.grey94) // Color, #F0F0F0
|
||||
let smallCornerRadius = GlobalTokens.corner(.radius20) // CGFloat, 2.0
|
||||
```
|
||||
|
||||
These read-only tokens can be accessed via both Swift and Objective-C using the provided static lookup functions.
|
||||
These read-only tokens can be accessed via both Swift and Objective-C using the provided static lookup functions in `GlobalTokens.swift`. However, because these values are completely unaware of their rendering context, you will usually build UI using Alias Tokens.
|
||||
|
||||
## Alias Tokens
|
||||
|
||||
Alias tokens are similar to global tokens, with one large change: they should reference global tokens whenever possible. Their goal is to provide semantic meaning for the raw values defined in the global system.
|
||||
Alias tokens reference global tokens whenever possible. Their goal is to provide semantic meaning for the raw values defined in the global system.
|
||||
|
||||
These values are stored on a category of `FluentTheme` so they can be easily accessed from any theme object.
|
||||
These values are stored on a category of `FluentTheme` so they can be easily accessed from any theme object. These are the values that most UI should be built using, paired with Global Tokens when appropriate for dimensional values such as spacing and line widths.
|
||||
|
||||
```swift
|
||||
public extension FluentTheme {
|
||||
@objc(MSFColorToken)
|
||||
enum ColorToken: Int, TokenSetKey {
|
||||
// Neutral colors - Background
|
||||
case background1
|
||||
case background1Pressed
|
||||
case background1Selected
|
||||
case background2
|
||||
case background2Pressed
|
||||
case background2Selected
|
||||
import SwiftUI
|
||||
import FluentUI
|
||||
|
||||
// ...
|
||||
}
|
||||
struct MyView: View {
|
||||
@Environment(.\fluentTheme) var fluentTheme: FluentTheme
|
||||
|
||||
/// Returns the color value for the given token.
|
||||
///
|
||||
/// - Parameter token: The `ColorsTokens` value to be retrieved.
|
||||
/// - Returns: A `UIColor` for the given token.
|
||||
@objc(colorForToken:)
|
||||
func color(_ token: ColorToken) -> UIColor {
|
||||
switch token {
|
||||
case .background1:
|
||||
return UIColor(light: GlobalTokens.neutralColor(.white),
|
||||
dark: GlobalTokens.neutralColor(.black),
|
||||
darkElevated: GlobalTokens.neutralColor(.grey4))
|
||||
case .background1Pressed:
|
||||
return UIColor(light: GlobalTokens.neutralColor(.grey88),
|
||||
dark: GlobalTokens.neutralColor(.grey18),
|
||||
darkElevated: GlobalTokens.neutralColor(.grey18))
|
||||
case .background1Selected:
|
||||
return UIColor(light: GlobalTokens.neutralColor(.grey92),
|
||||
dark: GlobalTokens.neutralColor(.grey14),
|
||||
darkElevated: GlobalTokens.neutralColor(.grey14))
|
||||
case .background2:
|
||||
return UIColor(light: GlobalTokens.neutralColor(.white),
|
||||
dark: GlobalTokens.neutralColor(.grey12),
|
||||
darkElevated: GlobalTokens.neutralColor(.grey16))
|
||||
case .background2Pressed:
|
||||
return UIColor(light: GlobalTokens.neutralColor(.grey88),
|
||||
dark: GlobalTokens.neutralColor(.grey30),
|
||||
darkElevated: GlobalTokens.neutralColor(.grey30))
|
||||
case .background2Selected:
|
||||
return UIColor(light: GlobalTokens.neutralColor(.grey92),
|
||||
dark: GlobalTokens.neutralColor(.grey26),
|
||||
darkElevated: GlobalTokens.neutralColor(.grey26))
|
||||
var body: some View {
|
||||
let backgroundColor = fluentTheme.color(.background1)
|
||||
let foregroundColor = fluentTheme.color(.brandForeground1)
|
||||
let cornerRadius = GlobalTokens.corner(.radius20)
|
||||
|
||||
// ...
|
||||
}
|
||||
// Create some view with these values
|
||||
Text("I'm a text label!")
|
||||
.foregroundStyle(foregroundColor)
|
||||
.background(backgroundColor)
|
||||
.clipShape(RoundedRect(cornerRadius: cornerRadius))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -160,18 +64,6 @@ Control token sets are simply the collection of tokens used by a single control.
|
|||
|
||||
A default implementation of the component’s theme will exist alongside the component, providing clients the opportunity to subclass and provide custom values for these tokens. Custom Control tokens can be provided for any control either upon instantiation or after presentation via a public property.
|
||||
|
||||
```swift
|
||||
open class CardNudgeTokens: ControlTokens {
|
||||
open var accentColor: ColorSet {
|
||||
return globalTokens.brandColors[.shade20]
|
||||
}
|
||||
|
||||
open var accentIconSize: CGFloat {
|
||||
return globalTokens.iconSize[.xxSmall]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Sub-Control tokens
|
||||
Tokens for controls contained within another control should be defined in the hosting control’s tokens as optional, then passed down as a custom subclass of the contained control’s tokens to the contained control through override tokens.
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче