Skip to content

Commit 0f207b5

Browse files
committed
fix(clerk-js): Color typing
1 parent a0006a9 commit 0f207b5

File tree

4 files changed

+99
-61
lines changed

4 files changed

+99
-61
lines changed
Lines changed: 49 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,50 @@
11
import { createAlphaScaleWithTransparentize, transparentize } from '../utils/colorMix';
22

3-
export const whiteAlpha = Object.freeze({
4-
whiteAlpha25: transparentize('white', '2%'),
5-
whiteAlpha50: transparentize('white', '3%'),
6-
whiteAlpha100: transparentize('white', '7%'),
7-
whiteAlpha150: transparentize('white', '11%'),
8-
whiteAlpha200: transparentize('white', '15%'),
9-
whiteAlpha300: transparentize('white', '28%'),
10-
whiteAlpha400: transparentize('white', '41%'),
11-
whiteAlpha500: transparentize('white', '53%'),
12-
whiteAlpha600: transparentize('white', '62%'),
13-
whiteAlpha700: transparentize('white', '73%'),
14-
whiteAlpha750: transparentize('white', '78%'),
15-
whiteAlpha800: transparentize('white', '81%'),
16-
whiteAlpha850: transparentize('white', '84%'),
17-
whiteAlpha900: transparentize('white', '87%'),
18-
whiteAlpha950: transparentize('white', '92%'),
19-
} as const);
3+
type ColorScale<Prefix extends string> = {
4+
[K in `${Prefix}${'50' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900' | '950'}`]: string;
5+
};
206

21-
export const neutralAlpha = Object.freeze({
22-
neutralAlpha25: transparentize('black', '2%'),
23-
neutralAlpha50: transparentize('black', '3%'),
24-
neutralAlpha100: transparentize('black', '7%'),
25-
neutralAlpha150: transparentize('black', '11%'),
26-
neutralAlpha200: transparentize('black', '15%'),
27-
neutralAlpha300: transparentize('black', '28%'),
28-
neutralAlpha400: transparentize('black', '41%'),
29-
neutralAlpha500: transparentize('black', '53%'),
30-
neutralAlpha600: transparentize('black', '62%'),
31-
neutralAlpha700: transparentize('black', '73%'),
32-
neutralAlpha750: transparentize('black', '78%'),
33-
neutralAlpha800: transparentize('black', '81%'),
34-
neutralAlpha850: transparentize('black', '84%'),
35-
neutralAlpha900: transparentize('black', '87%'),
36-
neutralAlpha950: transparentize('black', '92%'),
37-
} as const);
7+
// Create alpha scales separately to preserve types
8+
export const whiteAlpha = createAlphaScaleWithTransparentize('white', 'whiteAlpha');
9+
export const neutralAlpha = createAlphaScaleWithTransparentize('black', 'neutralAlpha');
10+
11+
const primaryAlpha = createAlphaScaleWithTransparentize('#2F3037', 'primaryAlpha');
12+
const dangerAlpha = createAlphaScaleWithTransparentize('#EF4444', 'dangerAlpha');
13+
const warningAlpha = createAlphaScaleWithTransparentize('#F36B16', 'warningAlpha');
14+
const successAlpha = createAlphaScaleWithTransparentize('#22C543', 'successAlpha');
15+
16+
// Define the base colors object type
17+
type BaseColors = {
18+
avatarBorder: string;
19+
avatarBackground: string;
20+
modalBackdrop: string;
21+
colorBackground: string;
22+
colorInputBackground: string;
23+
colorText: string;
24+
colorTextSecondary: string;
25+
colorInputText: string;
26+
colorTextOnPrimaryBackground: string;
27+
colorShimmer: string;
28+
transparent: string;
29+
white: string;
30+
black: string;
31+
primaryHover: string;
32+
};
33+
34+
// Combine all types
35+
type Colors = BaseColors &
36+
ColorScale<'primary'> &
37+
ColorScale<'danger'> &
38+
ColorScale<'warning'> &
39+
ColorScale<'success'> &
40+
typeof neutralAlpha &
41+
typeof whiteAlpha &
42+
typeof primaryAlpha &
43+
typeof dangerAlpha &
44+
typeof warningAlpha &
45+
typeof successAlpha;
3846

