# ColorTokensKit

The most complete color system for Swift: 740 colors in 37 themes, tokens that handle dark mode, contrast that holds in every hue, and one-line theming.

Every stop of every family, as Display P3 hex:

| Family          | \_50    | \_100   | \_150   | \_200   | \_250   | \_300   | \_350   | \_400   | \_450   | \_500   | \_550   | \_600   | \_650   | \_700   | \_750   | \_800   | \_850   | \_900   | \_950   | \_1000  |
| --------------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- |
| `proGray`       | #ffffff | #f5f5f5 | #e9e9e9 | #dddddd | #cfcfcf | #c0c0c0 | #b1b1b1 | #a1a1a1 | #909091 | #818182 | #717272 | #626262 | #535353 | #454545 | #383838 | #2c2c2c | #212121 | #171718 | #0d0d0d | #000001 |
| `proPink`       | #fef2f5 | #fde3ea | #fcd4e0 | #fbc4d5 | #fab3c9 | #f9a1be | #f88eb2 | #ea82a6 | #dc769a | #cb6c8d | #ba6381 | #a95975 | #985069 | #88465d | #783d52 | #683446 | #582c3b | #492331 | #3b1b26 | #2d131c |
| `proRuby`       | #fef2f3 | #fee3e6 | #fdd4d9 | #fdc4cb | #fdb3bd | #fca1af | #fc8ea0 | #ed8295 | #df7688 | #ce6c7e | #bd6373 | #ab5968 | #9a505d | #8a4652 | #7a3d48 | #69343e | #592c34 | #4a232a | #3c1b21 | #2e1318 |
| `proRed`        | #fef2f1 | #fee4e2 | #fed5d3 | #fec5c3 | #feb4b1 | #fea2a0 | #fd8f8e | #ef8383 | #e17777 | #cf6d6e | #be6364 | #ad5a5a | #9b5151 | #8b4747 | #7a3e3e | #6a3535 | #5a2c2c | #4b2424 | #3c1c1c | #2e1414 |
| `proTomato`     | #fef2ef | #fee4de | #fed6cd | #fdc6ba | #feb5a6 | #fda492 | #fd917c | #ef8571 | #e07966 | #cf6f5e | #be6555 | #ac5c4d | #9b5245 | #8b483c | #7a3f34 | #6a362c | #5a2d25 | #4b251e | #3c1c16 | #2e140f |
| `proCoral`      | #fef3ee | #fde5db | #fdd7c7 | #fcc8b2 | #fcb79c | #fba684 | #fb946b | #ec8860 | #de7c54 | #cd724d | #bc6846 | #ab5e3f | #9a5438 | #894a31 | #79412a | #693724 | #592e1d | #4a2617 | #3b1d11 | #2e150b |
| `proOrange`     | #fdf3ec | #fce6d8 | #fbd8c2 | #f9c9ab | #f8ba92 | #f7a977 | #f6985a | #e88c4f | #da8043 | #c9753d | #b86b37 | #a86132 | #97572c | #874d26 | #774320 | #67391b | #573015 | #492711 | #3a1e0c | #2d1607 |
| `proBrown`      | #fcf3eb | #fae7d5 | #f8d9be | #f6cca6 | #f4bd8a | #f2ad6d | #f09d4a | #e2913f | #d48431 | #c47a2d | #b36f28 | #a36524 | #935a20 | #83501b | #734616 | #643c12 | #55320e | #46290a | #382007 | #2b1704 |
| `proAmber`      | #fbf4ea | #f8e8d3 | #f4dbbb | #f1cea1 | #eec084 | #ebb164 | #e8a23c | #da9630 | #cc891f | #bc7e1d | #ad7319 | #9d6817 | #8d5e14 | #7e530f | #6f480d | #603e09 | #513407 | #442b05 | #362103 | #291802 |
| `proGold`       | #faf4ea | #f5e9d2 | #f0ddb9 | #ebd09e | #e7c380 | #e2b55f | #dea732 | #d09b24 | #c38e0e | #b4830e | #a5780a | #956d09 | #866108 | #785605 | #694b04 | #5b4103 | #4d3602 | #402d02 | #332301 | #271901 |
| `proMustard`    | #f9f5ea | #f2ead2 | #ebdfb8 | #e5d39d | #dec77f | #d8ba5d | #d2ac2e | #c5a01f | #b7940d | #a9880b | #9b7c09 | #8d7108 | #7e6506 | #705a05 | #634f04 | #554303 | #483902 | #3c2f01 | #2f2401 | #241b01 |
| `proYellow`     | #f7f5ea | #eeebd2 | #e6e0b9 | #ded59e | #d5ca80 | #cdbe5e | #c5b232 | #b8a524 | #ab990d | #9e8d0d | #908009 | #837509 | #766908 | #695d05 | #5c5104 | #4f4603 | #433b02 | #373002 | #2c2601 | #211c01 |
| `proOlive`      | #f5f6ea | #ebecd3 | #e0e2bb | #d6d8a1 | #cbcd83 | #c0c263 | #b6b73b | #aaaa2f | #9d9d1f | #91911c | #858518 | #787816 | #6c6c13 | #60600f | #54540c | #484809 | #3d3d07 | #323205 | #272703 | #1d1d02 |
| `proChartreuse` | #f4f6eb | #e7edd5 | #dbe4bd | #cedaa5 | #c1d089 | #b3c56c | #a6bb49 | #9baf3d | #8ea230 | #83952c | #788827 | #6c7c23 | #616f1f | #56631a | #4b5616 | #414a12 | #363f0d | #2d340a | #232907 | #191e04 |
| `proLime`       | #f2f7ec | #e3eed7 | #d5e5c1 | #c6dcaa | #b6d391 | #a6c976 | #95bf58 | #8ab24d | #7ea541 | #74983c | #6a8b36 | #607e30 | #56712b | #4c6525 | #42591f | #394c1a | #2f4015 | #273510 | #1e2a0b | #151f07 |
| `proGrass`      | #f0f7ee | #e0efda | #cfe6c6 | #bedeb1 | #abd59a | #98cb82 | #84c269 | #78b55e | #6da852 | #649b4c | #5b8e44 | #52813e | #497437 | #416730 | #385a29 | #304e23 | #28421c | #203616 | #182b10 | #11200a |
| `proGreen`      | #eff7ef | #ddf0de | #cae7cb | #b6dfb9 | #a1d6a4 | #8acd8f | #71c47a | #66b86f | #5aab63 | #539d5b | #4b9053 | #44824b | #3c7543 | #35683b | #2e5c33 | #264f2b | #1f4324 | #19371d | #132b16 | #0c210f |
| `proJade`       | #eef8f1 | #daf0e1 | #c5e8d1 | #b0e0c1 | #97d7af | #7ccf9e | #5ec68b | #52b980 | #45ac74 | #409f6b | #399161 | #348458 | #2e764f | #276946 | #225c3d | #1c5034 | #17432b | #123823 | #0d2c1b | #072113 |
| `proEmerald`    | #edf8f3 | #d8f0e5 | #c2e8d8 | #aae0ca | #8fd8bb | #70cfac | #4ac79d | #3eba92 | #2ead85 | #2b9f7b | #259270 | #228466 | #1e775b | #196a50 | #155d46 | #11503c | #0d4432 | #093829 | #062c20 | #032117 |
| `proMint`       | #ecf8f5 | #d6f0ea | #bfe8de | #a5e0d3 | #88d8c7 | #66cfbb | #37c7af | #27baa3 | #11ad96 | #0e9f8a | #0c927e | #0a8473 | #087767 | #066a5b | #055d50 | #035045 | #02433a | #02382f | #022c25 | #01211b |
| `proTeal`       | #ebf8f7 | #d5f0ee | #bde8e5 | #a3e0dc | #84d8d3 | #60cfc9 | #26c6c0 | #13b9b3 | #11aba6 | #0e9e99 | #0c908c | #0a837f | #087672 | #066965 | #055c59 | #034f4d | #024341 | #023735 | #012c2a | #01211f |
| `proTurquoise`  | #ebf8f9 | #d4f0f2 | #bce8eb | #a1dfe4 | #82d7de | #5dced7 | #1ec4d1 | #13b7c3 | #11a9b4 | #0e9ca6 | #0c8f98 | #0a828a | #08747c | #06686e | #055b61 | #034e54 | #024247 | #02373b | #012b2f | #012023 |
| `proCyan`       | #ebf7fa | #d4eff6 | #bce7f1 | #a2deec | #83d5e8 | #5fcce4 | #24c2e0 | #13b5d2 | #11a8c3 | #0e9ab3 | #0c8da4 | #0a8095 | #087386 | #066678 | #055a69 | #034d5b | #02414d | #023640 | #012b33 | #012027 |
| `proCerulean`   | #ecf7fc | #d5eff9 | #bee6f6 | #a5ddf4 | #87d3f2 | #65c9f0 | #35bfee | #25b2e0 | #10a5d2 | #0e98c2 | #0c8bb1 | #0a7ea1 | #087291 | #066581 | #055972 | #034c63 | #024054 | #023546 | #012a38 | #011f2a |
| `proSky`        | #ecf7fd | #d7eefc | #c1e5fb | #a9dbfa | #8dd1fa | #6ec6fa | #48bcfa | #3bafec | #2ba2de | #2895cd | #2388bc | #1f7cab | #1c6f9a | #176389 | #135779 | #0f4b69 | #0b3f59 | #08344a | #06293b | #031e2e |
| `proAzure`      | #edf6fe | #d9edfe | #c4e3fe | #afd9fe | #98cefe | #7fc3fe | #64b7fd | #4fabf6 | #439ee8 | #3d92d6 | #3785c4 | #3279b2 | #2c6ca0 | #26608f | #20547e | #1b496d | #153d5d | #11324e | #0c283e | #071d30 |
| `proBlue`       | #eff6ff | #ddecff | #cbe1fe | #b8d7fe | #a4cbfe | #8fc0fe | #7ab4fd | #63a7fd | #579aef | #508edc | #4882ca | #4176b8 | #3a69a5 | #335e94 | #2c5282 | #254771 | #1e3b60 | #183150 | #122640 | #0b1c32 |
| `proCobalt`     | #f0f5ff | #e0ebff | #d0e0fe | #bfd5fe | #aec9fe | #9cbcfe | #8ab0fd | #77a3fd | #6996f3 | #618ae0 | #587ece | #4f72bb | #4766a9 | #3e5b97 | #365085 | #2e4473 | #263962 | #1f2f52 | #172542 | #101b33 |
| `proIndigo`     | #f2f5ff | #e3eaff | #d5defe | #c6d3fe | #b6c6fe | #a7b9fe | #98acfd | #889ffd | #7a91f5 | #7086e2 | #667acf | #5d6fbd | #5363aa | #495898 | #404d86 | #374274 | #2e3763 | #252e53 | #1d2442 | #141a33 |
| `proIris`       | #f3f4ff | #e6e9ff | #d9ddfe | #ccd1fe | #bfc4fe | #b1b6fe | #a4a9fd | #979afd | #8a8df4 | #7f82e1 | #7476ce | #696bbc | #5e60a9 | #535597 | #494b85 | #3f4074 | #343662 | #2b2c52 | #212242 | #181933 |
| `proViolet`     | #f5f4ff | #eae8ff | #dedbfe | #d3cefe | #c7c1fe | #bcb3fe | #b0a4fd | #a595fd | #9988f0 | #8d7edd | #8173cb | #7568b9 | #695da6 | #5d5295 | #514883 | #463e72 | #3b3461 | #302a51 | #262141 | #1c1832 |
| `proGrape`      | #f6f3ff | #ede6ff | #e4d9fe | #daccfe | #d1bdfe | #c7aefe | #be9ffd | #b391f8 | #a684ea | #997ad7 | #8c6fc6 | #7f65b4 | #725aa2 | #665091 | #59467f | #4d3c6e | #41325e | #35294e | #2a203f | #201730 |
| `proPurple`     | #f8f3fe | #f1e5fd | #e9d8fc | #e2c9fb | #dbbafb | #d3aafc | #cc99fd | #c08def | #b381e1 | #a577cf | #976cbe | #8962ad | #7b589b | #6e4d8b | #60447a | #533a6a | #46305a | #3a284b | #2e1f3c | #23162e |
| `proOrchid`     | #f9f2fc | #f4e5fa | #eed6f7 | #e9c8f5 | #e3b8f4 | #dea7f2 | #d895f1 | #cb8ae3 | #be7dd5 | #af73c5 | #a069b4 | #925fa4 | #835593 | #754b84 | #674274 | #593864 | #4b2f55 | #3e2647 | #311e39 | #25152b |
| `proPlum`       | #fbf2fb | #f7e4f6 | #f3d5f2 | #efc6ee | #ebb6ea | #e6a5e7 | #e392e3 | #d587d6 | #c87bc8 | #b871b9 | #a967a9 | #995d9a | #8a538a | #7b497b | #6c406d | #5d375e | #4f2e4f | #422542 | #341d35 | #281428 |
| `proMagenta`    | #fcf2f9 | #f9e4f3 | #f6d5ec | #f4c5e6 | #f1b4e0 | #eea3da | #ec90d4 | #de84c7 | #d078ba | #c06fab | #b0659d | #a05b8e | #905280 | #804872 | #713f64 | #623656 | #532d49 | #45243d | #371c30 | #2a1424 |
| `proRose`       | #fdf2f7 | #fbe3ef | #f9d4e6 | #f8c5de | #f6b3d5 | #f4a1cc | #f38ec4 | #e583b7 | #d777aa | #c66d9d | #b5638f | #a55a82 | #945075 | #854768 | #753e5b | #65354f | #562c42 | #472437 | #391b2b | #2c1320 |

