Skip to content

Overriding Tokens

Mike Schreiber edited this page May 7, 2024 · 4 revisions

Overriding Tokens

This document explains how to override tokens from the Fluent Design System using FluentUI's Theming system.

Overriding Global Tokens

Global tokens are our most fundamental atoms of design information - as such, overriding these values is not supported.

Overriding Alias Tokens

Alias tokens are stored on the FluentTheme object, and as such can be customized when creating a new instance of FluentTheme.

In addition to hard-coded values, your custom alias tokens can also reference global tokens:

import FluentUI

var colorOverrides = [FluentTheme.ColorToken: UIColor]()

// Hard-coded values work fine.
colorOverrides[.background1] = UIColor(light: UIColor(hexValue: 0xEFF6FC), 
                                       dark: UIColor(hexValue: 0x001526))

// You can also reference global tokens.
colorOverrides[.stencil1] = GlobalTokens.brandColor(.comm80)

// Create and set a custom theme with these customized token sets.
let customFluentTheme = FluentTheme(colorOverrides: colorOverrides)

// Apply the custom Fluent theme to your app, window, or view as described below.

Overriding Component Tokens

To customize an individual component, consumers can directly modify values in the control's tokenSet property.

import FluentUI

self.cardNudge.tokenSet[.cornerRadius] = .float { 8.0 }
self.cardNudge.tokenSet[.outlineColor] = .color { GlobalTokens.neutralColor(.grey12) }

This same custom token override can be registered to apply to all components of this type theme-wide:

view.fluentTheme.register(tokenSetType: CardNudgeTokenSet.self, tokenSet: [
    .cornerRadius: .float { 8.0 },
    .outlineColor: .color { GlobalTokens.neutralColor(.grey12) }
])

Applying a Custom FluentTheme

FluentTheme represent a way to group together a custom set of alias and control tokens. Custom themes can be applied in one of two ways: globally, which applies to the entire application, or on a specific branch of the view hierarchy, including the root view or parent UIWindow.

Global Theme

The FluentUI library exposes a writeable static property, FluentTheme.shared.

This static FluentTheme instance will normally return the default token values associated with Fluent. However, it is also available for overriding in cases where a single custom theme is desired for the app linking this library.

let customTheme: FluentTheme = // a FluentTheme instance initialized with custom values
FluentTheme.shared = customTheme

Note that any custom themes set on a UIView hierarchy or via a SwiftUI view modifier will take precedence over this value. This value provides the fallback theme for cases where those overrides are not provided. See below for more information about per-view overriding.

View-Specific Theme

In addition to, or instead of, global themes, a custom theme can be applied to a specific UIView or SwiftUI View hierarchy, as detailed below.

SwiftUI

Our framework provides a simple ViewModifier called fluentTheme(_:) which takes a FluentTheme instance as its only argument. Simply add this view modifier to the highest point in your view hierarchy in which you’d like the custom theme to apply, and the theme will be detected and applied by any Fluent component in its subview hierarchy.

public var body: some View {
    VStack {
        // ...
        // some views that contain Fluent components
        // ...
    }
    .fluentTheme(myCustomFluentTheme)
}

If you'd like to use tokens from the FluentTheme in the environment for your own controls, you can retrieve the FluentTheme from the environment via EnvironmentValues by adding @Environment(\.fluentTheme) var fluentTheme: FluentTheme to your view.

UIKit

When importing FluentUI, a new public property on UIView will be available: fluentTheme. Simply set a customized instance of FluentTheme on the fluentTheme property on the view or window you wish to host your components in, and all views in its subview hierarchy will be styled with this theme.

let customTheme: FluentTheme = // a FluentTheme instance initialized with custom values
let view = // ... any UIView or UIWindow in your app
view.fluentTheme = customTheme