Put a soft spotlight behind a card's content, or a glow behind a badge: call proRadialGradient() on your colors. You get SwiftUI's EllipticalGradient, from the first color at the center to the last at the edges of its view, blended the same vivid way as proGradient().
let theme = Color.proPink // Kyoto's color
VStack(spacing: 4) {
Text("Kyoto")
.font(.headline)
.foregroundStyle(theme.foregroundPrimary)
Text("5 nights from November 3")
.font(.subheadline)
.foregroundStyle(theme.foregroundSecondary)
}
.padding(32)
.frame(maxWidth: .infinity)
.background([theme.backgroundTertiary, theme.backgroundPrimary].proRadialGradient()) // _200 at the center to _50 in light modeBoth ends are tokens, so the spotlight follows dark mode: it runs from _700 at the center to _1000 at the edges there.
A glow that fades to clear#
On one color, proRadialGradient makes the other colors with a recipe. .fade runs from the color at the center to transparent at the edges, for a glow over any background:
Circle()
.fill(Color.proPink._400.proRadialGradient(.fade))
.frame(width: 80, height: 80)The glow keeps its pink all the way out: only the opacity falls, so its edge doesn't darken the view behind it.
A backdrop from one family#
Three stops of one family give a backdrop with depth. Here the center is lighter than the edges:
let reykjavik = Color.proSky
Rectangle()
.fill([reykjavik._100, reykjavik._300, reykjavik._500].proRadialGradient())
.frame(height: 120)How it behaves#
The gradient is an ellipse that reaches the edges of its view, so a wide view gets a wide ellipse. Past the ellipse, in the corners, the view shows the last color. center moves the middle of the ellipse, as a UnitPoint such as .top or .bottomTrailing.
Blending, easing and dark mode work as they do for proGradient(): the path goes around the OKLCH hue wheel, eases .smooth by default, and in-between colors are worked out in the current appearance. One color gives a solid fill.
API#
proRadialGradient is an extension on arrays of Color and ProTheme, and on Color and ProTheme themselves.
public extension Array where Element == Color {
func proRadialGradient(center: UnitPoint = .center,
blend: ProGradient.Blend = .vivid, easing: ProGradient.Easing = .smooth) -> EllipticalGradient
}
// The same function exists on Array where Element == ProTheme.
public extension Color {
func proRadialGradient(_ recipe: ProGradient.Recipe = .subtle, center: UnitPoint = .center,
blend: ProGradient.Blend = .vivid, easing: ProGradient.Easing = .smooth) -> EllipticalGradient
}
// The same function exists on ProTheme.| Parameter | Type | Default | What other values do |
|---|---|---|---|
center | UnitPoint | .center | Moves the middle of the ellipse, such as .top. |
blend | ProGradient.Blend | .vivid | .direct goes straight through OKLab; .rainbow goes around the hue wheel the long way. |
easing | ProGradient.Easing | .smooth | Another preset or .timingCurve(_:_:_:_:) moves where the colors change. |
recipe | ProGradient.Recipe | .subtle | One-color version only: another recipe or your own. |
It returns SwiftUI's EllipticalGradient, so it works anywhere a shape style does, such as .background and .fill.
Sources#
- ColorTokensKit source: Array+ProGradient.swift and Color+ProGradient.swift.
- Apple, EllipticalGradient.
See also
- .proAngularGradient() Draw rings and dials that sweep through your colors, with no seam where the ends meet.
- Gradient theory Add depth with gradients that stay vivid, from a single color or a recipe, in both modes.
- How gradients blend and ease Why plain gradients turn gray, how each blend travels between colors, and where easing puts them.
- Understanding semantic tokens Learn the 20 tokens by the job each one does, and get dark mode and passing contrast with them.