## How it works

How a token comes to be, for `proOrange.foregroundSecondary`:

1. Hue: `proOrange` sits at 50° of 36 hues.
2. Ramp: 20 stops, from `_50` to `_1000`.
3. Stops: `_800` (#67391b) and `_200` (#f9c9ab), each a fixed color, in Display P3 hex.
4. Job: `foregroundSecondary` picks `_800` in light mode and `_200` in dark.
5. Your app: secondary text, in both modes.

Every hue becomes a ramp of 20 stops, and all 36 hues share one lightness at each stop. A token names a job, like secondary text, and picks one stop for light mode and one for dark. Your views use tokens, so they follow dark mode and any theme on their own. [What are tokens?](https://colortokenskit.com/basics/what-are-tokens/index.md) walks through it.

## What you get

### A palette of well-defined colors

We give you 37 families of 20 stops, the 740 colors at the top of this page. Every hue has the same lightness at each stop, so `_600` means the same contrast in red as in blue. Many colors reach past sRGB into [Display P3](https://colortokenskit.com/reference/glossary/index.md#display-p3), the wider range of color an iPhone screen shows, and any hue you like, such as your brand's, can become a family of its own. [What does the library offer?](https://colortokenskit.com/basics/color-library/index.md) shows every stop.

### Automatic dark mode

```swift
let brand = ProTheme(hex: "#00B386")

HStack {
    VStack(alignment: .leading, spacing: 4) {
        Text("LIS → KIX")
            .font(.headline)
            .foregroundStyle(brand.foregroundPrimary)     // _1000 in light mode, _50 in dark
        Text("Oct 12 · 14h 20m")
            .font(.subheadline)
            .foregroundStyle(brand.foregroundSecondary)   // _800 in light mode, _200 in dark
    }
    Spacer()
    Text("€620")
        .foregroundStyle(brand.foregroundPrimary)
}
.padding()
.background(brand.backgroundPrimary)                      // _50 in light mode, _1000 in dark
```

What this draws, with `#00B386`:

| Color                 | light mode                             | dark mode                             |
| --------------------- | -------------------------------------- | ------------------------------------- |
| `backgroundPrimary`   | #eaf8f2                                | color(display-p3 0.0176 0.1298 0.086) |
| `foregroundPrimary`   | color(display-p3 0.0176 0.1298 0.086)  | #eaf8f2                               |
| `foregroundSecondary` | color(display-p3 0.0797 0.3134 0.2262) | #9ce2c5                               |

A token names the job a color does and picks a stop for each mode. We give you 20 of them, tested in production, so you never write a dark-mode color by hand. [What are tokens?](https://colortokenskit.com/basics/what-are-tokens/index.md) explains how they work.

### Built-in theming

```swift
struct TripCard: View {
    let city: String
    let price: String
    let theme: ProTheme

    var body: some View {
        HStack(spacing: 12) {
            Image(systemName: "airplane")
                .foregroundStyle(theme.foregroundSecondary)
                .frame(width: 44, height: 44)
                .background(theme.backgroundTertiary, in: .rect(cornerRadius: 12))
            VStack(alignment: .leading, spacing: 2) {
                Text(city)
                    .font(.headline)
                    .foregroundStyle(theme.foregroundPrimary)
                Text("3 nights from October 12")
                    .font(.subheadline)
                    .foregroundStyle(theme.foregroundSecondary)
            }
            Spacer()
            Text(price)
                .font(.subheadline.weight(.semibold))
                .foregroundStyle(theme.foregroundPrimary)
                .padding(.horizontal, 10)
                .padding(.vertical, 4)
                .background(theme.backgroundPrimary, in: .capsule)
            Image(systemName: "chevron.right")
                .foregroundStyle(theme.foregroundTertiary)
        }
        .padding(12)
        .background(theme.backgroundSecondary, in: .rect(cornerRadius: 16))
    }
}

VStack(spacing: 10) {
    TripCard(city: "Lisbon", price: "€420", theme: Color.proOrange)
    TripCard(city: "Kyoto", price: "€980", theme: Color.proPink)
    TripCard(city: "Reykjavík", price: "€640", theme: Color.proSky)
}
```

What this draws:

| Color                        | light mode                             | dark mode                              |
| ---------------------------- | -------------------------------------- | -------------------------------------- |
| `orange.backgroundSecondary` | color(display-p3 0.9885 0.9007 0.8455) | #6e3612                                |
| `orange.backgroundTertiary`  | color(display-p3 0.978 0.79 0.6716)    | #90491a                                |
| `orange.foregroundSecondary` | #6e3612                                | color(display-p3 0.978 0.79 0.6716)    |
| `orange.foregroundPrimary`   | #301404                                | color(display-p3 0.9936 0.9528 0.9271) |
| `orange.backgroundPrimary`   | color(display-p3 0.9936 0.9528 0.9271) | #301404                                |
| `orange.foregroundTertiary`  | #90491a                                | color(display-p3 0.9695 0.664 0.4686)  |
| `pink.backgroundSecondary`   | color(display-p3 0.9918 0.8911 0.9193) | #6f3147                                |
| `pink.backgroundTertiary`    | color(display-p3 0.9839 0.7697 0.8336) | #92425e                                |
| `pink.foregroundSecondary`   | #6f3147                                | color(display-p3 0.9839 0.7697 0.8336) |
| `pink.foregroundPrimary`     | #31111c                                | color(display-p3 0.9953 0.9483 0.9611) |
| `pink.backgroundPrimary`     | color(display-p3 0.9953 0.9483 0.9611) | #31111c                                |
| `pink.foregroundTertiary`    | #92425e                                | color(display-p3 0.9767 0.6309 0.7435) |
| `sky.backgroundSecondary`    | #d1effe                                | color(display-p3 0.0596 0.2924 0.4106) |
| `sky.backgroundTertiary`     | #9addfd                                | color(display-p3 0.0889 0.3874 0.5384) |
| `sky.foregroundSecondary`    | color(display-p3 0.0596 0.2924 0.4106) | #9addfd                                |
| `sky.foregroundPrimary`      | color(display-p3 0.0119 0.1193 0.1786) | #eaf7fe                                |
| `sky.backgroundPrimary`      | #eaf7fe                                | color(display-p3 0.0119 0.1193 0.1786) |
| `sky.foregroundTertiary`     | color(display-p3 0.0889 0.3874 0.5384) | #48c9ff                                |

Every family has the same tokens at the same contrast, so a view that takes a theme can wear any of them, in one line. [Setting up themes](https://colortokenskit.com/advanced/themes/index.md) shows how far that goes.

### Accessibility from day one

Before: SwiftUI's system colors:

- Color.red, 3.57:1: #ff383c
- Color.green, 2.22:1: #34c759
- Color.blue, 3.52:1: #0088ff

After: ColorTokensKit, stop \_600:

- proRed.\_600, 4.68:1: #ad5a5a
- proGreen.\_600, 4.68:1: #44824b
- proBlue.\_600, 4.68:1: #4176b8

SwiftUI's system colors are tuned one at a time, so as text on white, none of the three above reaches the 4.5:1 that WCAG AA asks for body text. Ours share one lightness at each stop, so `_600` passes in every hue. Every text token passes AA on the page background, in both modes, and for stops you pick yourself, 12 stops apart always reaches 4.5:1. [How accessible is it?](https://colortokenskit.com/basics/how-accessible/index.md) lists what's guaranteed, and [why use ColorTokensKit over native colors?](https://colortokenskit.com/basics/why-colortokenskit/index.md) compares the two in full.

### Functions for interaction states

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

HStack {
    Text("Book now").padding(12).background(fill)
    Text("Book now").padding(12).background(fill.darken(by: 2))       // pressed: _750 in light mode, _350 in dark
    Text("Sold out").padding(12).background(fill.desaturate(by: 1))   // disabled: gray at the same lightness
}
.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                                |
| `_750/_350`                  | color(display-p3 0.0977 0.3637 0.2645) | color(display-p3 0.3144 0.7788 0.5953) |
| `#686868/#C8C8C8`            | #686868                                | #c8c8c8                                |

Hover, pressed and disabled colors come from the color you already have, so you don't pick a new color for each state, and "Sold out" keeps the button's contrast. [Building for interaction states](https://colortokenskit.com/getting-started/interaction-states/index.md) shows every state, and [`darken(by:)`](https://colortokenskit.com/api/darken/index.md) and [`desaturate(by:)`](https://colortokenskit.com/api/desaturate/index.md) have the details.

## Next steps

- [What are tokens?](https://colortokenskit.com/basics/what-are-tokens/index.md): Colors picked one at a time never line up. Tokens name each job and pick its color in both modes.
- [Installing ColorTokensKit](https://colortokenskit.com/getting-started/installing/index.md): Add one package and one file of tokens, and every view gets the palette and dark mode.
- [Using your first tokens](https://colortokenskit.com/getting-started/first-tokens/index.md): Color text, buttons, cards and lists with tokens, then theme a movie card in one line.
- [Components and examples](https://colortokenskit.com/getting-started/components/index.md): Copy the common mobile components, from buttons to paywalls, each built from tokens for both modes.

---

From ColorTokensKit, by Penguin Design Ventures: https://colortokenskit.com/
