# .proAngularGradient()

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

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)
```

What this draws, with `#00B386`:

| Color             | light mode                             | dark mode                              |
| ----------------- | -------------------------------------- | -------------------------------------- |
| `_400`            | color(display-p3 0.2666 0.7286 0.5502) | color(display-p3 0.2666 0.7286 0.5502) |
| `hue:286.99._400` | color(display-p3 0.63 0.5917 0.9929)   | color(display-p3 0.63 0.5917 0.9929)   |
| `hue:46.99._400`  | #f98546                                | #f98546                                |

It draws a angular gradient from `_400` to `hue:286.99._400` to `hue:46.99._400`, with `.vivid` and `.smooth`.

[`triad`](https://colortokenskit.com/api/triad/index.md) 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)
```

What this draws:

| Color         | light mode                             | dark mode                              |
| ------------- | -------------------------------------- | -------------------------------------- |
| `orange._450` | #e97a31                                | #e97a31                                |
| `pink._450`   | #eb6f9a                                | #eb6f9a                                |
| `sky._450`    | color(display-p3 0.1688 0.6353 0.8712) | color(display-p3 0.1688 0.6353 0.8712) |

It draws a angular gradient from `orange._450` to `pink._450` to `sky._450`, with `.vivid` and `.smooth`.

## A dial from one color

On one color, `proAngularGradient` makes the other colors with a [recipe](https://colortokenskit.com/api/gradient-recipes/index.md). `.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)
```

What this draws, with `#00B386`:

| Color  | light mode                             | dark mode                              |
| ------ | -------------------------------------- | -------------------------------------- |
| `_400` | color(display-p3 0.2666 0.7286 0.5502) | color(display-p3 0.2666 0.7286 0.5502) |

It draws a angular gradient from the `.analogous` recipe from `_400`, with `.vivid` and `.smooth`.

## 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()`](https://colortokenskit.com/api/pro-gradient/index.md), 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.
```

| Parameter | Type                 | Default   | What other values do                                                                                            |
| --------- | -------------------- | --------- | --------------------------------------------------------------------------------------------------------------- |
| `center`  | `UnitPoint`          | `.center` | Moves the point the colors sweep around.                                                                        |
| `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](https://colortokenskit.com/api/gradient-recipes/index.md) or your own. |

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

## Sources

- ColorTokensKit source: [Array+ProGradient.swift](https://github.com/metasidd/ColorTokensKit-Swift/blob/main/Sources/ColorTokensKit/Gradients/Array+ProGradient.swift) and [GradientStops.swift](https://github.com/metasidd/ColorTokensKit-Swift/blob/main/Sources/ColorTokensKit/Gradients/GradientStops.swift).
- Apple, [AngularGradient](https://developer.apple.com/documentation/swiftui/angulargradient).

## See also

- [.proRadialGradient()](https://colortokenskit.com/api/pro-radial-gradient/index.md): Draw glows and spotlights that fade from the center outward without going gray.
- [.harmony(\_:)](https://colortokenskit.com/api/harmony/index.md): Build the harmony someone picks at runtime, from a picker or a setting, in one call.
- [Color theory](https://colortokenskit.com/advanced/color-theory/index.md): Pair stops that always read, and pick secondary hues that match your brand, in both modes.
- [Gradient theory](https://colortokenskit.com/advanced/gradient-theory/index.md): Add depth with gradients that stay vivid, from a single color or a recipe, in both modes.

---

From ColorTokensKit, by Penguin Design Ventures: https://colortokenskit.com/api/pro-angular-gradient/ (updated September 26, 2026).
