Skip to content
ColorTokensKitby Penguin Design Ventures
Contents
Function

.proAngularGradient()

Draw rings and dials that sweep through your colors, with no seam where the ends meet.

Updated View as Markdown

Draw a ring, a dial or a progress track that sweeps through your colors: call proAngularGradient(). You get SwiftUI's AngularGradient, and your first color comes back at the end, so the ring has no seam where it meets itself.

swift
Circle()
    .strokeBorder(brand._400.triad.proAngularGradient(), lineWidth: 8)
    .frame(width: 80, height: 80)
light mode

triad gives three families spread evenly around the hue wheel, all at _400, and the ring runs through each of them and back to the brand.

A ring through your themes#

Any array of colors or families works. This ring runs through the three destinations, Lisbon, Kyoto and Reykjavík:

swift
Circle()
    .strokeBorder([Color.proOrange, Color.proPink, Color.proSky].proAngularGradient(), lineWidth: 8)
    .frame(width: 80, height: 80)
light mode

A dial from one color#

On one color, proAngularGradient makes the other colors with a recipe. .analogous sweeps from the hue 30° to one side, through your color, to the hue 30° to the other, at the same lightness:

swift
Circle()
    .strokeBorder(brand._400.proAngularGradient(.analogous), lineWidth: 6)
    .frame(width: 80, height: 80)
light mode

How it behaves#

The sweep starts at the trailing edge, 3 o'clock, and runs clockwise around center. To start it somewhere else, such as the top of a progress ring, rotate the view with .rotationEffect(.degrees(-90)).

Your first color is added again at the end unless the last color already matches it in both light and dark mode, so there's never a seam and never a doubled stop. Blending, easing and dark mode work as they do for proGradient(), and one color gives a solid ring.

API#

proAngularGradient is an extension on arrays of Color and ProTheme, and on Color and ProTheme themselves.

swift
public extension Array where Element == Color {
    func proAngularGradient(center: UnitPoint = .center,
                            blend: ProGradient.Blend = .vivid, easing: ProGradient.Easing = .smooth) -> AngularGradient
}
// The same function exists on Array where Element == ProTheme.

public extension Color {
    func proAngularGradient(_ recipe: ProGradient.Recipe = .subtle, center: UnitPoint = .center,
                            blend: ProGradient.Blend = .vivid, easing: ProGradient.Easing = .smooth) -> AngularGradient
}
// The same function exists on ProTheme.
ParameterTypeDefaultWhat other values do
centerUnitPoint.centerMoves the point the colors sweep around.
blendProGradient.Blend.vivid.direct goes straight through OKLab; .rainbow goes around the hue wheel the long way.
easingProGradient.Easing.smoothAnother preset or .timingCurve(_:_:_:_:) moves where the colors change.
recipeProGradient.Recipe.subtleOne-color version only: another recipe or your own.

It returns SwiftUI's AngularGradient, so it works anywhere a shape style does, such as .fill, .stroke and .strokeBorder.

Sources#

See also

  • .proRadialGradient() Draw glows and spotlights that fade from the center outward without going gray.
  • .harmony(_:) Build the harmony someone picks at runtime, from a picker or a setting, in one call.
  • Color theory Pair stops that always read, and pick secondary hues that match your brand, in both modes.
  • Gradient theory Add depth with gradients that stay vivid, from a single color or a recipe, in both modes.