# Using ColorTokensKit on visionOS

Use the palette on Apple Vision Pro, where tokens give their dark stops and color goes on buttons.

Your visionOS app gets the palette with the same code, and every token gives its dark stop, because visionOS reports a dark color scheme. Put that color where Apple recommends it on glass, in buttons and background layers, and leave plain text to the system's styles.

```swift
struct TripCard: View {
    let theme = Color.proOrange

    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            Text("Lisbon")
                .font(.headline)
            Text("3 nights from October 12")
                .font(.subheadline)
                .foregroundStyle(.secondary)
            Text("Beach")
                .font(.subheadline.bold())
                .foregroundStyle(theme.foregroundPrimary)   // _50 on visionOS
                .padding(.horizontal, 8)
                .padding(.vertical, 4)
                .background(theme.backgroundTertiary)   // _700 on visionOS
        }
        .padding()
        .glassBackgroundEffect()
    }
}
```

- Beach tag on visionOS: #fdf3ec

The card stays on glass, the title and dates use the system's text styles, and the palette colors the tag, where its text and background are a token pair.

## Why tokens give their dark stops

visionOS has no light or dark appearance for your app to switch between: its glass adapts to the room behind the window instead. It still reports a dark color scheme, and Apple's own system colors use their dark values there. The package's `Color(light:dark:)`, which every token in `ColorTokens.swift` is built with, reads that and picks the dark stop, and [color functions](https://colortokenskit.com/api/soften/index.md) work out their dark-mode result.

## Keep windows on glass

Apple asks apps to avoid solid colors on windows, because glass lets people see their surroundings and keeps contrast as the light changes. On visionOS, `backgroundPrimary` is `_1000`, an opaque near-black that would hide the room. Keep the window's glass, or `.glassBackgroundEffect()` for your own views, and give palette backgrounds to smaller areas: a tag, a button, a selected row.

## Use system styles for text on glass

Text on glass defaults to white, and the system's `.primary`, `.secondary` and `.tertiary` styles add vibrancy, which keeps text readable whatever shows through. A token is a solid color with a fixed contrast against glass, and the palette's contrast pairs hold between tokens, not against a room. So use tokens for text that sits on a token background, like the tag above.

## Color a whole button

```swift
Button {
    // book the trip
} label: {
    Text("Book now")
        .font(.headline)
        .foregroundStyle(theme.invertedForegroundPrimary)   // _1000 on visionOS
        .padding(.horizontal, 20)
        .padding(.vertical, 10)
        .background(theme.invertedBackgroundTertiary)   // _250 on visionOS
}
.buttonStyle(.plain)
```

- Book now button on visionOS: #2d1607

Apple recommends putting color in a background layer or an entire button, so people can see it on any glass. A plain-style button keeps visionOS's standard hover effect, so it still brightens when people look at it. [Building for interaction states](https://colortokenskit.com/getting-started/interaction-states/index.md) covers the pressed and disabled colors.

## UIKit on visionOS

`UIColor(light:dark:)` builds for visionOS as it does for iOS, and gives the dark stop there. The code on [the UIKit page](https://colortokenskit.com/platforms/uikit/index.md) works unchanged.

## Sources

- The library's [Color+Dynamic.swift](https://github.com/metasidd/ColorTokensKit-Swift/blob/main/Sources/ColorTokensKit/Platform/SwiftUI/Color+Dynamic.swift) and [UIColor+Dynamic.swift](https://github.com/metasidd/ColorTokensKit-Swift/blob/main/Sources/ColorTokensKit/Platform/UIKit/UIColor+Dynamic.swift), which build tokens as dynamic `UIColor`s on visionOS, and [Color+Adaptive.swift](https://github.com/metasidd/ColorTokensKit-Swift/blob/main/Sources/ColorTokensKit/Platform/SwiftUI/Color+Adaptive.swift) for the color functions.
- Apple, [WWDC23 session 10110](https://developer.apple.com/videos/play/wwdc2023/10110/), on bringing windowed apps to visionOS: "This platform reports its color scheme as dark", and plain buttons keep the standard hover effect.
- Apple, [Design for spatial user interfaces](https://developer.apple.com/videos/play/wwdc2023/10076/) (WWDC23), on glass, white text, vibrancy and where to use color.
- Apple Human Interface Guidelines, [Materials](https://developer.apple.com/design/human-interface-guidelines/materials): "visionOS doesn't have a distinct Dark Mode setting. Instead, glass automatically adapts to the luminance of the objects and colors behind it."
- Apple Human Interface Guidelines, [Color](https://developer.apple.com/design/human-interface-guidelines/color): "visionOS system colors use the default dark color values."

## See also

- [Using ColorTokensKit in UIKit](https://colortokenskit.com/platforms/uikit/index.md): Give UIKit views the palette's tokens as UIColors that follow dark mode on every iOS version tested.
- [Understanding semantic tokens](https://colortokenskit.com/getting-started/semantic-tokens/index.md): Learn the 20 tokens by the job each one does, and get dark mode and passing contrast with them.
- [Building for interaction states](https://colortokenskit.com/getting-started/interaction-states/index.md): Give buttons and rows hover, pressed, selected and disabled colors that stay readable in both modes.
- [How accessible is it?](https://colortokenskit.com/basics/how-accessible/index.md): What the palette guarantees for contrast in every hue and mode, and what you still need to check.

---

From ColorTokensKit, by Penguin Design Ventures: https://colortokenskit.com/platforms/visionos/ (updated September 26, 2026).
