Skip to content

Commit b8e8a3d

Browse files
mimarzunekinn
andauthored
refactor(color): 🏷️ better type safety using colors in code (#3176)
Co-authored-by: Une Sofie Kinn Ekroll <[email protected]>
1 parent dc39d28 commit b8e8a3d

File tree

22 files changed

+250
-190
lines changed

22 files changed

+250
-190
lines changed

apps/_components/src/ColorModal/ColorModal.tsx

+7-15
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
import { Dialog, Heading, Paragraph } from '@digdir/designsystemet-react';
2-
import type { ColorNumber, HexColor } from '@digdir/designsystemet/color';
3-
import {
4-
colorMetadata,
5-
getColorInfoFromPosition,
6-
getCssVariable,
7-
hexToHsluv,
8-
} from '@digdir/designsystemet/color';
2+
import type { Color } from '@digdir/designsystemet/color';
3+
import { getCssVariable, hexToHsluv } from '@digdir/designsystemet/color';
94
import { ClipboardButton } from '@repo/components';
105

116
import classes from './ColorModal.module.css';
@@ -37,17 +32,16 @@ const Field = ({
3732

3833
type ColorModalProps = {
3934
colorModalRef: React.Ref<HTMLDialogElement> | null;
40-
hex: HexColor;
4135
namespace: string;
42-
number: ColorNumber;
36+
color: Color;
4337
};
4438

4539
export const ColorModal = ({
4640
colorModalRef,
47-
hex,
4841
namespace,
49-
number,
42+
color,
5043
}: ColorModalProps) => {
44+
const { displayName, description, number, hex } = color;
5145
return (
5246
<Dialog
5347
ref={colorModalRef}
@@ -58,13 +52,11 @@ export const ColorModal = ({
5852
>
5953
<Dialog.Block>
6054
<Heading data-size='xs'>
61-
{`${capitalizeFirstLetter(namespace)} ${capitalizeFirstLetter(getColorInfoFromPosition(number).displayName)}`}
55+
{`${capitalizeFirstLetter(namespace)} ${displayName}`}
6256
</Heading>
6357
</Dialog.Block>
6458
<Dialog.Block className={classes.modalContent}>
65-
<div className={classes.description}>
66-
{colorMetadata[number].description}
67-
</div>
59+
<div className={classes.description}>{description}</div>
6860
<div className={classes.container}>
6961
<table className={classes.infoTable}>
7062
<tbody>

apps/storefront/components/Tokens/TokenColor/TokenColor.module.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
outline-offset: 2px;
1919
}
2020

21-
.test {
21+
.colorBox {
2222
--color: #cfcfcf;
2323

2424
background-color: #e5e5f7;

apps/storefront/components/Tokens/TokenColor/TokenColor.tsx

+35-23
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
import { getColorInfoFromPosition } from '@digdir/designsystemet/color';
1+
import { getColorMetadataByNumber } from '@digdir/designsystemet/color';
22
import { ColorModal } from '@repo/components';
33
import cl from 'clsx/lite';
44
import { useRef } from 'react';
55
import type { TransformedToken } from 'style-dictionary';
66

7-
import type { ColorNumber, HexColor } from '@digdir/designsystemet/color';
7+
import type {
8+
Color,
9+
ColorNumber,
10+
HexColor,
11+
} from '@digdir/designsystemet/color';
812

913
import classes from './TokenColor.module.css';
1014
interface TokenColorProps {
@@ -14,9 +18,8 @@ interface TokenColorProps {
1418

1519
/* The original.value is something like "{global.yellow.1}", and we need to get the weight between the last . and } */
1620
export function getColorNumber(value: string): ColorNumber | undefined {
17-
const firstSplit = value.split('.').pop()?.replace('}', '');
18-
19-
const parsed = parseInt(firstSplit as string);
21+
const digit = value.match(/^\d+$/)?.[0];
22+
const parsed = parseInt(digit || '');
2023

2124
return Number.isNaN(parsed) ? undefined : (parsed as ColorNumber);
2225
}
@@ -25,30 +28,39 @@ const TokenColor = ({ value, token }: TokenColorProps) => {
2528
const colorModalRef = useRef<HTMLDialogElement>(null);
2629

2730
const number = getColorNumber(token.original.$value as string);
28-
const Element = number ? 'button' : 'div';
31+
const color: Color | undefined = number
32+
? {
33+
...getColorMetadataByNumber(number),
34+
number,
35+
hex: value,
36+
}
37+
: undefined;
38+
39+
const namespace = token.path[1];
2940

30-
return (
41+
return color ? (
3142
<>
32-
{number ? (
33-
<ColorModal
34-
number={number}
35-
hex={value}
36-
namespace={token.path[1]}
37-
colorModalRef={colorModalRef}
38-
/>
39-
) : null}
40-
<div className={classes.test}>
41-
<Element
43+
<ColorModal
44+
namespace={namespace}
45+
colorModalRef={colorModalRef}
46+
color={color}
47+
/>
48+
<div className={classes.colorBox}>
49+
<button
4250
style={{ backgroundColor: value }}
4351
className={cl(classes.color, 'ds-focus')}
44-
onClick={() => number && colorModalRef.current?.showModal()}
45-
aria-label={
46-
number &&
47-
`Se mer om ${token.path[1]} ${getColorInfoFromPosition(number).displayName}`
48-
}
49-
></Element>
52+
onClick={() => colorModalRef.current?.showModal()}
53+
aria-label={`Se mer om ${namespace} ${color?.displayName}`}
54+
></button>
5055
</div>
5156
</>
57+
) : (
58+
<div className={classes.colorBox}>
59+
<div
60+
style={{ backgroundColor: value }}
61+
className={cl(classes.color, 'ds-focus')}
62+
></div>
63+
</div>
5264
);
5365
};
5466

apps/theme/app/page.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ export default function Home() {
5656
return (
5757
<div>
5858
<ColorModal
59-
number={selectedColor.color.number}
60-
hex={selectedColor.color.hex}
59+
color={selectedColor.color}
6160
namespace={'d'}
6261
colorModalRef={colorModalRef}
6362
/>

apps/theme/app/testside/BackgroundSurface/BackgroundSurface.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client';
22

33
import { Heading } from '@digdir/designsystemet-react';
4-
import type { ColorInfo, ThemeInfo } from '@digdir/designsystemet/color';
4+
import type { Color, ThemeInfo } from '@digdir/designsystemet/color';
55

66
import classes from './BackgroundSurface.module.css';
77

@@ -75,7 +75,7 @@ export const BackgroundSurface = ({
7575

7676
type ColumnProps = {
7777
title: string;
78-
scales: ColorInfo[][];
78+
scales: Color[][];
7979
};
8080

8181
const Column = ({ title, scales }: ColumnProps) => {
@@ -94,9 +94,9 @@ const Column = ({ title, scales }: ColumnProps) => {
9494
};
9595

9696
type BoxProps = {
97-
colorScale: ColorInfo[];
97+
colorScale: Color[];
9898
backgroundIndex: 0 | 1;
99-
scales: ColorInfo[][];
99+
scales: Color[][];
100100
};
101101

102102
const Box = ({ colorScale, backgroundIndex, scales }: BoxProps) => {

apps/theme/app/testside/BaseContrast/BaseContrast.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22
import { Heading } from '@digdir/designsystemet-react';
3-
import type { ColorInfo, ThemeInfo } from '@digdir/designsystemet/color';
3+
import type { Color, ThemeInfo } from '@digdir/designsystemet/color';
44

55
import { ContrastBox } from '../ContrastBox/ContrastBox';
66

@@ -44,7 +44,7 @@ const BaseColumn = ({ colorTheme, title }: BaseColumnProps) => {
4444
};
4545

4646
type BaseBoxProps = {
47-
colorScale: ColorInfo[];
47+
colorScale: Color[];
4848
title: string;
4949
};
5050

apps/theme/app/testside/Interaction/Interaction.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22
import { Heading } from '@digdir/designsystemet-react';
3-
import type { ColorInfo, ThemeInfo } from '@digdir/designsystemet/color';
3+
import type { Color, ThemeInfo } from '@digdir/designsystemet/color';
44
import cl from 'clsx/lite';
55
import { useEffect } from 'react';
66

@@ -96,7 +96,7 @@ export const Interaction = ({
9696

9797
type ColumnProps = {
9898
title: string;
99-
scales: ColorInfo[][];
99+
scales: Color[][];
100100
};
101101

102102
const Column = ({ title, scales }: ColumnProps) => {
@@ -128,7 +128,7 @@ const Column = ({ title, scales }: ColumnProps) => {
128128

129129
type BoxProps = {
130130
colorIndex: number;
131-
scales: ColorInfo[][];
131+
scales: Color[][];
132132
type: 'base' | 'surface';
133133
columnTitle: string;
134134
};

apps/theme/app/testside/page.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client';
22

33
import { Heading } from '@digdir/designsystemet-react';
4-
import type { ColorInfo, CssColor } from '@digdir/designsystemet/color';
4+
import type { Color, CssColor } from '@digdir/designsystemet/color';
55
import { generateColorSchemes } from '@digdir/designsystemet/color';
66
import { Container } from '@repo/components';
77
import cl from 'clsx/lite';
@@ -28,7 +28,7 @@ const Box = (name: string, color1: CssColor, color2: CssColor) => {
2828
);
2929
};
3030

31-
const Row = (title: string, colors: ColorInfo[], whiteText = false) => {
31+
const Row = (title: string, colors: Color[], whiteText = false) => {
3232
return (
3333
<div className={cl(whiteText && classes.whiteText)}>
3434
<Heading data-size='xs' className={classes.mainTitle}>

apps/theme/app/themebuilder/_components/ThemePages.tsx

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
'use client';
22

33
import {
4-
type ColorInfo,
4+
type Color,
55
type ColorNumber,
6-
getColorInfoFromPosition,
6+
getColorMetadataByNumber,
77
} from '@digdir/designsystemet';
88
import cl from 'clsx/lite';
99
import { useEffect, useRef } from 'react';
@@ -45,8 +45,8 @@ export const ThemePages = () => {
4545
}, [baseBorderRadius]);
4646

4747
const getDsVars = (colors: {
48-
light: ColorInfo[];
49-
dark: ColorInfo[];
48+
light: Color[];
49+
dark: Color[];
5050
}) => {
5151
const style = {} as Record<string, string>;
5252

@@ -59,7 +59,7 @@ export const ThemePages = () => {
5959
for (let i = 0; i < lightColors.length; i++) {
6060
const number = (i + 1) as ColorNumber;
6161
style[
62-
`--ds-color-neutral-${getColorInfoFromPosition(number)
62+
`--ds-color-neutral-${getColorMetadataByNumber(number)
6363
.displayName.replace(/\s+/g, '-')
6464
.toLowerCase()}`
6565
] = lightColors[i].hex;
@@ -69,8 +69,8 @@ export const ThemePages = () => {
6969
};
7070

7171
const getDsMainVars = (colors: {
72-
light: ColorInfo[];
73-
dark: ColorInfo[];
72+
light: Color[];
73+
dark: Color[];
7474
}) => {
7575
const style = {} as Record<string, string>;
7676

@@ -83,7 +83,7 @@ export const ThemePages = () => {
8383
for (let i = 0; i < lightColors.length; i++) {
8484
const number = (i + 1) as ColorNumber;
8585
style[
86-
`--ds-color-${getColorInfoFromPosition(number)
86+
`--ds-color-${getColorMetadataByNumber(number)
8787
.displayName.replace(/\s+/g, '-')
8888
.toLowerCase()}`
8989
] = lightColors[i].hex;

apps/theme/components/ColorContrasts/ColorContrasts.tsx

+6-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
2-
type ColorInfo,
2+
type Color,
33
generateColorSchemes,
4-
getColorInfoFromPosition,
4+
getColorMetadataByNumber,
55
getContrastFromHex,
66
} from '@digdir/designsystemet';
77
import {
@@ -79,21 +79,18 @@ export const ColorContrasts = () => {
7979
});
8080
}, [selectedBaseColor, colors, colorScheme]);
8181

82-
const ThCell = ({ color }: { color: ColorInfo }) => {
82+
const ThCell = ({ color }: { color: Color }) => {
8383
return (
8484
<th className={classes.th}>
8585
<div className={classes.header}>
86-
{getColorInfoFromPosition(color.number).displayName}
86+
{getColorMetadataByNumber(color.number).displayName}
8787
<div className={classes.headerHex}>{color.hex}</div>
8888
</div>
8989
</th>
9090
);
9191
};
9292

93-
const Tag = ({
94-
color1,
95-
color2,
96-
}: { color1: ColorInfo; color2: ColorInfo }) => {
93+
const Tag = ({ color1, color2 }: { color1: Color; color2: Color }) => {
9794
const contrast = getContrastFromHex(color1.hex, color2.hex);
9895
let type = 'AAA';
9996

@@ -108,10 +105,7 @@ export const ColorContrasts = () => {
108105
return <div className={cl(classes.tag, classes[type])}>{type}</div>;
109106
};
110107

111-
const TdCell = ({
112-
color1,
113-
color2,
114-
}: { color1: ColorInfo; color2: ColorInfo }) => {
108+
const TdCell = ({ color1, color2 }: { color1: Color; color2: Color }) => {
115109
return (
116110
<div className={classes.cell}>
117111
<div className={classes.colors}>

apps/theme/components/ColorPreview/ColorPreview.tsx

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
2-
type ColorInfo,
2+
type Color,
33
type ColorNumber,
4-
getColorInfoFromPosition,
4+
getColorMetadataByNumber,
55
} from '@digdir/designsystemet';
66
import {
77
Button,
@@ -28,15 +28,15 @@ export const ColorPreview = () => {
2828
color: {
2929
name: string;
3030
colors: {
31-
light: ColorInfo[];
32-
dark: ColorInfo[];
31+
light: Color[];
32+
dark: Color[];
3333
};
3434
};
3535
};
3636

3737
const setStyle = (colors: {
38-
light: ColorInfo[];
39-
dark: ColorInfo[];
38+
light: Color[];
39+
dark: Color[];
4040
}) => {
4141
const style = {} as Record<string, string>;
4242

@@ -49,12 +49,12 @@ export const ColorPreview = () => {
4949
for (let i = 0; i < lightColors.length; i++) {
5050
const number = (i + 1) as ColorNumber;
5151
style[
52-
`--ds-color-accent-${getColorInfoFromPosition(number)
52+
`--ds-color-accent-${getColorMetadataByNumber(number)
5353
.displayName.replace(/\s+/g, '-')
5454
.toLowerCase()}`
5555
] = lightColors[i].hex;
5656
style[
57-
`--ds-color-${getColorInfoFromPosition(number)
57+
`--ds-color-${getColorMetadataByNumber(number)
5858
.displayName.replace(/\s+/g, '-')
5959
.toLowerCase()}`
6060
] = lightColors[i].hex;

0 commit comments

Comments
 (0)