feat(settings): add custom highlight color picker (#2273)

Add ability to customize highlight colors with hex color picker. Users can now set custom colors for all five highlight styles (red, violet, blue, green, yellow) in the settings panel.

Fixes #2271
This commit is contained in:
AlI
2025-10-19 18:33:59 +03:30
committed by GitHub
parent f66642b8ec
commit cd71c494da
6 changed files with 121 additions and 23 deletions
@@ -142,7 +142,8 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
const detail = (event as CustomEvent).detail;
const { draw, annotation, doc, range } = detail;
const { style, color } = annotation as BookNote;
const hexColor = color ? HIGHLIGHT_COLOR_HEX[color] : color;
const customColors = settings.globalReadSettings.customHighlightColors;
const hexColor = color && customColors ? customColors[color] : color ? HIGHLIGHT_COLOR_HEX[color] : color;
if (style === 'highlight') {
draw(Overlayer.highlight, { color: hexColor });
} else if (['underline', 'squiggly'].includes(style as string)) {
@@ -4,6 +4,7 @@ import { FaCheckCircle } from 'react-icons/fa';
import { HighlightColor, HighlightStyle } from '@/types/book';
import { useSettingsStore } from '@/store/settingsStore';
import { useResponsiveSize } from '@/hooks/useResponsiveSize';
import { DEFAULT_CUSTOM_HIGHLIGHT_COLORS } from '@/services/constants';
const styles = ['highlight', 'underline', 'squiggly'] as HighlightStyle[];
const colors = ['red', 'violet', 'blue', 'green', 'yellow'] as HighlightColor[];
@@ -25,6 +26,7 @@ const HighlightOptions: React.FC<HighlightOptionsProps> = ({
}) => {
const { settings, setSettings } = useSettingsStore();
const globalReadSettings = settings.globalReadSettings;
const customColors = globalReadSettings.customHighlightColors || DEFAULT_CUSTOM_HIGHLIGHT_COLORS;
const [selectedStyle, setSelectedStyle] = React.useState<HighlightStyle>(_selectedStyle);
const [selectedColor, setSelectedColor] = React.useState<HighlightColor>(_selectedColor);
const size16 = useResponsiveSize(16);
@@ -65,24 +67,26 @@ const HighlightOptions: React.FC<HighlightOptionsProps> = ({
style={{ width: size28, height: size28, minHeight: size28 }}
>
<div
style={{ width: size16, height: style === 'squiggly' ? size18 : size16 }}
className={clsx(
'w-4 p-0 text-center leading-none',
style === 'highlight' &&
(selectedStyle === 'highlight'
? `bg-${selectedColor}-300 pt-[2px]`
: `bg-gray-300 pt-[2px]`),
(style === 'underline' || style === 'squiggly') &&
'text-gray-300 underline decoration-2',
style === 'underline' &&
(selectedStyle === 'underline'
? `decoration-${selectedColor}-300`
: `decoration-gray-300`),
style === 'squiggly' &&
(selectedStyle === 'squiggly'
? `decoration-wavy decoration-${selectedColor}-300`
: `decoration-gray-300 decoration-wavy`),
)}
style={{
width: size16,
height: style === 'squiggly' ? size18 : size16,
...(style === 'highlight' && selectedStyle === 'highlight' && {
backgroundColor: customColors[selectedColor],
paddingTop: '2px'
}),
...(style === 'highlight' && selectedStyle !== 'highlight' && {
backgroundColor: '#d1d5db',
paddingTop: '2px'
}),
...((style === 'underline' || style === 'squiggly') && {
color: '#d1d5db',
textDecoration: 'underline',
textDecorationThickness: '2px',
textDecorationColor: selectedStyle === style ? customColors[selectedColor] : '#d1d5db',
...(style === 'squiggly' && { textDecorationStyle: 'wavy' })
})
}}
className='w-4 p-0 text-center leading-none'
>
A
</div>
@@ -101,11 +105,15 @@ const HighlightOptions: React.FC<HighlightOptionsProps> = ({
<button
key={color}
onClick={() => handleSelectColor(color)}
style={{ width: size16, height: size16 }}
className={clsx(`rounded-full p-0`, selectedColor !== color && `bg-${color}-300`)}
style={{
width: size16,
height: size16,
backgroundColor: selectedColor !== color ? customColors[color] : 'transparent'
}}
className='rounded-full p-0'
>
{selectedColor === color && (
<FaCheckCircle size={size16} className={clsx(`fill-${color}-300`)} />
<FaCheckCircle size={size16} style={{ fill: customColors[color] }} />
)}
</button>
))}