Skip to content

Commit 227226f

Browse files
committed
refactor(theme-generator): replace culori with @ant-design/colors
1 parent 0c32a09 commit 227226f

File tree

16 files changed

+146
-153
lines changed

16 files changed

+146
-153
lines changed

packages/storybook/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
"start": "yarn generate:versions && storybook dev -p 6006 --no-open"
1212
},
1313
"dependencies": {
14+
"@ant-design/colors": "7.1.0",
1415
"@ark-ui/react": "5.25.1",
1516
"@ovhcloud/ods-react": "19.2.1",
1617
"@ovhcloud/ods-themes": "19.2.1",
1718
"classnames": "2.5.1",
18-
"culori": "4.0.2",
1919
"lz-string": "1.5.0",
2020
"prettier": "3.6.2",
2121
"react": "18.2.0",
@@ -30,7 +30,6 @@
3030
"@storybook/react": "8.6.12",
3131
"@storybook/react-vite": "8.6.12",
3232
"@storybook/types": "8.6.12",
33-
"@types/culori": "4.0.1",
3433
"custom-elements-manifest": "1.0.0",
3534
"node-fetch": "2.7.0",
3635
"prop-types": "15.8.1",

packages/storybook/src/components/themeGenerator/ThemeGeneratorColorPicker/ThemeGeneratorColorPicker.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,14 @@ const ThemeGeneratorColorPicker = ({
8585
{label}
8686
</ColorPicker.Label>
8787
)}
88-
8988
<ColorPicker.Control className={styles['theme-generator-color-picker__control']}>
89+
<ColorPicker.ChannelInput
90+
asChild
91+
channel="hex"
92+
onKeyDown={(e) => e.stopPropagation()}
93+
>
94+
<Input type="text" />
95+
</ColorPicker.ChannelInput>
9096
<ColorPicker.Trigger className={styles['theme-generator-color-picker__control__trigger']}>
9197
<ColorPicker.ValueSwatch className={styles['theme-generator-color-picker__control__trigger__swatch']} />
9298
</ColorPicker.Trigger>

packages/storybook/src/components/themeGenerator/ThemeGeneratorColorPicker/index.ts

Lines changed: 0 additions & 2 deletions
This file was deleted.

packages/storybook/src/components/themeGenerator/ThemeGeneratorColorPicker/themeGeneratorColorPicker.module.css

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.theme-generator-color-picker {
22
display: flex;
3-
gap: 0.5rem;
3+
gap: 8px;
44
align-items: center;
55
justify-content: space-between;
66
width: 100%;
@@ -28,7 +28,7 @@
2828
}
2929

3030
.theme-generator-color-picker__control__trigger:disabled {
31-
opacity: 0.5;
31+
opacity: 1;
3232
cursor: not-allowed;
3333
}
3434

@@ -128,4 +128,3 @@
128128
gap: 8px;
129129
min-width: 200px;
130130
}
131-

packages/storybook/src/components/themeGenerator/ThemeGeneratorTreeView/ThemeGeneratorTreeView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Spinner, Text, TreeView, TreeViewNode, TreeViewNodes, SPINNER_SIZE, TEXT_PRESET } from '@ovhcloud/ods-react';
22
import React, { useMemo } from 'react';
33
import { categorizeCssVariables } from '../themeVariableUtils';
4-
import { ThemeGeneratorColorPicker } from '../ThemeGeneratorColorPicker';
4+
import { ThemeGeneratorColorPicker } from '../ThemeGeneratorColorPicker/ThemeGeneratorColorPicker';
55
import styles from './themeGeneratorTreeView.module.css';
66