39-
export const colors = Object.freeze({
47+
export const colors: Colors = Object.freeze({
4048
avatarBorder: neutralAlpha.neutralAlpha200,
4149
avatarBackground: neutralAlpha.neutralAlpha400,
4250
modalBackdrop: neutralAlpha.neutralAlpha700,
@@ -63,8 +71,9 @@ export const colors = Object.freeze({
6371
primary700: '#25232A',
6472
primary800: '#201D23',
6573
primary900: '#1B171C',
66-
primaryHover: '#3B3C45', //primary 500 adjusted for lightness
67-
...createAlphaScaleWithTransparentize('#2F3037', 'primaryAlpha'),
74+
primary950: '#0F0D12',
75+
primaryHover: '#3B3C45', // primary 500 adjusted for lightness
76+
...primaryAlpha,
6877
danger50: '#FEF2F2',
6978
danger100: '#FEE5E5',
7079
danger200: '#FECACA',
@@ -76,7 +85,7 @@ export const colors = Object.freeze({
7685
danger800: '#991B1B',
7786
danger900: '#7F1D1D',
7887
danger950: '#450A0A',
79-
...createAlphaScaleWithTransparentize('#EF4444', 'dangerAlpha'),
88+
...dangerAlpha,
8089
warning50: '#FFF6ED',
8190
warning100: '#FFEBD5',
8291
warning200: '#FED1AA',
@@ -88,7 +97,7 @@ export const colors = Object.freeze({
8897
warning800: '#9A2F12',
8998
warning900: '#7C2912',
9099
warning950: '#431207',
91-
...createAlphaScaleWithTransparentize('#F36B16', 'warningAlpha'),
100+
...warningAlpha,
92101
success50: '#F0FDF2',
93102
success100: '#DCFCE2',
94103
success200: '#BBF7C6',
@@ -100,5 +109,5 @@ export const colors = Object.freeze({
100109
success800: '#166527',
101110
success900: '#145323',
102111
success950: '#052E0F',
103-
...createAlphaScaleWithTransparentize('#22C543', 'successAlpha'),
112+
...successAlpha,
104113
} as const);

packages/clerk-js/src/ui/primitives/Badge.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ const { applyVariants, filterProps } = createVariants(theme => ({
5454
},
5555
}));
5656

57-
// @ts-ignore
5857
export type BadgeProps = PropsOfComponent<typeof Flex> & StyleVariants<typeof applyVariants>;
5958

6059
export const Badge = (props: BadgeProps) => {

packages/clerk-js/src/ui/utils/colorMix.ts

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,39 @@
44
*/
55
type Percentage = `${number}%`;
66

7+
/**
8+
* A default key for a shade of a color/lightness/etc
9+
* @example '25'
10+
*/
11+
type DefaultShadeKey =
12+
| '25'
13+
| '50'
14+
| '100'
15+
| '150'
16+
| '200'
17+
| '300'
18+
| '400'
19+
| '500'
20+
| '600'
21+
| '700'
22+
| '750'
23+
| '800'
24+
| '850'
25+
| '900'
26+
| '950';
27+
28+
/**
29+
* A key for a shade of an alpha color
30+
* @example '25'
31+
*/
32+
type AlphaShadeKey = DefaultShadeKey;
33+
34+
/**
35+
* A key for a shade of a lightness color
36+
* @example '25'
37+
*/
38+
type LightnessShadeKey = DefaultShadeKey;
39+
740
/**
841
* Mix a color with a color tint
942
* @param color - The color to mix
@@ -48,7 +81,7 @@ export function darken(color: string, percentage: Percentage) {
4881
/**
4982
* A map of alpha shades to percentages
5083
*/
51-
const ALPHA_SHADES_MAP: Record<string, string> = {
84+
const ALPHA_SHADES_MAP: Record<AlphaShadeKey, Percentage> = {
5285
'25': '2%',
5386
'50': '3%',
5487
'100': '7%',
@@ -64,7 +97,7 @@ const ALPHA_SHADES_MAP: Record<string, string> = {
6497
'850': '84%',
6598
'900': '87%',
6699
'950': '92%',
67-
};
100+
} as const;
68101

69102
/**
70103
* Create an alpha scale with transparentize
@@ -75,19 +108,16 @@ const ALPHA_SHADES_MAP: Record<string, string> = {
75108
export function createAlphaScaleWithTransparentize<P extends string>(
76109
baseColor: string,
77110
prefix: P,
78-
): Record<`${P}${keyof typeof ALPHA_SHADES_MAP}`, string> {
79-
const scale = {} as Record<`${P}${keyof typeof ALPHA_SHADES_MAP}`, string>;
80-
for (const shadeKey in ALPHA_SHADES_MAP) {
81-
if (Object.prototype.hasOwnProperty.call(ALPHA_SHADES_MAP, shadeKey)) {
82-
const percentage = ALPHA_SHADES_MAP[shadeKey];
83-
// @ts-expect-error - TODO: align percentage type
84-
scale[`${prefix}${shadeKey}`] = transparentize(baseColor, percentage);
85-
}
86-
}
87-
return scale;
111+
): Record<`${P}${AlphaShadeKey}`, string> {
112+
return Object.fromEntries(
113+
Object.entries(ALPHA_SHADES_MAP).map(([shadeKey, percentage]) => [
114+
`${prefix}${shadeKey}`,
115+
transparentize(baseColor, percentage),
116+
]),
117+
) as Record<`${P}${AlphaShadeKey}`, string>;
88118
}
89119

90-
const LIGHTNESS_SHADES_DEF: Record<string, { type: 'lighten' | 'darken' | 'base'; amount: Percentage }> = {
120+
const LIGHTNESS_SHADES_DEF: Record<LightnessShadeKey, { type: 'lighten' | 'darken' | 'base'; amount: Percentage }> = {
91121
'25': { type: 'lighten', amount: '92%' },
92122
'50': { type: 'lighten', amount: '85%' },
93123
'100': { type: 'lighten', amount: '70%' },
@@ -105,7 +135,7 @@ const LIGHTNESS_SHADES_DEF: Record<string, { type: 'lighten' | 'darken' | 'base'
105135
'950': { type: 'darken', amount: '92%' },
106136
};
107137

108-
const ALL_LIGHTNESS_SHADE_KEYS = Object.keys(LIGHTNESS_SHADES_DEF);
138+
const ALL_LIGHTNESS_SHADE_KEYS = Object.keys(LIGHTNESS_SHADES_DEF) as LightnessShadeKey[];
109139

110140
/**
111141
* Creates a full lightness color scale (shades 25-950) using color-mix lighten/darken.
@@ -114,15 +144,15 @@ const ALL_LIGHTNESS_SHADE_KEYS = Object.keys(LIGHTNESS_SHADES_DEF);
114144
* @returns A prefixed color scale object, or undefined if colorOption is undefined.
115145
*/
116146
export function createColorMixLightnessScale<P extends string>(
117-
colorOption: string | Partial<Record<keyof typeof LIGHTNESS_SHADES_DEF, string>> | undefined,
147+
colorOption: string | Partial<Record<LightnessShadeKey, string>> | undefined,
118148
prefix: P,
119-
): Record<`${P}${keyof typeof LIGHTNESS_SHADES_DEF}`, string> | undefined {
149+
): Record<`${P}${LightnessShadeKey}`, string> | undefined {
120150
if (!colorOption) {
121151
return undefined;
122152
}
123153

124154
let baseFor500: string;
125-
const userProvidedShades: Partial<Record<keyof typeof LIGHTNESS_SHADES_DEF, string>> = {};
155+
const userProvidedShades: Partial<Record<LightnessShadeKey, string>> = {};
126156

127157
if (typeof colorOption === 'string') {
128158
baseFor500 = colorOption;
@@ -140,7 +170,7 @@ export function createColorMixLightnessScale<P extends string>(
140170
}
141171
}
142172

143-
const generatedScale: Partial<Record<keyof typeof LIGHTNESS_SHADES_DEF, string>> = {};
173+
const generatedScale: Partial<Record<LightnessShadeKey, string>> = {};
144174
for (const shadeKey of ALL_LIGHTNESS_SHADE_KEYS) {
145175
const definition = LIGHTNESS_SHADES_DEF[shadeKey];
146176
switch (definition.type) {
@@ -158,7 +188,7 @@ export function createColorMixLightnessScale<P extends string>(
158188

159189
const mergedScale = { ...generatedScale, ...userProvidedShades };
160190

161-
const resultScale = {} as Record<`${P}${keyof typeof LIGHTNESS_SHADES_DEF}`, string>;
191+
const resultScale = {} as Record<`${P}${LightnessShadeKey}`, string>;
162192
for (const key of ALL_LIGHTNESS_SHADE_KEYS) {
163193
if (mergedScale[key]) {
164194
resultScale[`${prefix}${key}`] = mergedScale[key];

packages/clerk-js/src/ui/utils/colors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ const hslaColorToHslaString = ({ h, s, l, a }: HslaColor): HslaColorString => {
256256

257257
const parse = (str: string): ParsedResult => {
258258
// TODO(Colors): This is a temporary fix to allow for custom colors to be passed in as variables
259-
return str;
259+
return str as unknown as ParsedResult;
260260
const prefix = str.substr(0, 3).toLowerCase();
261261
let res;
262262
if (prefix === 'hsl') {

0 commit comments

Comments
 (0)