diff --git a/src/common/components/modal-popup/theme-popup.js b/src/common/components/modal-popup/theme-popup.js
index 19f10d90..91627f82 100644
--- a/src/common/components/modal-popup/theme-popup.js
+++ b/src/common/components/modal-popup/theme-popup.js
@@ -88,10 +88,14 @@ function ThemePopup({ params, customThemes, colorScheme, lightTheme, darkTheme,
let currentTheme = currentColorScheme === 'light' ? lightTheme : darkTheme;
let bg = '#FFFFFF';
let fg = '#000000';
+ let lc = '#0000EE';
+ let vlc = '#551A8B';
let inv = false;
if (currentTheme) {
bg = currentTheme.background;
fg = currentTheme.foreground;
+ lc = currentTheme.linkColor || '';
+ vlc = currentTheme.visitedLinkColor || '';
inv = currentTheme.invertImages;
}
@@ -99,6 +103,8 @@ function ThemePopup({ params, customThemes, colorScheme, lightTheme, darkTheme,
let [label, setLabel] = useState(params.theme?.label || '');
let [background, setBackground] = useState(params.theme?.background || bg);
let [foreground, setForeground] = useState(params.theme?.foreground || fg);
+ let [linkColor, setLinkColor] = useState(params.theme?.linkColor || params.theme?.foreground || lc);
+ let [visitedLinkColor, setVisitedLinkColor] = useState(params.theme?.visitedLinkColor || params.theme?.foreground || vlc);
let [invertImages, setInvertImages] = useState(params.theme?.invertImages ?? inv);
let themeIsDark = isDarkTheme(background, foreground);
@@ -136,6 +142,18 @@ function ThemePopup({ params, customThemes, colorScheme, lightTheme, darkTheme,
theme.label = label.trim();
theme.background = background;
theme.foreground = foreground;
+ if (linkColor && isValidHexColor(linkColor)) {
+ theme.linkColor = linkColor;
+ }
+ else {
+ delete theme.linkColor;
+ }
+ if (visitedLinkColor && isValidHexColor(visitedLinkColor)) {
+ theme.visitedLinkColor = visitedLinkColor;
+ }
+ else {
+ delete theme.visitedLinkColor;
+ }
if (invertImages) {
theme.invertImages = true;
}
@@ -181,6 +199,8 @@ function ThemePopup({ params, customThemes, colorScheme, lightTheme, darkTheme,
!nameInvalid
&& isValidHexColor(background)
&& isValidHexColor(foreground)
+ && (!linkColor || isValidHexColor(linkColor))
+ && (!visitedLinkColor || isValidHexColor(visitedLinkColor))
);
return (
@@ -202,6 +222,10 @@ function ThemePopup({ params, customThemes, colorScheme, lightTheme, darkTheme,
diff --git a/src/common/defines.js b/src/common/defines.js
index fab092bf..083fe470 100644
--- a/src/common/defines.js
+++ b/src/common/defines.js
@@ -49,12 +49,16 @@ export const INK_ANNOTATION_WIDTH_STEPS = [
export const TEXT_ANNOTATION_FONT_SIZE_STEPS = [6, 8, 10, 12, 14, 18, 24, 36, 48, 64, 72, 96, 144, 192];
export const DEFAULT_THEMES = [
- { id: 'dark', label: 'Dark', background: "#2E3440", foreground: "#D8DEE9" },
- { id: 'black', label: 'Black', background: "#000000", foreground: "#FFFFFF", invertImages: true },
- { id: 'snow', label: 'Snow', background: "#ECEFF4", foreground: "#3B4252" },
- { id: 'sepia', label: 'Sepia', background: "#F4ECD8", foreground: "#5B4636" }
+ { id: 'dark', label: 'Dark', background: "#2E3440", foreground: "#D8DEE9", linkColor: "#88C0D0", visitedLinkColor: "#6E9FAB" },
+ { id: 'black', label: 'Black', background: "#000000", foreground: "#FFFFFF", linkColor: "#6CB6FF", visitedLinkColor: "#5A92CC", invertImages: true },
+ { id: 'snow', label: 'Snow', background: "#ECEFF4", foreground: "#3B4252", linkColor: "#4C6E96", visitedLinkColor: "#3D5975" },
+ { id: 'sepia', label: 'Sepia', background: "#F4ECD8", foreground: "#5B4636", linkColor: "#8A4F3D", visitedLinkColor: "#6E3F31" }
];
+export const ORIGINAL_THEME = {
+ id: 'light', label: '', background: "#FFFFFF", foreground: "#121212", linkColor: "#0000EE", visitedLinkColor: "#551A8B"
+};
+
export const A11Y_VIRT_CURSOR_DEBOUNCE_LENGTH = 500; // ms
export const READ_ALOUD_SEGMENT_MAX_LENGTH = 5000; // UTF-8 bytes
diff --git a/src/common/types.ts b/src/common/types.ts
index 5ad6fc68..f051c8b2 100644
--- a/src/common/types.ts
+++ b/src/common/types.ts
@@ -289,6 +289,8 @@ export type Theme = {
label: string;
background: string;
foreground: string;
+ linkColor?: string;
+ visitedLinkColor?: string;
invertImages?: boolean;
};
diff --git a/src/dom/common/dom-view.tsx b/src/dom/common/dom-view.tsx
index c5ee0944..adc919fe 100644
--- a/src/dom/common/dom-view.tsx
+++ b/src/dom/common/dom-view.tsx
@@ -41,6 +41,7 @@ import {
import { getSelectionRanges, makeDragImageForTextSelection } from "./lib/selection";
import { FindProcessor } from "./lib/find";
import {
+ ORIGINAL_THEME,
READ_ALOUD_ACTIVE_SEGMENT_COLOR,
READ_ALOUD_ACTIVE_SENTENCE_COLOR,
SELECTION_COLOR
@@ -944,12 +945,7 @@ abstract class DOMView {
theme = this._darkTheme;
}
else {
- theme = {
- id: 'light',
- label: '',
- background: '#ffffff',
- foreground: '#121212'
- };
+ theme = { ...ORIGINAL_THEME };
}
let themeColorScheme = getModeBasedOnColors(theme.background, theme.foreground);
@@ -960,6 +956,8 @@ abstract class DOMView {
root.style.colorScheme = themeColorScheme;
root.style.setProperty('--background-color', theme.background);
root.style.setProperty('--text-color', theme.foreground);
+ root.style.setProperty('--link-color', theme.linkColor || theme.foreground);
+ root.style.setProperty('--visited-link-color', theme.visitedLinkColor || theme.linkColor || theme.foreground);
}
this._theme = theme;
diff --git a/src/dom/epub/stylesheets/_content.scss b/src/dom/epub/stylesheets/_content.scss
index 884342aa..6af4f4f6 100644
--- a/src/dom/epub/stylesheets/_content.scss
+++ b/src/dom/epub/stylesheets/_content.scss
@@ -41,15 +41,6 @@
}
}
-:root {
- --link-color: #0000ee;
- --visited-link-color: #551a8b;
-
- &[data-color-scheme="dark"] {
- --link-color: #63caff;
- --visited-link-color: #0099e5;
- }
-}
:root {
background-color: var(--background-color) !important;
diff --git a/src/dom/sdt/stylesheets/sdt.scss b/src/dom/sdt/stylesheets/sdt.scss
index e3493083..4dc9aa36 100644
--- a/src/dom/sdt/stylesheets/sdt.scss
+++ b/src/dom/sdt/stylesheets/sdt.scss
@@ -18,14 +18,6 @@
font-size: 1.1rem;
background-color: var(--background-color);
color: var(--text-color);
-
- --link-color: #0000ee;
- --visited-link-color: #551a8b;
-
- &[data-color-scheme="dark"] {
- --link-color: #63caff;
- --visited-link-color: #0099e5;
- }
}
body {
diff --git a/src/dom/snapshot/stylesheets/inject.scss b/src/dom/snapshot/stylesheets/inject.scss
index 8968c305..b97125a1 100644
--- a/src/dom/snapshot/stylesheets/inject.scss
+++ b/src/dom/snapshot/stylesheets/inject.scss
@@ -19,4 +19,12 @@ body.force-static-theme {
background-color: transparent !important;
color: var(--text-color);
}
+
+ :link {
+ color: var(--link-color) !important;
+ }
+
+ :visited {
+ color: var(--visited-link-color) !important;
+ }
}
diff --git a/src/pdf/pdf-view.js b/src/pdf/pdf-view.js
index 9ef26bfa..0a2ec5f5 100644
--- a/src/pdf/pdf-view.js
+++ b/src/pdf/pdf-view.js
@@ -58,6 +58,7 @@ import {
A11Y_VIRT_CURSOR_DEBOUNCE_LENGTH,
MIN_IMAGE_ANNOTATION_SIZE,
MIN_TEXT_ANNOTATION_WIDTH,
+ ORIGINAL_THEME,
PDF_NOTE_DIMENSIONS
} from '../common/defines';
import { ReadAloudJumpButton } from '../common/read-aloud/jump-button';
@@ -549,16 +550,22 @@ class PDFView {
if (this._colorScheme === 'light' && this._lightTheme) {
this._iframeWindow.theme = this._lightTheme;
root.style.setProperty('--background-color', this._lightTheme.background);
+ root.style.setProperty('--link-color', this._lightTheme.linkColor || this._lightTheme.foreground);
+ root.style.setProperty('--visited-link-color', this._lightTheme.visitedLinkColor || this._lightTheme.linkColor || this._lightTheme.foreground);
this._themeColorScheme = getModeBasedOnColors(this._lightTheme.background, this._lightTheme.foreground);
}
else if (this._colorScheme === 'dark' && this._darkTheme) {
this._iframeWindow.theme = this._darkTheme;
root.style.setProperty('--background-color', this._darkTheme.background);
+ root.style.setProperty('--link-color', this._darkTheme.linkColor || this._darkTheme.foreground);
+ root.style.setProperty('--visited-link-color', this._darkTheme.visitedLinkColor || this._darkTheme.linkColor || this._darkTheme.foreground);
this._themeColorScheme = getModeBasedOnColors(this._darkTheme.background, this._darkTheme.foreground);
}
else {
this._iframeWindow.theme = null;
- root.style.setProperty('--background-color', '#FFFFFF');
+ root.style.setProperty('--background-color', ORIGINAL_THEME.background);
+ root.style.setProperty('--link-color', ORIGINAL_THEME.linkColor);
+ root.style.setProperty('--visited-link-color', ORIGINAL_THEME.visitedLinkColor);
this._themeColorScheme = 'light';
}