77
interface TreeItem {

packages/storybook/src/components/themeGenerator/ThemeGeneratorTreeView/themeGeneratorTreeView.module.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66

77
.theme-generator-tree-view__loading {
88
display: flex;
9-
align-items: center;
109
gap: 8px;
10+
align-items: center;
1111
margin: 16px;
1212
}
1313

1414
.theme-generator-tree-view__item {
1515
display: flex;
16-
gap: 0.5rem;
16+
gap: 8px;
1717
align-items: center;
1818
justify-content: space-between;
1919
width: 100%;

packages/storybook/src/components/themeGenerator/themeGenerator.module.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
}
5353

5454
.theme-generator__container__resize--vertical {
55-
margin: 2px 16px ;
55+
margin: 2px 16px;
5656
height: 4px;
5757
min-height: auto;
5858
}

packages/storybook/src/components/themeGenerator/themeGeneratorJSONModal/ThemeGeneratorJSONModal.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,3 @@ const ThemeGeneratorJSONModal = ({ open, variables, onClose, onReplace }: ThemeG
8282
};
8383

8484
export { ThemeGeneratorJSONModal };
85-
86-

packages/storybook/src/components/themeGenerator/themeGeneratorJSONModal/themeGeneratorJSONModal.module.css

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,3 @@
2525
.theme-generator-json-modal__error {
2626
color: var(--ods-color-critical-600);
2727
}
28-
29-

packages/storybook/src/components/themeGenerator/themeGeneratorPaletteModal/ThemeGeneratorPaletteModal.tsx

Lines changed: 75 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
import React, { type JSX, useState, useEffect, useMemo } from 'react';
22
import { Button, BUTTON_VARIANT, Modal, ModalBody, ModalContent, Text, TreeView, TreeViewNode, TreeViewNodes } from '@ovhcloud/ods-react';
3-
43
import styles from './themeGeneratorPaletteModal.module.css';
54
import { generatePalette, formatPaletteAsCssVariables, COLOR_FAMILIES, PALETTE_STEPS, type ColorFamily, type PaletteResult } from './paletteGenerator';
6-
import { ThemeGeneratorColorPicker } from '../ThemeGeneratorColorPicker';
5+
import { ThemeGeneratorColorPicker } from '../ThemeGeneratorColorPicker/ThemeGeneratorColorPicker';
6+
7+
const ODS_COLOR_PREFIX = '--ods-color';
8+
9+
/**
10+
* Builds a CSS variable name for a color token
11+
* @param family - Color family (e.g., 'primary', 'neutral')
12+
* @param step - Optional color step (e.g., '500', '100')
13+
* @returns CSS variable name (e.g., '--ods-color-primary-500')
14+
*/
15+
function buildColorVar(family: string, step?: string): string {
16+
return step ? `${ODS_COLOR_PREFIX}-${family}-${step}` : `${ODS_COLOR_PREFIX}-${family}`;
17+
}
718

819
interface TreeItem {
920
id: string;
@@ -22,35 +33,31 @@ interface ThemeGeneratorPaletteModalProps {
2233
const ThemeGeneratorPaletteModal = ({ open, onClose, onApply, currentVariables }: ThemeGeneratorPaletteModalProps): JSX.Element => {
2334
const [generatedPalettes, setGeneratedPalettes] = useState<Record<ColorFamily, PaletteResult>>({} as Record<ColorFamily, PaletteResult>);
2435
const [seedColors, setSeedColors] = useState<Record<ColorFamily, string>>({} as Record<ColorFamily, string>);
36+
const [errors, setErrors] = useState<Partial<Record<ColorFamily, string>>>({});
2537

2638
useEffect(() => {
2739
const initialSeeds: Record<ColorFamily, string> = {} as Record<ColorFamily, string>;
2840
COLOR_FAMILIES.forEach((family) => {
29-
const defaultColorVar = `--ods-color-${family}-500`;
41+
const defaultColorVar = buildColorVar(family, '500');
3042
initialSeeds[family] = currentVariables[defaultColorVar] || '#000000';
3143
});
3244
setSeedColors(initialSeeds);
3345
}, [currentVariables]);
3446

3547
const treeItems = useMemo(() => {
3648
return COLOR_FAMILIES.map((family) => {
37-
let palette: PaletteResult;
38-
39-
if (generatedPalettes[family]) {
40-
palette = generatedPalettes[family];
41-
} else {
42-
palette = {};
43-
for (const step of PALETTE_STEPS) {
44-
const varName = `--ods-color-${family}-${step}`;
45-
palette[step] = currentVariables[varName] || '#000000';
46-
}
47-
}
48-
49-
const children: TreeItem[] = PALETTE_STEPS.map((step) => ({
50-
id: `${family}-${step}`,
51-
name: `--ods-color-${family}-${step}`,
52-
value: palette[step] || '#000000',
53-
}));
49+
const palette = generatedPalettes[family];
50+
51+
const children: TreeItem[] = PALETTE_STEPS.map((step) => {
52+
const varName = buildColorVar(family, step);
53+
const value = palette?.[step] || currentVariables[varName] || '#000000';
54+
55+
return {
56+
id: `${family}-${step}`,
57+
name: varName,
58+
value,
59+
};
60+
});
5461

5562
return {
5663
id: family,
@@ -72,6 +79,13 @@ const ThemeGeneratorPaletteModal = ({ open, onClose, onApply, currentVariables }
7279
[family]: color,
7380
}));
7481

82+
// Clear previous error for this family
83+
setErrors(prev => {
84+
const newErrors = { ...prev };
85+
delete newErrors[family];
86+
return newErrors;
87+
});
88+
7589
// Generate palette automatically when seed color changes
7690
try {
7791
const palette = generatePalette(color);
@@ -80,7 +94,11 @@ const ThemeGeneratorPaletteModal = ({ open, onClose, onApply, currentVariables }
8094
[family]: palette,
8195
}));
8296
} catch (error) {
83-
console.error('Failed to generate palette:', error);
97+
const errorMessage = error instanceof Error ? error.message : 'Failed to generate palette';
98+
setErrors(prev => ({
99+
...prev,
100+
[family]: errorMessage,
101+
}));
84102
}
85103
}
86104

@@ -108,31 +126,42 @@ const ThemeGeneratorPaletteModal = ({ open, onClose, onApply, currentVariables }
108126
<TreeViewNodes>
109127
{treeItems.map((item) => (
110128
<TreeViewNode key={item.id} item={item}>
111-
{({ item, isBranch }: { item: TreeItem; isBranch: boolean }) => (
112-
<div className={styles['theme-generator-palette-modal__preview__tree-view__tree-item']}>
113-
{isBranch ? (
114-
<>
115-
<Text className={styles['theme-generator-palette-modal__preview__tree-view__tree-item__name']}>
116-
{item.name}
117-
</Text>
118-
<ThemeGeneratorColorPicker
119-
value={seedColors[item.id as ColorFamily] || '#000000'}
120-
onChange={(color) => handleSeedColorChange(item.id as ColorFamily, color)}
121-
showLabel={false}
122-
/>
123-
</>
124-
) : (
125-
item.value && (
126-
<ThemeGeneratorColorPicker
127-
label={item.name}
128-
value={item.value}
129-
onChange={() => {}}
130-
disabled
131-
/>
132-
)
133-
)}
134-
</div>
135-
)}
129+
{({ item, isBranch }: { item: TreeItem; isBranch: boolean }) => {
130+
const familyError = isBranch ? errors[item.id as ColorFamily] : undefined;
131+
132+
return (
133+
<div className={styles['theme-generator-palette-modal__preview__tree-view__tree-item']}>
134+
{isBranch ? (
135+
<>
136+
<div className={styles['theme-generator-palette-modal__preview__tree-view__tree-item__header']}>
137+
<Text className={styles['theme-generator-palette-modal__preview__tree-view__tree-item__name']}>
138+
{item.name}
139+
</Text>
140+
<ThemeGeneratorColorPicker
141+
value={seedColors[item.id as ColorFamily] || '#000000'}
142+
onChange={(color) => handleSeedColorChange(item.id as ColorFamily, color)}
143+
showLabel={false}
144+
/>
145+
</div>
146+
{familyError && (
147+
<Text className={styles['theme-generator-palette-modal__preview__tree-view__tree-item__error']}>
148+
{familyError}
149+
</Text>
150+
)}
151+
</>
152+
) : (
153+
item.value && (
154+
<ThemeGeneratorColorPicker
155+
label={item.name}
156+
value={item.value}
157+
onChange={() => {}}
158+
disabled
159+
/>
160+
)
161+
)}
162+
</div>
163+
);
164+
}}
136165
</TreeViewNode>
137166
))}
138167
</TreeViewNodes>

0 commit comments

Comments
 (0)