feat: add configurable highlight colors

- Add highlightColor setting with 6 preset colors (yellow, orange, pink, green, blue, purple)
- Implement color picker UI with square color swatches
- Use CSS variables to dynamically apply highlight colors
- Add hex to RGB conversion for color transparency support
- Update both marker and underline styles to use selected color
This commit is contained in:
Gigi
2025-10-05 04:12:31 +01:00
parent b59a295ad3
commit e4b6d1a122
5 changed files with 106 additions and 19 deletions

View File

@@ -131,6 +131,7 @@ const Bookmarks: React.FC<BookmarksProps> = ({ relayPool, onLogout }) => {
highlights={highlights}
showUnderlines={showUnderlines}
highlightStyle={settings.highlightStyle || 'marker'}
highlightColor={settings.highlightColor || '#ffff00'}
onHighlightClick={(id) => {
setSelectedHighlightId(id)
if (isHighlightsCollapsed) setIsHighlightsCollapsed(false)

View File

@@ -8,6 +8,14 @@ import { applyHighlightsToHTML } from '../utils/highlightMatching'
import { readingTime } from 'reading-time-estimator'
import { filterHighlightsByUrl } from '../utils/urlHelpers'
// Helper to convert hex color to RGB values
function hexToRgb(hex: string): string {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
return result
? `${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}`
: '255, 255, 0'
}
interface ContentPanelProps {
loading: boolean
title?: string
@@ -17,6 +25,7 @@ interface ContentPanelProps {
highlights?: Highlight[]
showUnderlines?: boolean
highlightStyle?: 'marker' | 'underline'
highlightColor?: string
onHighlightClick?: (highlightId: string) => void
selectedHighlightId?: string
}
@@ -30,6 +39,7 @@ const ContentPanel: React.FC<ContentPanelProps> = ({
highlights = [],
showUnderlines = true,
highlightStyle = 'marker',
highlightColor = '#ffff00',
onHighlightClick,
selectedHighlightId
}) => {
@@ -151,8 +161,10 @@ const ContentPanel: React.FC<ContentPanelProps> = ({
)
}
const highlightRgb = hexToRgb(highlightColor)
return (
<div className="reader">
<div className="reader" style={{ '--highlight-rgb': highlightRgb } as React.CSSProperties}>
{title && (
<div className="reader-header">
<h2 className="reader-title">{title}</h2>

View File

@@ -4,6 +4,14 @@ import { UserSettings } from '../services/settingsService'
import IconButton from './IconButton'
import { loadFont, getFontFamily } from '../utils/fontLoader'
// Helper to convert hex color to RGB values
function hexToRgb(hex: string): string {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
return result
? `${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}`
: '255, 255, 0'
}
interface SettingsProps {
settings: UserSettings
onSave: (settings: UserSettings) => Promise<void>
@@ -131,14 +139,38 @@ const Settings: React.FC<SettingsProps> = ({ settings, onSave, onClose }) => {
</div>
</div>
<div className="setting-group setting-inline">
<label>Highlight Color</label>
<div className="color-picker">
{[
{ name: 'Yellow', value: '#ffff00' },
{ name: 'Orange', value: '#ff9500' },
{ name: 'Pink', value: '#ff69b4' },
{ name: 'Green', value: '#00ff7f' },
{ name: 'Blue', value: '#4da6ff' },
{ name: 'Purple', value: '#b19cd9' }
].map(color => (
<button
key={color.value}
onClick={() => setLocalSettings({ ...localSettings, highlightColor: color.value })}
className={`color-swatch ${(localSettings.highlightColor || '#ffff00') === color.value ? 'active' : ''}`}
style={{ backgroundColor: color.value }}
title={color.name}
aria-label={`${color.name} highlight color`}
/>
))}
</div>
</div>
<div className="setting-preview">
<div className="preview-label">Preview</div>
<div
className="preview-content"
style={{
fontFamily: previewFontFamily,
fontSize: `${localSettings.fontSize || 16}px`
}}
fontSize: `${localSettings.fontSize || 16}px`,
'--highlight-rgb': hexToRgb(localSettings.highlightColor || '#ffff00')
} as React.CSSProperties}
>
<h3>The Quick Brown Fox</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. <span className={localSettings.showUnderlines !== false ? `content-highlight-${localSettings.highlightStyle || 'marker'}` : ""}>Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</span> Ut enim ad minim veniam.</p>