diff --git a/components/src/components/atoms/Avatar/Avatar.tsx b/components/src/components/atoms/Avatar/Avatar.tsx index ecd01927..1ac963b8 100644 --- a/components/src/components/atoms/Avatar/Avatar.tsx +++ b/components/src/components/atoms/Avatar/Avatar.tsx @@ -2,7 +2,7 @@ import * as React from 'react' import { rainbowSprinkles } from '@/src/css/rainbow-spinkles.css' -import { rawColorToRGBA } from '@/src/tokens/color3' +import { rawColorToRGBA } from '@/src/tokens/color' import { Box, type BoxProps } from '../Box/Box' import { avatar } from './styles.css' diff --git a/components/src/components/atoms/Button/utils/getValidatedColor.ts b/components/src/components/atoms/Button/utils/getValidatedColor.ts index 3d189778..9ba7b006 100644 --- a/components/src/components/atoms/Button/utils/getValidatedColor.ts +++ b/components/src/components/atoms/Button/utils/getValidatedColor.ts @@ -1,7 +1,7 @@ -import type { PrimaryColor } from '@/src/tokens/color3' -import { validatePrimaryColor } from '@/src/tokens/color3' +import type { Hue } from '@/src/tokens/color' +import { validatePrimaryColor } from '@/src/tokens/color' -export type Color = PrimaryColor +export type Color = Hue export type WithColor = { color: Color } diff --git a/components/src/components/atoms/Button/utils/withColorStyle.ts b/components/src/components/atoms/Button/utils/withColorStyle.ts index df1f0f0a..fc2b4210 100644 --- a/components/src/components/atoms/Button/utils/withColorStyle.ts +++ b/components/src/components/atoms/Button/utils/withColorStyle.ts @@ -1,13 +1,13 @@ import { P, match } from 'ts-pattern' -import type { PrimaryColor } from '@/src/tokens/color3' -import { validatePrimaryColor } from '@/src/tokens/color3' +import type { Hue } from '@/src/tokens/color' +import { validatePrimaryColor } from '@/src/tokens/color' type Shade = 'Primary' | 'Secondary' export type ColorStyle = - | PrimaryColor - | `${PrimaryColor}${Shade}` + | Hue + | `${Hue}${Shade}` | 'background' | 'disabled' | 'transparent' @@ -23,14 +23,14 @@ type Properties = { type Property = keyof Properties -const getPrimaryColor = (color: PrimaryColor, property: Property): string => +const getPrimaryColor = (color: Hue, property: Property): string => match(property) .with(P.union('background', 'border'), () => `$${color}Primary`) .with('content', () => '$textAccent') .with('hover', () => `$${color}Bright`) .exhaustive() -const getSecondaryColor = (color: PrimaryColor, property: Property): string => +const getSecondaryColor = (color: Hue, property: Property): string => match(property) .with(P.union('background', 'border'), () => `$${color}Surface`) .with('content', () => `$${color}Dim`) diff --git a/components/src/components/atoms/Heading/Heading.tsx b/components/src/components/atoms/Heading/Heading.tsx index dfbb01f8..8b3048d5 100644 --- a/components/src/components/atoms/Heading/Heading.tsx +++ b/components/src/components/atoms/Heading/Heading.tsx @@ -1,6 +1,6 @@ import * as React from 'react' -import type { WithColor } from '@/src/types/withColorOrColorStyle' +import type { WithColor } from '@/src/interfaces/withColor' import type { BoxProps } from '../Box/Box' import { Box } from '../Box/Box' diff --git a/components/src/components/atoms/Tag/utils/withColorStyle.ts b/components/src/components/atoms/Tag/utils/withColorStyle.ts index 3398cb9b..bec8d730 100644 --- a/components/src/components/atoms/Tag/utils/withColorStyle.ts +++ b/components/src/components/atoms/Tag/utils/withColorStyle.ts @@ -1,11 +1,11 @@ import { P, match } from 'ts-pattern' -import type { PrimaryColor } from '@/src/tokens/color3' -import { validatePrimaryColor } from '@/src/tokens/color3' +import type { Hue } from '@/src/tokens/color' +import { validatePrimaryColor } from '@/src/tokens/color' type Shade = 'Primary' | 'Secondary' -type ColorStyle = PrimaryColor | `${PrimaryColor}${Shade}` +type ColorStyle = Hue | `${Hue}${Shade}` export type WithColorStyle = { colorStyle?: ColorStyle } @@ -17,14 +17,14 @@ type Properties = { type Property = keyof Properties -const getPrimaryColor = (color: PrimaryColor, property: Property): string => +const getPrimaryColor = (color: Hue, property: Property): string => match(property) .with('background', () => `$${color}Primary`) .with('content', () => '$textAccent') .with('hover', () => `$${color}Bright`) .exhaustive() -const getSecondaryColor = (color: PrimaryColor, property: Property): string => +const getSecondaryColor = (color: Hue, property: Property): string => match(property) .with('background', () => `$${color}Surface`) .with('content', () => `$${color}Primary`) diff --git a/components/src/components/molecules/Checkbox/utils/getValueForColorStyle.ts b/components/src/components/molecules/Checkbox/utils/getValueForColorStyle.ts index 40655bf9..ebc1a355 100644 --- a/components/src/components/molecules/Checkbox/utils/getValueForColorStyle.ts +++ b/components/src/components/molecules/Checkbox/utils/getValueForColorStyle.ts @@ -1,11 +1,11 @@ import { P, match } from 'ts-pattern' -import type { PrimaryColor } from '@/src/tokens/color3' -import { validatePrimaryColor } from '@/src/tokens/color3' +import type { Hue } from '@/src/tokens/color' +import { validatePrimaryColor } from '@/src/tokens/color' type Shade = 'Primary' | 'Secondary' -type ColorStyle = PrimaryColor | `${PrimaryColor}${Shade}` +type ColorStyle = Hue | `${Hue}${Shade}` export type WithColorStyle = { colorStyle?: ColorStyle } @@ -16,13 +16,13 @@ type Properties = { type Property = keyof Properties -const getPrimaryColor = (color: PrimaryColor, property: Property): string => +const getPrimaryColor = (color: Hue, property: Property): string => match(property) .with('background', () => `$${color}Primary`) .with('content', () => '$textAccent') .exhaustive() -const getSecondaryColor = (color: PrimaryColor, property: Property): string => +const getSecondaryColor = (color: Hue, property: Property): string => match(property) .with(P.union('background'), () => `$${color}Surface`) .with('content', () => `$${color}Primary`) diff --git a/components/src/components/molecules/CheckboxRow/utils/getValueForColorStyle.ts b/components/src/components/molecules/CheckboxRow/utils/getValueForColorStyle.ts index adcadd6e..924d7696 100644 --- a/components/src/components/molecules/CheckboxRow/utils/getValueForColorStyle.ts +++ b/components/src/components/molecules/CheckboxRow/utils/getValueForColorStyle.ts @@ -1,11 +1,11 @@ import { P, match } from 'ts-pattern' -import type { PrimaryColor } from '@/src/tokens/color3' -import { validatePrimaryColor } from '@/src/tokens/color3' +import type { Hue } from '@/src/tokens/color' +import { validatePrimaryColor } from '@/src/tokens/color' type Shade = 'Primary' | 'Secondary' -export type ColorStyle = PrimaryColor | `${PrimaryColor}${Shade}` +export type ColorStyle = Hue | `${Hue}${Shade}` export type WithColorStyle = { colorStyle: ColorStyle } @@ -18,7 +18,7 @@ type Properties = { type Property = keyof Properties -const getPrimaryColor = (color: PrimaryColor, property: Property): string => +const getPrimaryColor = (color: Hue, property: Property): string => match(property) .with('background', () => `$${color}Surface`) .with('svg', () => '$textAccent') @@ -26,7 +26,7 @@ const getPrimaryColor = (color: PrimaryColor, property: Property): string => .with('iconHover', () => `$${color}Bright`) .exhaustive() -const getSecondaryColor = (color: PrimaryColor, property: Property): string => +const getSecondaryColor = (color: Hue, property: Property): string => match(property) .with('background', () => `$${color}Surface`) .with('svg', () => `$${color}Dim`) diff --git a/components/src/components/molecules/CountdownCircle/utils/getValidatedColor.ts b/components/src/components/molecules/CountdownCircle/utils/getValidatedColor.ts index fcb0b4c2..861e5038 100644 --- a/components/src/components/molecules/CountdownCircle/utils/getValidatedColor.ts +++ b/components/src/components/molecules/CountdownCircle/utils/getValidatedColor.ts @@ -1,7 +1,7 @@ -import type { PrimaryColor } from '@/src/tokens/color3' -import { validatePrimaryColor } from '@/src/tokens/color3' +import type { Hue } from '@/src/tokens/color' +import { validatePrimaryColor } from '@/src/tokens/color' -export type Color = PrimaryColor +export type Color = Hue export type WithColor = { color: Color } diff --git a/components/src/components/molecules/CurrencyToggle/utils/getValidatedColor.ts b/components/src/components/molecules/CurrencyToggle/utils/getValidatedColor.ts index 0be8a6f1..fd282001 100644 --- a/components/src/components/molecules/CurrencyToggle/utils/getValidatedColor.ts +++ b/components/src/components/molecules/CurrencyToggle/utils/getValidatedColor.ts @@ -1,7 +1,7 @@ -import type { PrimaryColor } from '@/src/tokens/color3' -import { validatePrimaryColor } from '@/src/tokens/color3' +import type { Hue } from '@/src/tokens/color' +import { validatePrimaryColor } from '@/src/tokens/color' -export type Color = PrimaryColor +export type Color = Hue export type WithColor = { color: Color } diff --git a/components/src/components/molecules/RadioButton/utils/getValidatedColor.ts b/components/src/components/molecules/RadioButton/utils/getValidatedColor.ts index 0be8a6f1..fd282001 100644 --- a/components/src/components/molecules/RadioButton/utils/getValidatedColor.ts +++ b/components/src/components/molecules/RadioButton/utils/getValidatedColor.ts @@ -1,7 +1,7 @@ -import type { PrimaryColor } from '@/src/tokens/color3' -import { validatePrimaryColor } from '@/src/tokens/color3' +import type { Hue } from '@/src/tokens/color' +import { validatePrimaryColor } from '@/src/tokens/color' -export type Color = PrimaryColor +export type Color = Hue export type WithColor = { color: Color } diff --git a/components/src/components/molecules/ThemeToggle/utils/getValidatedColor.ts b/components/src/components/molecules/ThemeToggle/utils/getValidatedColor.ts index 0be8a6f1..fd282001 100644 --- a/components/src/components/molecules/ThemeToggle/utils/getValidatedColor.ts +++ b/components/src/components/molecules/ThemeToggle/utils/getValidatedColor.ts @@ -1,7 +1,7 @@ -import type { PrimaryColor } from '@/src/tokens/color3' -import { validatePrimaryColor } from '@/src/tokens/color3' +import type { Hue } from '@/src/tokens/color' +import { validatePrimaryColor } from '@/src/tokens/color' -export type Color = PrimaryColor +export type Color = Hue export type WithColor = { color: Color } diff --git a/components/src/components/molecules/Toggle/utils/getValidatedColor.ts b/components/src/components/molecules/Toggle/utils/getValidatedColor.ts index 0be8a6f1..fd282001 100644 --- a/components/src/components/molecules/Toggle/utils/getValidatedColor.ts +++ b/components/src/components/molecules/Toggle/utils/getValidatedColor.ts @@ -1,7 +1,7 @@ -import type { PrimaryColor } from '@/src/tokens/color3' -import { validatePrimaryColor } from '@/src/tokens/color3' +import type { Hue } from '@/src/tokens/color' +import { validatePrimaryColor } from '@/src/tokens/color' -export type Color = PrimaryColor +export type Color = Hue export type WithColor = { color: Color } diff --git a/components/src/css/theme.css.ts b/components/src/css/theme.css.ts index 83bbcce2..9090014e 100644 --- a/components/src/css/theme.css.ts +++ b/components/src/css/theme.css.ts @@ -3,7 +3,7 @@ import { createGlobalThemeContract, } from '@vanilla-extract/css' -import { darkColors, lightColors } from '../tokens/color3' +import { darkColors, lightColors } from '../tokens/color' import { borderStyles, borderWidths, radii } from '../tokens/border' import { space } from '../tokens/space' import { diff --git a/components/src/index.ts b/components/src/index.ts index 74b08544..f27dac72 100644 --- a/components/src/index.ts +++ b/components/src/index.ts @@ -6,4 +6,4 @@ export { tokens, baseTheme, lightTheme, darkTheme } from './tokens' export type { DefaultTheme, EmptyObject, Accent, Mode, ReactNodeNoStrings } from './types' export type { Hue, Colors, Space } from './tokens' export * from './css/theme.css' -export * from './tokens/color3' +export * from './tokens/color' diff --git a/components/src/interfaces/withColor.ts b/components/src/interfaces/withColor.ts index 0ed06ab7..388ebee7 100644 --- a/components/src/interfaces/withColor.ts +++ b/components/src/interfaces/withColor.ts @@ -1,14 +1,14 @@ import type { AdditionalColor, PaletteColor, - PrimaryColor } from '@/src/tokens/color3' + Hue } from '@/src/tokens/color' import { ADDITIONAL_COLORS, PALETTE_COLORS, PRIMARY_COLORS, -} from '@/src/tokens/color3' +} from '@/src/tokens/color' -export type Color = PrimaryColor | PaletteColor | AdditionalColor +export type Color = Hue | PaletteColor | AdditionalColor export type WithColor = { color?: Color } diff --git a/components/src/interfaces/withColourStyle.ts b/components/src/interfaces/withColourStyle.ts index b4ad4b56..834772cc 100644 --- a/components/src/interfaces/withColourStyle.ts +++ b/components/src/interfaces/withColourStyle.ts @@ -1,13 +1,13 @@ import { P, match } from 'ts-pattern' -import type { Color, PrimaryColor } from '../tokens/color3' -import { validatePrimaryColor } from '../tokens/color3' +import type { Color, Hue } from '../tokens/color' +import { validatePrimaryColor } from '../tokens/color' type Shade = 'Primary' | 'Secondary' type ColourStyle = - | PrimaryColor - | `${PrimaryColor}${Shade}` + | Hue + | `${Hue}${Shade}` | 'background' | 'disabled' @@ -22,14 +22,14 @@ type Properties = { type Property = keyof Properties -const getPrimaryColor = (colour: PrimaryColor, property: Property): Color => +const getPrimaryColor = (colour: Hue, property: Property): Color => match(property) .with(P.union('background', 'border'), () => `${colour}Primary` as const) .with('content', () => 'textAccent' as const) .with('hover', () => `${colour}Bright` as const) .exhaustive() -const getSecondaryColor = (colour: PrimaryColor, property: Property): Color => +const getSecondaryColor = (colour: Hue, property: Property): Color => match(property) .with(P.union('background', 'border'), () => `${colour}Surface` as const) .with('content', () => `${colour}Dim` as const) diff --git a/components/src/tokens/color.ts b/components/src/tokens/color.ts index e1dbe4e8..38573716 100644 --- a/components/src/tokens/color.ts +++ b/components/src/tokens/color.ts @@ -1,274 +1,416 @@ -/** - * Color Variables - * - * All the following variables are used to generate color tokens. - * Changes made to these variables will be reflected throughout the library. - */ - -// The Mode type contains all possible theme modes. +/** PRIMARY COLORS */ + export type Mode = 'light' | 'dark' -const shades = [50, 100, 300, 400, 500, 750] as const +export type Hue = + | 'accent' + | 'blue' + | 'green' + | 'yellow' + | 'red' + | 'orange' + | 'indigo' + | 'pink' + | 'purple' + | 'grey' + +export type RawColor = Readonly<[number, number, number]> -const namedShadeMap = { - Surface: 50, - Light: 100, - Bright: 300, - Primary: 400, - Dim: 500, - Active: 750, +const RAW_PRIMARY_COLORS: { [key in Hue]: RawColor } = { + accent: [56, 137, 255], + blue: [56, 137, 255], + green: [25, 156, 117], + yellow: [233, 185, 17], + red: [198, 48, 27], + orange: [243, 147, 11], + indigo: [88, 84, 214], + pink: [213, 46, 126], + purple: [163, 67, 211], + grey: [155, 155, 167], } as const -// The hues object is a map of HSL colors, with optional overrides for each shade. -const hues = { - blue: [216, 100, 61, { 50: [215, 100, 97] }], - indigo: [242, 61, 58], - purple: [280, 62, 55], - pink: [331, 67, 51, { 100: [331, 64, 88] }], - red: [7, 76, 44, { 50: [0, 60, 94], 100: [360, 60, 85] }], - orange: [35, 91, 50, { 100: [36, 89, 86] }], - yellow: [47, 86, 49, { 50: [48, 100, 90], 100: [48, 100, 85] }], - green: [162, 72, 40, { 50: [157, 37, 93], 100: [157, 37, 85] }], - teal: [199, 66, 49], - grey: [ - 240, - 6, - 63, - { - 50: [0, 0, 96], - 100: [0, 0, 91], - 500: [0, 0, 35], - 750: [0, 0, 15], - }, - ], -} satisfies Record +export const PRIMARY_COLORS = Object.keys(RAW_PRIMARY_COLORS) as Hue[] -const backgroundColor = { - light: '0 0% 100%', - dark: '0 0% 8%', +export const validatePrimaryColor = ( + colour: unknown, + fallback: Hue = 'accent', +): Hue => { + return PRIMARY_COLORS.includes(colour as Hue) + ? (colour as Hue) + : fallback } -// The categories object is a map of categorised colors, which can each have their own custom values. -const categories = { - background: { - hue: 'grey', - items: { - primary: backgroundColor, - secondary: 'Surface', - }, +/** PALETTE COLOR */ + +export type Shade = + | 'active' + | 'dim' + | 'primary' + | 'bright' + | 'light' + | 'surface' + +export type Shades = { [key in Shade]: RawColor } + +export type Palette = { [key in Hue]: Shades } + +export const RAW_PALETTE_LIGHT: Palette = { + accent: { + active: [0, 54, 133], + dim: [5, 106, 255], + primary: RAW_PRIMARY_COLORS.blue, + bright: [86, 154, 255], + light: [209, 228, 255], + surface: [238, 245, 255], }, - text: { - hue: 'grey', - items: { - primary: 'Active', - secondary: 'Dim', - tertiary: 'Primary', - accent: { - light: backgroundColor.light, - dark: backgroundColor.light, - }, - }, + blue: { + active: [0, 54, 133], + dim: [5, 106, 255], + primary: RAW_PRIMARY_COLORS.blue, + bright: [86, 154, 255], + light: [209, 228, 255], + surface: [238, 245, 255], }, - border: { - hue: 'grey', - items: { - primary: 'Light', - }, + green: { + active: [7, 44, 33], + dim: [21, 132, 99], + primary: RAW_PRIMARY_COLORS.green, + bright: [30, 183, 137], + light: [203, 231, 220], + surface: [231, 244, 239], + }, + yellow: { + active: [66, 53, 5], + dim: [185, 147, 14], + primary: RAW_PRIMARY_COLORS.yellow, + bright: [240, 201, 60], + light: [255, 239, 173], + surface: [255, 245, 205], + }, + red: { + active: [40, 10, 6], + dim: [153, 37, 21], + primary: RAW_PRIMARY_COLORS.red, + bright: [227, 70, 49], + light: [240, 194, 194], + surface: [249, 231, 231], + }, + orange: { + active: [73, 44, 3], + dim: [195, 118, 9], + primary: RAW_PRIMARY_COLORS.orange, + bright: [246, 169, 60], + light: [251, 225, 188], + surface: [253, 240, 221], + }, + indigo: { + active: [25, 23, 95], + dim: [52, 47, 197], + primary: RAW_PRIMARY_COLORS.indigo, + bright: [126, 123, 223], + light: [199, 197, 241], + surface: [227, 226, 248], + }, + pink: { + active: [68, 14, 40], + dim: [174, 35, 102], + primary: RAW_PRIMARY_COLORS.pink, + bright: [222, 89, 153], + light: [244, 205, 224], + surface: [250, 232, 241], + }, + purple: { + active: [61, 19, 83], + dim: [138, 43, 186], + primary: RAW_PRIMARY_COLORS.purple, + bright: [184, 110, 221], + light: [227, 198, 241], + surface: [235, 214, 245], + }, + grey: { + active: [30, 33, 34], + dim: [89, 89, 89], + primary: RAW_PRIMARY_COLORS.grey, + bright: [182, 182, 191], + light: [232, 232, 232], + surface: [246, 246, 246], }, -} satisfies Record +} as const -const gradients = { - blue: 'linear-gradient(330.4deg, #44BCF0 4.54%, #7298F8 59.2%, #A099FF 148.85%)', - green: - 'linear-gradient(90deg, rgba(68,240,127,1) 4.54%, rgba(114,248,176,1) 59.2%, rgba(153,202,255,1) 148.85%)', - red: 'linear-gradient(90deg, rgba(240,68,87,1) 4.54%, rgba(248,114,149,1) 59.2%, rgba(212,153,255,1) 148.85%)', - purple: 'linear-gradient(323.31deg, #DE82FF -15.56%, #7F6AFF 108.43%)', - grey: 'linear-gradient(330.4deg, #DFDFDF 4.54%, #959595 59.2%, #474747 148.85%)', +export const RAW_PALETTE_DARK: Palette = { + accent: { + active: [238, 245, 255], + dim: [209, 228, 255], + primary: RAW_PRIMARY_COLORS.blue, + bright: [5, 106, 255], + light: [12, 69, 151], + surface: [13, 40, 81], + }, + blue: { + active: [238, 245, 255], + dim: [209, 228, 255], + primary: RAW_PRIMARY_COLORS.blue, + bright: [5, 106, 255], + light: [12, 69, 151], + surface: [13, 40, 81], + }, + green: { + active: [231, 244, 239], + dim: [203, 231, 220], + primary: RAW_PRIMARY_COLORS.green, + bright: [21, 132, 99], + light: [16, 74, 56], + surface: [21, 60, 49], + }, + yellow: { + active: [255, 245, 205], + dim: [255, 239, 173], + primary: RAW_PRIMARY_COLORS.yellow, + bright: [185, 147, 14], + light: [92, 75, 12], + surface: [55, 50, 34], + }, + red: { + active: [249, 231, 231], + dim: [240, 194, 194], + primary: RAW_PRIMARY_COLORS.red, + bright: [167, 38, 20], + light: [127, 19, 19], + surface: [40, 10, 6], + }, + orange: { + active: [253, 240, 221], + dim: [251, 225, 188], + primary: RAW_PRIMARY_COLORS.orange, + bright: [195, 118, 9], + light: [109, 67, 8], + surface: [88, 53, 3], + }, + indigo: { + active: [227, 226, 248], + dim: [199, 197, 241], + primary: [107, 103, 233], + bright: [52, 47, 197], + light: [34, 30, 144], + surface: [35, 33, 109], + }, + pink: { + active: [250, 232, 241], + dim: [244, 205, 224], + primary: RAW_PRIMARY_COLORS.pink, + bright: [174, 35, 102], + light: [118, 21, 68], + surface: [91, 17, 53], + }, + purple: { + active: [235, 214, 245], + dim: [227, 198, 241], + primary: RAW_PRIMARY_COLORS.purple, + bright: [138, 43, 186], + light: [94, 22, 131], + surface: [66, 20, 90], + }, + grey: { + active: [255, 255, 255], + dim: [232, 232, 232], + primary: RAW_PRIMARY_COLORS.grey, + bright: [93, 92, 98], + light: [66, 67, 71], + surface: [20, 20, 22], + }, +} as const + +export type PaletteColor = `${Hue}${Capitalize}` | Hue + +const flattenPalette = ( + palette: Palette, +): { [key in PaletteColor]: RawColor } => { + const paletteEntries = Object.entries(palette) as [ + Hue, + { [key in Shade]: RawColor }, + ][] + const primaryColorEntries = paletteEntries.map(([primaryColor, shades]) => [ + primaryColor, + shades.primary, + ]) + const paletteColorEntries = paletteEntries.reduce<[PaletteColor, RawColor][]>( + (acc, [primaryColor, shades]) => { + const shadeEntries = Object.entries(shades) as [Shade, RawColor][] + const shadeMap = shadeEntries.map(([shade, rawColor]) => { + const key = `${primaryColor}${shade + .charAt(0) + .toUpperCase()}${shade.slice(1)}` as PaletteColor + return [key, rawColor] as [PaletteColor, RawColor] + }) + return [...acc, ...shadeMap] + }, + [], + ) + return Object.fromEntries([ + ...primaryColorEntries, + ...paletteColorEntries, + ]) as { + [key in PaletteColor]: RawColor + } } -/** - * END COLOR VARIABLES - */ +const RAW_PALETTE_COLORS_LIGHT = flattenPalette(RAW_PALETTE_LIGHT) +const RAW_PALETTE_COLORS_DARK = flattenPalette(RAW_PALETTE_DARK) -export type NamedShade = keyof typeof namedShadeMap -export type Shade = (typeof shades)[number] -export type Hue = keyof typeof hues -export type Category = keyof Categories | 'accent' -export type Gradient = keyof typeof gradients +export const PALETTE_COLORS = Object.keys( + RAW_PALETTE_COLORS_LIGHT, +) as PaletteColor[] -type HSLColor = [hue: number, saturation: number, lightness: number] +export type RawPalettes = { [key in Mode]: Palette } -type HueItem = [ - ...hsl: HSLColor, - overrides?: { - [key in Shade]?: HSLColor - }, -] - -type Categories = typeof categories - -type CamelCaseNested = ( - T extends object - ? { - [K in Exclude]: `${K}${Capitalize< - CamelCaseNested - >}` - }[Exclude] - : '' -) extends infer D - ? Extract - : never - -type DotNestedCategoryKeys = CamelCaseNested<{ - [item in keyof Categories]: { - [key in keyof Categories[item]['items']]: string - } & { - '': string - } -}> -type DotNestedCategories = { [K in DotNestedCategoryKeys]: string } - -type GeneratedCategories = WithRaw - -type CategoryItem = { - hue: Hue - items: { - [key: string]: - | { - [key in Mode]: string - } - | NamedShade - } +export const RAW_PALETTE_COLORS: RawPalettes = { + light: RAW_PALETTE_LIGHT, + dark: RAW_PALETTE_DARK, } -type WithRaw = Omit & { raw: Omit } - -type ShadeColor = { [key in Shade]: string } -type NameColor = { [key in NamedShade]: string } -type ColorItem< - TObject extends Record, - TName extends string, -> = TObject extends object ? { - [key in Exclude as `${TName}${key}`]: string -} & { - [T in `${TName}`]: string +/** ADDITIONAL COLORS */ + +export type AdditionalColor = + | 'black' + | 'white' + | 'text' + | 'textPrimary' + | 'textSecondary' + | 'textAccent' + | 'textDisabled' + | 'background' + | 'backgroundPrimary' + | 'backgroundSecondary' + | 'border' + +const RAW_STATIC_COLORS: { [key in 'black' | 'white']: RawColor } = { + black: [30, 33, 34], + white: [255, 255, 255], } - : never -type CalculatedColors = WithRaw> -type AllColors = WithRaw - -const makeColorObject = ( - mode: Mode, - name: THue, - color: ShadeColor, -) => { - if (mode === 'dark') { - color = Object.fromEntries( - Object.entries(color).map(([key], index, arr) => [ - key, - arr[arr.length - index - 1][1], - ]), - ) as ShadeColor - } - const values = Object.fromEntries( - Object.entries(namedShadeMap).map(([key, value]) => [ - `${name}${key}`, - color[value], - ]), - ) +const RAW_ADDITIONAL_COLORS_LIGHT: { [key in AdditionalColor]: RawColor } = { + black: RAW_STATIC_COLORS.black, + white: RAW_STATIC_COLORS.white, + text: RAW_STATIC_COLORS.black, + textPrimary: RAW_STATIC_COLORS.black, + textSecondary: RAW_PALETTE_LIGHT.grey.dim, + textAccent: RAW_STATIC_COLORS.white, + textDisabled: RAW_PALETTE_LIGHT.grey.bright, + background: RAW_STATIC_COLORS.white, + backgroundPrimary: RAW_STATIC_COLORS.white, + backgroundSecondary: RAW_PALETTE_LIGHT.grey.surface, + border: RAW_PALETTE_LIGHT.grey.light, +} - return { ...values, [name]: values[`${name}Primary`] } as ColorItem< - NameColor, - THue - > +const RAW_ADDITIONAL_COLORS_DARK: { [key in AdditionalColor]: RawColor } = { + black: RAW_STATIC_COLORS.black, + white: RAW_STATIC_COLORS.white, + text: RAW_STATIC_COLORS.white, + textPrimary: RAW_STATIC_COLORS.white, + textSecondary: RAW_PALETTE_DARK.grey.primary, + textAccent: RAW_STATIC_COLORS.white, + textDisabled: RAW_PALETTE_DARK.grey.bright, + background: RAW_STATIC_COLORS.black, + backgroundPrimary: RAW_STATIC_COLORS.black, + backgroundSecondary: RAW_PALETTE_DARK.grey.surface, + border: RAW_PALETTE_DARK.grey.light, } -const makeCSSHSL = (hsl: HSLColor) => `${hsl[0]} ${hsl[1]}% ${hsl[2]}%` - -const makeColorRange = ( - mode: Mode, - name: THue, - hue: HueItem, -) => { - const color = Object.fromEntries( - shades.map((shade) => { - if (hue[3]?.[shade]) { - return [shade, makeCSSHSL(hue[3]![shade]!)] - } - const hsl = hue.slice(0, 3) as HSLColor - hsl[2] = hsl[2] + (400 - shade) / 10 - return [shade, makeCSSHSL(hsl)] - }), - ) as ShadeColor - return { - normal: makeColorObject( - mode, - name, - Object.fromEntries( - Object.entries(color).map(([key, value]) => [key, `hsl(${value})`]), - ) as ShadeColor, - ), - raw: makeColorObject(mode, name, color), - } +export const ADDITIONAL_COLORS = Object.keys( + RAW_ADDITIONAL_COLORS_LIGHT, +) as AdditionalColor[] + +export type RawAdditionalColors = { + [key in Mode]: { [key in AdditionalColor]: RawColor } } -const makeGradients = (accent: unknown, colors: AllColors) => { - return { - ...gradients, - accent: gradients[accent as Gradient] || colors[accent as Hue], - } +export const RAW_ADDITIONAL_COLORS: RawAdditionalColors = { + light: RAW_ADDITIONAL_COLORS_LIGHT, + dark: RAW_ADDITIONAL_COLORS_DARK, } -const makeMode = (accent: Hue, mode: Mode) => { - const calculatedColors = Object.entries({ - ...hues, - accent: hues[accent], - }).reduce((prev, curr) => { - const [key, value] = curr - const colorRange = makeColorRange(mode, key as Hue, value) - return { - ...prev, - ...colorRange.normal, - raw: { - ...prev.raw, - ...colorRange.raw, - }, - } - }, {} as CalculatedColors) - - const allColours = Object.entries(categories).reduce((prev, curr) => { - const [category, value] = curr - for (const [name, shade] of Object.entries(value.items)) { - const itemKey = `${category}${name.replace(/^[a-z]/, l => - l.toUpperCase(), - )}` as DotNestedCategoryKeys - const newItem - = typeof shade === 'string' - ? calculatedColors.raw[`${value.hue}${shade as NamedShade}`] - : shade[mode] - - prev[itemKey] = `hsl(${newItem})` - prev.raw[itemKey] = newItem - - if (name === 'primary') { - const categoryKey = category as keyof typeof categories - prev[categoryKey] = `hsl(${newItem})` - prev.raw[categoryKey] = newItem - } - } - return prev - }, calculatedColors as AllColors) - - return { - ...allColours, - gradients: makeGradients(accent, allColours), - } +/** GRADIENTS */ +type Gradient = + | 'blueGradient' + | 'greenGradient' + | 'redGradient' + | 'purpleGradient' + | 'greyGradient' + +const GRADIENT_MAP: { [key in Gradient]: string } = { + blueGradient: + 'linear-gradient(330.4deg, #44BCF0 4.54%, #7298F8 59.2%, #A099FF 148.85%)', + greenGradient: + 'linear-gradient(90deg, rgba(68,240,127,1) 4.54%, rgba(114,248,176,1) 59.2%, rgba(153,202,255,1) 148.85%)', + redGradient: + 'linear-gradient(90deg, rgba(240,68,87,1) 4.54%, rgba(248,114,149,1) 59.2%, rgba(212,153,255,1) 148.85%)', + purpleGradient: + 'linear-gradient(323.31deg, #DE82FF -15.56%, #7F6AFF 108.43%)', + greyGradient: + 'linear-gradient(330.4deg, #DFDFDF 4.54%, #959595 59.2%, #474747 148.85%)', +} + +export type Color = PaletteColor | AdditionalColor | Gradient + +export const rawColorToRGB = (color: RawColor): string => + `rgb(${color.join(', ')})` + +export const rawColorToRGBA = (color: RawColor, opacity = 1): string => + `rgba(${[...color, opacity].join(', ')})` + +export const rawColorToHex = (color: RawColor): string => { + return `#${color.map(c => c.toString(16)).join('')}` +} + +export const rawColorToHSL = ([r, g, b]: RawColor): string => { + r /= 255 + g /= 255 + b /= 255 + const l = Math.max(r, g, b) + const s = l - Math.min(r, g, b) + const h = s + ? l === r + ? (g - b) / s + : l === g + ? 2 + (b - r) / s + : 4 + (r - g) / s + : 0 + const rawHsl = [ + 60 * h < 0 ? 60 * h + 360 : 60 * h, + 100 * (s ? (l <= 0.5 ? s / (2 * l - s) : s / (2 - (2 * l - s))) : 0), + (100 * (2 * l - s)) / 2, + ] + + return `hsl(${rawHsl[0].toFixed(0)}, ${rawHsl[1].toFixed( + 0, + )}%, ${rawHsl[2].toFixed(0)}%)` +} + +const convertMapColors = ( + map: { [key in T]: RawColor }, + converter: (color: RawColor) => string, +): { [key in T]: string } => { + return Object.fromEntries( + Object.entries(map).map(([key, color]: [string, RawColor]) => [ + key, + converter(color), + ]), + ) as { [key in T]: string } } -export const makeColors = (accent: Hue) => ({ - light: makeMode(accent, 'light'), - dark: makeMode(accent, 'dark'), -}) +export const lightColors: { [key in Color]: string } = { + ...convertMapColors(RAW_PALETTE_COLORS_LIGHT, rawColorToRGB), + ...convertMapColors(RAW_ADDITIONAL_COLORS_LIGHT, rawColorToRGB), + ...GRADIENT_MAP, +} + +export const darkColors: { [key in Color]: string } = { + ...convertMapColors(RAW_PALETTE_COLORS_DARK, rawColorToRGB), + ...convertMapColors(RAW_ADDITIONAL_COLORS_DARK, rawColorToRGB), + ...GRADIENT_MAP, +} -export const colors = makeColors('blue') +export const colors = { + light: lightColors, + dark: darkColors, +} diff --git a/components/src/tokens/color3.ts b/components/src/tokens/color3.ts deleted file mode 100644 index e12b4e26..00000000 --- a/components/src/tokens/color3.ts +++ /dev/null @@ -1,411 +0,0 @@ -/** PRIMARY COLORS */ - -export type Mode = 'light' | 'dark' - -export type PrimaryColor = - | 'accent' - | 'blue' - | 'green' - | 'yellow' - | 'red' - | 'orange' - | 'indigo' - | 'pink' - | 'purple' - | 'grey' - -export type RawColor = Readonly<[number, number, number]> - -const RAW_PRIMARY_COLORS: { [key in PrimaryColor]: RawColor } = { - accent: [56, 137, 255], - blue: [56, 137, 255], - green: [25, 156, 117], - yellow: [233, 185, 17], - red: [198, 48, 27], - orange: [243, 147, 11], - indigo: [88, 84, 214], - pink: [213, 46, 126], - purple: [163, 67, 211], - grey: [155, 155, 167], -} as const - -export const PRIMARY_COLORS = Object.keys(RAW_PRIMARY_COLORS) as PrimaryColor[] - -export const validatePrimaryColor = ( - colour: unknown, - fallback: PrimaryColor = 'accent', -): PrimaryColor => { - return PRIMARY_COLORS.includes(colour as PrimaryColor) - ? (colour as PrimaryColor) - : fallback -} - -/** PALETTE COLOR */ - -export type Shade = - | 'active' - | 'dim' - | 'primary' - | 'bright' - | 'light' - | 'surface' - -export type Shades = { [key in Shade]: RawColor } - -export type Palette = { [key in PrimaryColor]: Shades } - -export const RAW_PALETTE_LIGHT: Palette = { - accent: { - active: [0, 54, 133], - dim: [5, 106, 255], - primary: RAW_PRIMARY_COLORS.blue, - bright: [86, 154, 255], - light: [209, 228, 255], - surface: [238, 245, 255], - }, - blue: { - active: [0, 54, 133], - dim: [5, 106, 255], - primary: RAW_PRIMARY_COLORS.blue, - bright: [86, 154, 255], - light: [209, 228, 255], - surface: [238, 245, 255], - }, - green: { - active: [7, 44, 33], - dim: [21, 132, 99], - primary: RAW_PRIMARY_COLORS.green, - bright: [30, 183, 137], - light: [203, 231, 220], - surface: [231, 244, 239], - }, - yellow: { - active: [66, 53, 5], - dim: [185, 147, 14], - primary: RAW_PRIMARY_COLORS.yellow, - bright: [240, 201, 60], - light: [255, 239, 173], - surface: [255, 245, 205], - }, - red: { - active: [40, 10, 6], - dim: [153, 37, 21], - primary: RAW_PRIMARY_COLORS.red, - bright: [227, 70, 49], - light: [240, 194, 194], - surface: [249, 231, 231], - }, - orange: { - active: [73, 44, 3], - dim: [195, 118, 9], - primary: RAW_PRIMARY_COLORS.orange, - bright: [246, 169, 60], - light: [251, 225, 188], - surface: [253, 240, 221], - }, - indigo: { - active: [25, 23, 95], - dim: [52, 47, 197], - primary: RAW_PRIMARY_COLORS.indigo, - bright: [126, 123, 223], - light: [199, 197, 241], - surface: [227, 226, 248], - }, - pink: { - active: [68, 14, 40], - dim: [174, 35, 102], - primary: RAW_PRIMARY_COLORS.pink, - bright: [222, 89, 153], - light: [244, 205, 224], - surface: [250, 232, 241], - }, - purple: { - active: [61, 19, 83], - dim: [138, 43, 186], - primary: RAW_PRIMARY_COLORS.purple, - bright: [184, 110, 221], - light: [227, 198, 241], - surface: [235, 214, 245], - }, - grey: { - active: [30, 33, 34], - dim: [89, 89, 89], - primary: RAW_PRIMARY_COLORS.grey, - bright: [182, 182, 191], - light: [232, 232, 232], - surface: [246, 246, 246], - }, -} as const - -export const RAW_PALETTE_DARK: Palette = { - accent: { - active: [238, 245, 255], - dim: [209, 228, 255], - primary: RAW_PRIMARY_COLORS.blue, - bright: [5, 106, 255], - light: [12, 69, 151], - surface: [13, 40, 81], - }, - blue: { - active: [238, 245, 255], - dim: [209, 228, 255], - primary: RAW_PRIMARY_COLORS.blue, - bright: [5, 106, 255], - light: [12, 69, 151], - surface: [13, 40, 81], - }, - green: { - active: [231, 244, 239], - dim: [203, 231, 220], - primary: RAW_PRIMARY_COLORS.green, - bright: [21, 132, 99], - light: [16, 74, 56], - surface: [21, 60, 49], - }, - yellow: { - active: [255, 245, 205], - dim: [255, 239, 173], - primary: RAW_PRIMARY_COLORS.yellow, - bright: [185, 147, 14], - light: [92, 75, 12], - surface: [55, 50, 34], - }, - red: { - active: [249, 231, 231], - dim: [240, 194, 194], - primary: RAW_PRIMARY_COLORS.red, - bright: [167, 38, 20], - light: [127, 19, 19], - surface: [40, 10, 6], - }, - orange: { - active: [253, 240, 221], - dim: [251, 225, 188], - primary: RAW_PRIMARY_COLORS.orange, - bright: [195, 118, 9], - light: [109, 67, 8], - surface: [88, 53, 3], - }, - indigo: { - active: [227, 226, 248], - dim: [199, 197, 241], - primary: [107, 103, 233], - bright: [52, 47, 197], - light: [34, 30, 144], - surface: [35, 33, 109], - }, - pink: { - active: [250, 232, 241], - dim: [244, 205, 224], - primary: RAW_PRIMARY_COLORS.pink, - bright: [174, 35, 102], - light: [118, 21, 68], - surface: [91, 17, 53], - }, - purple: { - active: [235, 214, 245], - dim: [227, 198, 241], - primary: RAW_PRIMARY_COLORS.purple, - bright: [138, 43, 186], - light: [94, 22, 131], - surface: [66, 20, 90], - }, - grey: { - active: [255, 255, 255], - dim: [232, 232, 232], - primary: RAW_PRIMARY_COLORS.grey, - bright: [93, 92, 98], - light: [66, 67, 71], - surface: [20, 20, 22], - }, -} as const - -export type PaletteColor = `${PrimaryColor}${Capitalize}` | PrimaryColor - -const flattenPalette = ( - palette: Palette, -): { [key in PaletteColor]: RawColor } => { - const paletteEntries = Object.entries(palette) as [ - PrimaryColor, - { [key in Shade]: RawColor }, - ][] - const primaryColorEntries = paletteEntries.map(([primaryColor, shades]) => [ - primaryColor, - shades.primary, - ]) - const paletteColorEntries = paletteEntries.reduce<[PaletteColor, RawColor][]>( - (acc, [primaryColor, shades]) => { - const shadeEntries = Object.entries(shades) as [Shade, RawColor][] - const shadeMap = shadeEntries.map(([shade, rawColor]) => { - const key = `${primaryColor}${shade - .charAt(0) - .toUpperCase()}${shade.slice(1)}` as PaletteColor - return [key, rawColor] as [PaletteColor, RawColor] - }) - return [...acc, ...shadeMap] - }, - [], - ) - return Object.fromEntries([ - ...primaryColorEntries, - ...paletteColorEntries, - ]) as { - [key in PaletteColor]: RawColor - } -} - -const RAW_PALETTE_COLORS_LIGHT = flattenPalette(RAW_PALETTE_LIGHT) -const RAW_PALETTE_COLORS_DARK = flattenPalette(RAW_PALETTE_DARK) - -export const PALETTE_COLORS = Object.keys( - RAW_PALETTE_COLORS_LIGHT, -) as PaletteColor[] - -export type RawPalettes = { [key in Mode]: Palette } - -export const RAW_PALETTE_COLORS: RawPalettes = { - light: RAW_PALETTE_LIGHT, - dark: RAW_PALETTE_DARK, -} - -/** ADDITIONAL COLORS */ - -export type AdditionalColor = - | 'black' - | 'white' - | 'text' - | 'textPrimary' - | 'textSecondary' - | 'textAccent' - | 'textDisabled' - | 'background' - | 'backgroundPrimary' - | 'backgroundSecondary' - | 'border' - -const RAW_STATIC_COLORS: { [key in 'black' | 'white']: RawColor } = { - black: [30, 33, 34], - white: [255, 255, 255], -} - -const RAW_ADDITIONAL_COLORS_LIGHT: { [key in AdditionalColor]: RawColor } = { - black: RAW_STATIC_COLORS.black, - white: RAW_STATIC_COLORS.white, - text: RAW_STATIC_COLORS.black, - textPrimary: RAW_STATIC_COLORS.black, - textSecondary: RAW_PALETTE_LIGHT.grey.dim, - textAccent: RAW_STATIC_COLORS.white, - textDisabled: RAW_PALETTE_LIGHT.grey.bright, - background: RAW_STATIC_COLORS.white, - backgroundPrimary: RAW_STATIC_COLORS.white, - backgroundSecondary: RAW_PALETTE_LIGHT.grey.surface, - border: RAW_PALETTE_LIGHT.grey.light, -} - -const RAW_ADDITIONAL_COLORS_DARK: { [key in AdditionalColor]: RawColor } = { - black: RAW_STATIC_COLORS.black, - white: RAW_STATIC_COLORS.white, - text: RAW_STATIC_COLORS.white, - textPrimary: RAW_STATIC_COLORS.white, - textSecondary: RAW_PALETTE_DARK.grey.primary, - textAccent: RAW_STATIC_COLORS.white, - textDisabled: RAW_PALETTE_DARK.grey.bright, - background: RAW_STATIC_COLORS.black, - backgroundPrimary: RAW_STATIC_COLORS.black, - backgroundSecondary: RAW_PALETTE_DARK.grey.surface, - border: RAW_PALETTE_DARK.grey.light, -} - -export const ADDITIONAL_COLORS = Object.keys( - RAW_ADDITIONAL_COLORS_LIGHT, -) as AdditionalColor[] - -export type RawAdditionalColors = { - [key in Mode]: { [key in AdditionalColor]: RawColor } -} - -export const RAW_ADDITIONAL_COLORS: RawAdditionalColors = { - light: RAW_ADDITIONAL_COLORS_LIGHT, - dark: RAW_ADDITIONAL_COLORS_DARK, -} - -/** GRADIENTS */ -type Gradient = - | 'blueGradient' - | 'greenGradient' - | 'redGradient' - | 'purpleGradient' - | 'greyGradient' - -const GRADIENT_MAP: { [key in Gradient]: string } = { - blueGradient: - 'linear-gradient(330.4deg, #44BCF0 4.54%, #7298F8 59.2%, #A099FF 148.85%)', - greenGradient: - 'linear-gradient(90deg, rgba(68,240,127,1) 4.54%, rgba(114,248,176,1) 59.2%, rgba(153,202,255,1) 148.85%)', - redGradient: - 'linear-gradient(90deg, rgba(240,68,87,1) 4.54%, rgba(248,114,149,1) 59.2%, rgba(212,153,255,1) 148.85%)', - purpleGradient: - 'linear-gradient(323.31deg, #DE82FF -15.56%, #7F6AFF 108.43%)', - greyGradient: - 'linear-gradient(330.4deg, #DFDFDF 4.54%, #959595 59.2%, #474747 148.85%)', -} - -export type Color = PaletteColor | AdditionalColor | Gradient - -export const rawColorToRGB = (color: RawColor): string => - `rgb(${color.join(', ')})` - -export const rawColorToRGBA = (color: RawColor, opacity = 1): string => - `rgba(${[...color, opacity].join(', ')})` - -export const rawColorToHex = (color: RawColor): string => { - return `#${color.map(c => c.toString(16)).join('')}` -} - -export const rawColorToHSL = ([r, g, b]: RawColor): string => { - r /= 255 - g /= 255 - b /= 255 - const l = Math.max(r, g, b) - const s = l - Math.min(r, g, b) - const h = s - ? l === r - ? (g - b) / s - : l === g - ? 2 + (b - r) / s - : 4 + (r - g) / s - : 0 - const rawHsl = [ - 60 * h < 0 ? 60 * h + 360 : 60 * h, - 100 * (s ? (l <= 0.5 ? s / (2 * l - s) : s / (2 - (2 * l - s))) : 0), - (100 * (2 * l - s)) / 2, - ] - - return `hsl(${rawHsl[0].toFixed(0)}, ${rawHsl[1].toFixed( - 0, - )}%, ${rawHsl[2].toFixed(0)}%)` -} - -const convertMapColors = ( - map: { [key in T]: RawColor }, - converter: (color: RawColor) => string, -): { [key in T]: string } => { - return Object.fromEntries( - Object.entries(map).map(([key, color]: [string, RawColor]) => [ - key, - converter(color), - ]), - ) as { [key in T]: string } -} - -export const lightColors: { [key in Color]: string } = { - ...convertMapColors(RAW_PALETTE_COLORS_LIGHT, rawColorToRGB), - ...convertMapColors(RAW_ADDITIONAL_COLORS_LIGHT, rawColorToRGB), - ...GRADIENT_MAP, -} - -export const darkColors: { [key in Color]: string } = { - ...convertMapColors(RAW_PALETTE_COLORS_DARK, rawColorToRGB), - ...convertMapColors(RAW_ADDITIONAL_COLORS_DARK, rawColorToRGB), - ...GRADIENT_MAP, -} diff --git a/components/src/tokens/colors2.ts b/components/src/tokens/colors2.ts deleted file mode 100644 index e77dd902..00000000 --- a/components/src/tokens/colors2.ts +++ /dev/null @@ -1,283 +0,0 @@ -/** - * Color Variables - * - * All the following variables are used to generate color tokens. - * Changes made to these variables will be reflected throughout the library. - */ - -// The Mode type contains all possible theme modes. -export type Mode = 'light' | 'dark' - -const shades = [50, 100, 300, 400, 500, 750] as const - -const namedShadeMap = { - Surface: 50, - Light: 100, - Bright: 300, - Primary: 400, - Dim: 500, - Active: 750, -} as const - -// The hues object is a map of HSL colors, with optional overrides for each shade. -const hues = { - blue: [216, 100, 61, { 50: [215, 100, 97] }], - indigo: [242, 61, 58], - purple: [280, 62, 55], - pink: [331, 67, 51, { 100: [331, 64, 88] }], - red: [7, 76, 44, { 50: [0, 60, 94], 100: [360, 60, 85] }], - orange: [35, 91, 50, { 100: [36, 89, 86] }], - yellow: [47, 86, 49, { 50: [48, 100, 90], 100: [48, 100, 85] }], - green: [162, 72, 40, { 50: [157, 37, 93], 100: [157, 37, 85] }], - teal: [199, 66, 49], - grey: [ - 240, - 6, - 63, - { - 50: [0, 0, 96], - 100: [0, 0, 91], - 500: [0, 0, 35], - 750: [0, 0, 15], - }, - ], -} satisfies Record - -const backgroundColor = { - light: '0 0% 100%', - dark: '0 0% 8%', -} - -// The categories object is a map of categorised colors, which can each have their own custom values. -const categories = { - background: { - hue: 'grey', - items: { - primary: backgroundColor, - secondary: 'Surface', - }, - }, - text: { - hue: 'grey', - items: { - primary: 'Active', - secondary: 'Dim', - tertiary: 'Primary', - accent: { - light: backgroundColor.light, - dark: backgroundColor.light, - }, - }, - }, - border: { - hue: 'grey', - items: { - primary: 'Light', - }, - }, -} satisfies Record - -const gradients = { - blueGradient: - 'linear-gradient(330.4deg, #44BCF0 4.54%, #7298F8 59.2%, #A099FF 148.85%)', - greenGradient: - 'linear-gradient(90deg, rgba(68,240,127,1) 4.54%, rgba(114,248,176,1) 59.2%, rgba(153,202,255,1) 148.85%)', - redGradient: - 'linear-gradient(90deg, rgba(240,68,87,1) 4.54%, rgba(248,114,149,1) 59.2%, rgba(212,153,255,1) 148.85%)', - purpleGradient: - 'linear-gradient(323.31deg, #DE82FF -15.56%, #7F6AFF 108.43%)', - greyGradient: - 'linear-gradient(330.4deg, #DFDFDF 4.54%, #959595 59.2%, #474747 148.85%)', -} - -/** - * END COLOR VARIABLES - */ - -export type NamedShade = keyof typeof namedShadeMap -export type Shade = (typeof shades)[number] -export type Hue = keyof typeof hues -export type Category = keyof Categories | 'accent' -export type Gradient = keyof typeof gradients - -type HSLColor = [hue: number, saturation: number, lightness: number] - -type HueItem = [ - ...hsl: HSLColor, - overrides?: { - [key in Shade]?: HSLColor - }, -] - -type Categories = typeof categories - -type CamelCaseNested = ( - T extends object - ? { - [K in Exclude]: `${K}${Capitalize< - CamelCaseNested - >}` - }[Exclude] - : '' -) extends infer D - ? Extract - : never - -type DotNestedCategoryKeys = CamelCaseNested<{ - [item in keyof Categories]: { - [key in keyof Categories[item]['items']]: string - } & { - '': string - } -}> -type DotNestedCategories = { [K in DotNestedCategoryKeys]: string } - -type GeneratedCategories = DotNestedCategories - -type CategoryItem = { - hue: Hue - items: { - [key: string]: - | { - [key in Mode]: string - } - | NamedShade - } -} - -type WithRaw = Omit & { raw: Omit } - -type ShadeColor = { [key in Shade]: string } -type NameColor = { [key in NamedShade]: string } -type ColorItem< - TObject extends Record, - TName extends string, -> = TObject extends object ? { - [key in Exclude as `${TName}${key}`]: string -} & { - [T in `${TName}`]: string -} - : never -type CalculatedColors = WithRaw> -type AllColors = WithRaw - -const makeColorObject = ( - mode: Mode, - name: THue, - color: ShadeColor, -) => { - if (mode === 'dark') { - color = Object.fromEntries( - Object.entries(color).map(([key], index, arr) => [ - key, - arr[arr.length - index - 1][1], - ]), - ) as ShadeColor - } - - const values = Object.fromEntries( - Object.entries(namedShadeMap).map(([key, value]) => [ - `${name}${key}`, - color[value], - ]), - ) - - return { ...values, [name]: values[`${name}Primary`] } as ColorItem< - NameColor, - THue - > -} - -const makeCSSHSL = (hsl: HSLColor) => `${hsl[0]} ${hsl[1]}% ${hsl[2]}%` - -const makeColorRange = ( - mode: Mode, - name: THue, - hue: HueItem, -) => { - const color = Object.fromEntries( - shades.map((shade) => { - if (hue[3]?.[shade]) { - return [shade, makeCSSHSL(hue[3]![shade]!)] - } - const hsl = hue.slice(0, 3) as HSLColor - hsl[2] = hsl[2] + (400 - shade) / 10 - return [shade, makeCSSHSL(hsl)] - }), - ) as ShadeColor - return { - normal: makeColorObject( - mode, - name, - Object.fromEntries( - Object.entries(color).map(([key, value]) => [key, `hsl(${value})`]), - ) as ShadeColor, - ), - raw: makeColorObject(mode, name, color), - } -} - -const makeGradients = (accent: unknown, colors: AllColors) => { - const accentGradient = gradients[accent as Gradient] || colors[accent as Hue] - const entries = Object.entries({ - ...gradients, - accent: accentGradient, - }) - return Object.fromEntries(entries) as Record -} - -const makeMode = (accent: Hue, mode: Mode) => { - const calculatedColors = Object.entries({ - ...hues, - accent: hues[accent], - }).reduce((prev, curr) => { - const [key, value] = curr - const colorRange = makeColorRange(mode, key as Hue, value) - return { - ...prev, - ...colorRange.normal, - raw: { - ...prev.raw, - ...colorRange.raw, - }, - } - }, {} as CalculatedColors) - - const allColours = Object.entries(categories).reduce((prev, curr) => { - const [category, value] = curr - for (const [name, shade] of Object.entries(value.items)) { - const itemKey = `${category}${name.replace(/^[a-z]/, l => - l.toUpperCase(), - )}` as DotNestedCategoryKeys - const newItem - = typeof shade === 'string' - ? calculatedColors.raw[`${value.hue}${shade as NamedShade}`] - : shade[mode] - - prev[itemKey] = `hsl(${newItem})` - prev.raw[itemKey] = newItem - - if (name === 'primary') { - const categoryKey = category as keyof typeof categories - prev[categoryKey] = `hsl(${newItem})` - prev.raw[categoryKey] = newItem - } - } - return prev - }, calculatedColors as AllColors) - - const allColoursWithRaw = { - ...allColours, - ...makeGradients(accent, allColours), - } - - delete (allColoursWithRaw as any)['raw'] - return allColoursWithRaw as Omit -} - -export const makeColors = (accent: Hue) => ({ - light: makeMode(accent, 'light'), - dark: makeMode(accent, 'dark'), -}) - -export const colors = makeColors('blue') diff --git a/components/src/tokens/index.ts b/components/src/tokens/index.ts index 1f5a0df2..cc14e8be 100644 --- a/components/src/tokens/index.ts +++ b/components/src/tokens/index.ts @@ -91,5 +91,5 @@ export type { Hue, Mode } from './color' export type Tokens = typeof lightTheme export type Breakpoints = keyof typeof breakpoints export type Space = keyof typeof space -export type Colors = Exclude +export type Colors = keyof typeof colors.light export type Radii = keyof typeof radii diff --git a/components/src/types/index.ts b/components/src/types/index.ts index 922ea14f..244272da 100644 --- a/components/src/types/index.ts +++ b/components/src/types/index.ts @@ -4,13 +4,6 @@ import type { Hue as TokenHue, Mode as TokenMode, Tokens } from '@/src/tokens' export type AllOrNone = T | { [K in keyof T]?: never } -export type { - Color, - ColorStyle, - WithColor, - WithColorStyle, -} from './withColorOrColorStyle' - export type { FontVariant, WithTypography } from './withTypography' /* diff --git a/components/src/types/withColorOrColorStyle.test.tsx b/components/src/types/withColorOrColorStyle.test.tsx deleted file mode 100644 index f7cfbf46..00000000 --- a/components/src/types/withColorOrColorStyle.test.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import { colors } from '@/src/tokens/color' - -import type { - Color } from './withColorOrColorStyle' -import { - colorMap, - getColor, - getColorStyle, -} from './withColorOrColorStyle' - -const colorMapKeys = Object.keys(colorMap).filter( - color => color != 'raw' && color != 'gradients', -) as Color[] - -const gradientKeys = Object.keys(colors.light.gradients) - -describe('WithColor', () => { - colorMapKeys.forEach((color) => { - it('should resolve ' + color + ' to a string', () => { - const attribute = getColor(color as any) - expect(typeof attribute).toBe('string') - }) - }) - - gradientKeys.forEach((color) => { - it('should resolve ' + color + ' to a string', () => { - const attribute = getColor(color as any) - expect(typeof attribute).toBe('string') - }) - }) -}) - -const colorStyleColors = [ - 'accent', - 'blue', - 'indigo', - 'purple', - 'pink', - 'red', - 'orange', - 'yellow', - 'green', - 'teal', - 'grey', -] - -const specialColorStyles = ['transparent', 'disabled'] - -const attributes = ['background', 'border', 'text', 'hover'] - -describe('WithColorStyle', () => { - colorStyleColors.forEach((color) => { - attributes.forEach((attribute) => { - it( - 'should resolve ' + color + 'Primary ' + attribute + ' to a string', - () => { - const value = getColorStyle( - `${color}Primary` as any, - attribute as any, - ) - expect(typeof value).toBe('string') - if (attribute !== 'hoverFilter') - expect(value).toMatch(/^(hsl\(|transparent|initial|inherit)/) - }, - ) - }) - }) - - colorStyleColors.forEach((color) => { - attributes.forEach((attribute) => { - it( - 'should resolve ' + color + 'Secondary ' + attribute + ' to a string', - () => { - const value = getColorStyle( - `${color}Secondary` as any, - attribute as any, - ) - expect(typeof value).toBe('string') - if (attribute !== 'hoverFilter') - expect(value).toMatch(/^(hsl\(|transparent|initial|inherit)/) - }, - ) - }) - }) - - specialColorStyles.forEach((style) => { - attributes.forEach((attribute) => { - it('should resolve ' + style + ' ' + attribute + ' to a string', () => { - const value = getColorStyle(`${style}` as any, attribute as any) - expect(typeof value).toBe('string') - if (attribute !== 'hoverFilter') - expect(value).toMatch(/^(hsl\(|transparent|initial|inherit)/) - }) - }) - }) -}) diff --git a/components/src/types/withColorOrColorStyle.ts b/components/src/types/withColorOrColorStyle.ts deleted file mode 100644 index 9cde3cb1..00000000 --- a/components/src/types/withColorOrColorStyle.ts +++ /dev/null @@ -1,172 +0,0 @@ -import type { Colors } from '../tokens' -import { colors as colorObj } from '../tokens/color' - -type ColorObj = typeof colorObj.light - -type ColorMode = keyof typeof colorObj - -type ColorGradient = keyof typeof colorObj.light.gradients - -const makeColorMap = (mode: ColorMode) => { - const gradientKeys = Object.keys( - colorObj[mode]['gradients'], - ) as ColorGradient[] - - const gradientValues = Object.fromEntries( - gradientKeys.map((color: ColorGradient) => [ - `${color}Gradient`, - colorObj[mode]['gradients'][color], - ]), - ) as { - [key in `${ColorGradient}Gradient`]: string - } - - const colorKeys = Object.keys(colorObj[mode]).filter( - ([color]) => color !== 'gradients' && color !== 'raw', - ) as Colors[] - - const colorValues = Object.fromEntries( - colorKeys.map(color => [color, colorObj[mode][color]]), - ) as { [key in Colors]: string } - - return { - ...gradientValues, - ...colorValues, - tranparent: 'transparent', - initial: 'initial', - inherit: 'inherit', - } -} - -export const colorMap = makeColorMap('light') - -export type Color = keyof typeof colorMap - -export type WithColor = { - /** The color to style the component */ - color?: Color -} - -const BASE_COLORS = [ - 'accent', - 'blue', - 'indigo', - 'purple', - 'pink', - 'red', - 'orange', - 'yellow', - 'green', - 'teal', - 'grey', -] as const - -type BaseColor = (typeof BASE_COLORS)[number] - -type ColorStyleItem = { - text: string - background: string - border: string - hover: string -} - -type ColorAttribute = keyof ColorStyleItem - -const makeColorStyleMap = (mode: ColorMode) => { - const primaryStyles = Object.fromEntries( - BASE_COLORS.map(color => [ - `${color}Primary`, - { - text: colorObj[mode][`backgroundPrimary`], - background: colorObj[mode][`${color}Primary`], - border: 'transparent', - hover: colorObj[mode][`${color}Bright`], - }, - ]), - ) as { - [key in `${BaseColor}Primary`]: ColorStyleItem - } - const secondaryStyles = Object.fromEntries( - BASE_COLORS.map(color => [ - `${color}Secondary`, - { - text: colorObj[mode][`${color}Primary`], - background: colorObj[mode][`${color}Surface`], - border: 'transparent', - hover: colorObj[mode][`${color}Light`], - }, - ]), - ) as { - [key in `${BaseColor}Secondary`]: ColorStyleItem - } - - const gradientKeys = Object.keys( - colorObj[mode]['gradients'], - ) as ColorGradient[] - const gradientValues = Object.fromEntries( - gradientKeys.map(color => [ - `${color}Gradient`, - { - text: colorObj[mode][`backgroundPrimary`], - background: colorObj[mode]['gradients'][color], - border: 'transparent', - hover: colorObj[mode]['gradients'][color], - }, - ]), - ) as { - [key in Exclude< - keyof ColorObj['gradients'], - symbol - > as `${key}Gradient`]: ColorStyleItem - } - - const transparent: ColorStyleItem = { - text: 'initial', - background: 'transparent', - border: 'transparent', - hover: colorObj[mode]['greyLight'], - } - - const disabled: ColorStyleItem = { - text: colorObj[mode]['greyPrimary'], - background: colorObj[mode]['greyLight'], - border: colorObj[mode]['greyLight'], - hover: colorObj[mode]['greyLight'], - } - - const background: ColorStyleItem = { - text: colorObj[mode]['textPrimary'], - background: colorObj[mode]['backgroundPrimary'], - border: colorObj[mode]['border'], - hover: colorObj[mode]['backgroundSecondary'], - } - - return { - ...primaryStyles, - ...secondaryStyles, - ...gradientValues, - transparent, - disabled, - background, - } -} - -const colorStyleMap = makeColorStyleMap('light') - -export type ColorStyle = keyof typeof colorStyleMap - -export type WithColorStyle = { - /** The color style to style the component */ - colorStyle?: ColorStyle -} - -export const getColor = (color: Color) => { - return colorMap[color] -} - -export const getColorStyle = ( - colorStyle: ColorStyle, - attribute: ColorAttribute, -) => { - return colorStyleMap[colorStyle]?.[attribute] -} diff --git a/docs/src/components/CodePreview.tsx b/docs/src/components/CodePreview.tsx index 9ef35a45..4e0d1720 100644 --- a/docs/src/components/CodePreview.tsx +++ b/docs/src/components/CodePreview.tsx @@ -6,7 +6,8 @@ import { mdx } from '@mdx-js/react' import type { PrismTheme } from 'prism-react-renderer' import type { Colors } from '@ensdomains/thorin' -import { Button, Components, UpChevronSVG } from '@ensdomains/thorin' +import { Button, UpChevronSVG } from '@ensdomains/thorin' +import * as Components from '@ensdomains/thorin' import { createPlayroomLink } from '~/utils/playroom' import { usePlayroomStore } from '~/playroom/PlayroomState'