# .darken(by:)

Make hover and pressed fills from any color, an exact stop darker in both modes.

Make hover and pressed fills from any color with `darken(by:)`. It moves the color down the palette by whole stops, one by default, and returns a `Color` that still follows dark mode:

```swift
let fill = brand.invertedBackgroundTertiary   // _650 in light mode, _250 in dark

VStack(alignment: .leading) {
    Text("Book now").padding(12).background(fill)
    Text("Book now").padding(12).background(fill.darken())        // hovered: _700 and _300
    Text("Book now").padding(12).background(fill.darken(by: 2))   // pressed: _750 and _350
}
.font(.headline)
.foregroundStyle(brand.invertedForegroundPrimary)
```

What this draws, with `#00B386`:

| Color                        | light mode                             | dark mode                              |
| ---------------------------- | -------------------------------------- | -------------------------------------- |
| `invertedForegroundPrimary`  | #eaf8f2                                | color(display-p3 0.0176 0.1298 0.086)  |
| `invertedBackgroundTertiary` | color(display-p3 0.1368 0.4655 0.3425) | #79dab5                                |
| `_700/_300`                  | color(display-p3 0.1149 0.4143 0.3028) | #4cd2a5                                |
| `_750/_350`                  | color(display-p3 0.0977 0.3637 0.2645) | color(display-p3 0.3144 0.7788 0.5953) |

Rest, hover and pressed are exact stops a design spec can name, and the label stays above 7:1 when pressed, in both modes and every hue. Pick a color and a number of stops below:

A playground applies `darken()` to a palette stop, a token or a hex color. By default it shows `Color.proBlue._600.toColor().darken()`, which gives #3a69a5 in both modes. [Try it on the live page](https://colortokenskit.com/api/darken/).

With the defaults, `proBlue._600` darkens to exactly `proBlue._650`.

## Darken or strengthen?

A pressed button should look darker in both modes. [`strengthen(by:)`](https://colortokenskit.com/api/strengthen/index.md) moves a color away from the page instead, so in dark mode it goes lighter, toward a light label:

```swift
let fill = brand.backgroundTertiary   // _200 in light mode, _700 in dark

HStack {
    Text("Book now").padding(12).background(fill.strengthen(by: 2))   // _300 and _600
    Text("Book now").padding(12).background(fill.darken(by: 2))       // _300 and _800
}
.foregroundStyle(brand.foregroundPrimary)
```

What this draws, with `#00B386`:

| Color               | light mode                            | dark mode                              |
| ------------------- | ------------------------------------- | -------------------------------------- |
| `foregroundPrimary` | color(display-p3 0.0176 0.1298 0.086) | #eaf8f2                                |
| `_300/_600`         | #4cd2a5                               | color(display-p3 0.1547 0.5182 0.3824) |
| `_300/_800`         | #4cd2a5                               | color(display-p3 0.0797 0.3134 0.2262) |

In dark mode, the strengthened fill drops the label to 4.29:1, and the darkened one keeps it at 8.72:1. [Building for interaction states](https://colortokenskit.com/getting-started/interaction-states/index.md) puts these fills in a `ButtonStyle`.

## How it behaves

A palette color lands on an exact stop of its family, so it has that stop's contrast in every hue. Past `_1000` it stays at `_1000`, and black stays black. Gray moves along gray's own stops.

A color off the palette, such as a system color or your own hex, moves by the same step in lightness and keeps its hue and chroma, as [how colors land on exact stops](https://colortokenskit.com/under-the-hood/palette-snapping/index.md) shows. The result keeps the color's opacity, and each mode darkens that mode's color.

## API

```swift
public extension Color {
    func darken(by stops: Int = 1) -> Color
}
```

| Parameter | Type  | Default | What other values do                                                    |
| --------- | ----- | ------- | ----------------------------------------------------------------------- |
| `stops`   | `Int` | `1`     | A negative value goes lighter, so `darken(by: -2)` is `lighten(by: 2)`. |

It returns a new `Color` that resolves in each appearance, so it follows light and dark mode like the color you started from.

## Sources

- [Color+Adjustments.swift](https://github.com/metasidd/ColorTokensKit-Swift/blob/main/Sources/ColorTokensKit/Adjustments/Color+Adjustments.swift), which defines `darken(by:)` as `lighten(by: -stops)`.
- [ColorAdjustment.swift](https://github.com/metasidd/ColorTokensKit-Swift/blob/main/Sources/ColorTokensKit/Adjustments/ColorAdjustment.swift), which moves a color along the stops.

## See also

- [.lighten(by:)](https://colortokenskit.com/api/lighten/index.md): Add highlights and lighter steps to any color, landing on an exact palette stop.
- [.desaturate(by:)](https://colortokenskit.com/api/desaturate/index.md): Gray out disabled and finished states, and every label stays just as readable.
- [.soften(by:)](https://colortokenskit.com/api/soften/index.md): Make quieter text and fills from any token: lighter in light mode, darker in dark mode.
- [Stops: .\_50 to .\_1000](https://colortokenskit.com/api/stops/index.md): Twenty fixed colors per theme, lightest to darkest, with the same contrast in every hue.

---

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