Skip to content

Commit 3f65ee8

Browse files
hervedombyaclaude
andcommitted
refactor: use polished getLuminance instead of custom luminance implementation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 37e930f commit 3f65ee8

File tree

2 files changed

+9
-24
lines changed

2 files changed

+9
-24
lines changed

src/lib/utils.test.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ describe('getContrastText', () => {
3333
expect(getContrastText('#000', LIGHT_TEXT, DARK_TEXT)).toBe(LIGHT_TEXT);
3434
});
3535

36-
it('handles hex without # prefix', () => {
37-
expect(getContrastText('000000', LIGHT_TEXT, DARK_TEXT)).toBe(LIGHT_TEXT);
38-
expect(getContrastText('FFFFFF', LIGHT_TEXT, DARK_TEXT)).toBe(DARK_TEXT);
36+
it('handles rgb color format', () => {
37+
expect(getContrastText('rgb(0, 0, 0)', LIGHT_TEXT, DARK_TEXT)).toBe(LIGHT_TEXT);
38+
expect(getContrastText('rgb(255, 255, 255)', LIGHT_TEXT, DARK_TEXT)).toBe(DARK_TEXT);
3939
});
4040

41-
it('returns null for non-hex values', () => {
41+
it('returns null for unparseable values', () => {
4242
expect(
4343
getContrastText(
4444
'linear-gradient(130deg, #9355E7 0%, #2E4AA3 60%)',
@@ -47,8 +47,5 @@ describe('getContrastText', () => {
4747
),
4848
).toBeNull();
4949
expect(getContrastText('not-a-color', LIGHT_TEXT, DARK_TEXT)).toBeNull();
50-
expect(
51-
getContrastText('rgb(255, 0, 0)', LIGHT_TEXT, DARK_TEXT),
52-
).toBeNull();
5350
});
5451
});

src/lib/utils.ts

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { getLuminance } from 'polished';
2+
13
const RGB_HEX = /^#?(?:([\da-f]{3})[\da-f]?|([\da-f]{6})(?:[\da-f]{2})?)$/i;
24

35
/** Ensure the consistency of colors between old and new colors */
@@ -45,23 +47,9 @@ export const hex2RGB = (str: string): [number, number, number] => {
4547
throw new Error('Invalid hex string provided');
4648
};
4749

48-
// WCAG 2.0 relative luminance
49-
const relativeLuminance = (r: number, g: number, b: number): number => {
50-
const [rs, gs, bs] = [r, g, b].map((c) => {
51-
const s = c / 255;
52-
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
53-
});
54-
return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
55-
};
56-
5750
const wcagContrastRatio = (l1: number, l2: number): number =>
5851
(Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
5952

60-
const luminanceOf = (hex: string): number => {
61-
const [r, g, b] = hex2RGB(hex);
62-
return relativeLuminance(r, g, b);
63-
};
64-
6553
// Minimum WCAG contrast ratio to consider a text color readable on a background.
6654
// 3.0 corresponds to WCAG AA for large text — same threshold used by MUI.
6755
const CONTRAST_THRESHOLD = 3;
@@ -72,9 +60,9 @@ export const getContrastText = (
7260
textReverse: string,
7361
): string | null => {
7462
try {
75-
const bgLum = luminanceOf(bgColor);
76-
const primaryLum = luminanceOf(textPrimary);
77-
const reverseLum = luminanceOf(textReverse);
63+
const bgLum = getLuminance(bgColor);
64+
const primaryLum = getLuminance(textPrimary);
65+
const reverseLum = getLuminance(textReverse);
7866

7967
const lighterText = primaryLum >= reverseLum ? textPrimary : textReverse;
8068
const darkerText = primaryLum >= reverseLum ? textReverse : textPrimary;

0 commit comments

Comments
 (0)