Add support for System theme - dynamic switching between Light and Dark themes (#405)

* add support for system theme

* add EN texts
This commit is contained in:
Ilya Popovs 2022-08-30 14:33:49 +03:00 committed by GitHub
parent 717a2ace25
commit eaa57925ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 229 additions and 63 deletions

View file

@ -227,6 +227,9 @@
"darkLabel": {
"message": "Dark"
},
"systemLabel": {
"message": "System"
},
"buttonStyleLabel": {
"message": "Translation button"
},
@ -299,6 +302,9 @@
"resultFontColorLabel": {
"message": "Font color of translation result"
},
"isOverrideColorsLabel": {
"message": "Override default colors with colors below"
},
"candidateFontColorLabel": {
"message": "Font color of translation candidates"
},
@ -782,4 +788,4 @@
"lang_zh": {
"message": "Chinese"
}
}
}

View file

@ -3,6 +3,7 @@ import React, { Component } from "react";
import ReactDOM from "react-dom";
import { getSettings } from "src/settings/settings";
import "../styles/TranslatePanel.scss";
import { getBackgroundColor, getCandidateFontColor, getResultFontColor } from "../../settings/defaultColors";
const splitLine = text => {
const regex = /(\n)/g;
@ -173,17 +174,17 @@ export default class TranslatePanel extends Component {
top: this.state.panelPosition.y,
left: this.state.panelPosition.x,
fontSize: parseInt(getSettings("fontSize")),
backgroundColor: getSettings("bgColor")
};
const backgroundColor = getBackgroundColor()
if (backgroundColor) {
panelStyles.backgroundColor = backgroundColor.backgroundColor
}
const wrapperStyles = {
overflow: this.state.isOverflow ? "auto" : "hidden"
};
const resultStyles = {
color: getSettings("resultFontColor")
};
const candidateStyles = {
color: getSettings("candidateFontColor")
};
const translationApi = getSettings("translationApi");
return (
@ -195,10 +196,10 @@ export default class TranslatePanel extends Component {
<div className="simple-translate-result-wrapper" ref="wrapper" style={wrapperStyles}>
<div className="simple-translate-move" draggable="true" ref="move"></div>
<div className="simple-translate-result-contents">
<p className="simple-translate-result" style={resultStyles} dir="auto">
<p className="simple-translate-result" style={getResultFontColor()} dir="auto">
{splitLine(resultText)}
</p>
<p className="simple-translate-candidate" style={candidateStyles} dir="auto">
<p className="simple-translate-candidate" style={getCandidateFontColor()} dir="auto">
{splitLine(candidateText)}
</p>
{isError && (

View file

@ -216,7 +216,9 @@ const showTranslateContainer = (
if (element) return;
if (!isEnabled) return;
document.body.insertAdjacentHTML("beforeend", "<div id='simple-translate'></div>");
const themeClass = getSettings("theme") + "-theme";
document.body.insertAdjacentHTML("beforeend", `<div id="simple-translate" class="${themeClass}"></div>`);
ReactDOM.render(
<TranslateContainer
removeContainer={removeTranslatecontainer}

View file

@ -1,7 +1,7 @@
#simple-translate {
.simple-translate-button {
all: initial;
background-color: #fff;
background-color: var(--simple-translate-main-bg);
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08);
border-radius: 10%;
background-size: 75%;

View file

@ -5,10 +5,35 @@
}
position: absolute;
--simple-translate-main-text: #0c0c0d;
--simple-translate-sub-text: #737373;
--simple-translate-line: #ededf0;
--simple-translate-button: #d7d7db;
--simple-translate-highlight: #5595ff;
}
.light-theme {
--simple-translate-main-text: #0c0c0d;
--simple-translate-sub-text: #737373;
--simple-translate-main-bg: #ffffff;
}
.dark-theme {
--simple-translate-main-text: #e6e6e6;
--simple-translate-sub-text: #aaaaaa;
--simple-translate-main-bg: #181818;
}
// copy of .light-theme
.system-theme {
--simple-translate-main-text: #000000;
--simple-translate-sub-text: #737373;
--simple-translate-main-bg: #ffffff;
}
@media (prefers-color-scheme: dark) {
// copy of .dark-theme
.system-theme {
--simple-translate-main-text: #e6e6e6;
--simple-translate-sub-text: #aaaaaa;
--simple-translate-main-bg: #181818;
}
}

View file

@ -44,8 +44,8 @@
all: initial;
display: block;
margin: 0;
font-family: "Segoe UI", "San Francisco", "Ubuntu", "Fira Sans", "Roboto", "Arial",
"Helvetica", sans-serif !important;
font-family: "Segoe UI", "San Francisco", "Ubuntu", "Fira Sans",
"Roboto", "Arial", "Helvetica", sans-serif !important;
word-wrap: break-word;
font-size: inherit;
line-height: 150%;
@ -62,11 +62,11 @@
background: var(--simple-translate-line);
}
&.simple-translate-result {
.simple-translate-result {
color: var(--simple-translate-main-text);
}
&.simple-translate-candidate,
&.simple-translate-error {
.simple-translate-candidate,
.simple-translate-error {
color: var(--simple-translate-sub-text);
margin-top: 1em;
&:empty {

View file

@ -9,11 +9,16 @@ import "../styles/OptionsPage.scss";
const setupTheme = async () => {
await initSettings();
document.body.dataset.theme = getSettings("theme");
document.body.classList.add(getSettings("theme") + "-theme");
browser.storage.onChanged.addListener((changes) => {
if (changes.Settings.newValue.theme === changes.Settings.oldValue.theme) return;
document.body.dataset.theme = changes.Settings.newValue.theme;
if (changes.Settings.newValue.theme === changes.Settings.oldValue.theme)
return;
document.body.classList.replace(
changes.Settings.oldValue.theme + "-theme",
changes.Settings.newValue.theme + "-theme"
);
});
};

View file

@ -1,6 +1,4 @@
body {
background-color: var(--main-bg);
.light-theme {
--main-text: #0c0c0d;
--sub-text: #737373;
--line: #ededf0;
@ -9,8 +7,32 @@ body {
--main-bg: #ffffff;
--sub-bg: #ffffff;
--new: #ff4f4f;
}
&[data-theme="dark"] {
.dark-theme {
--main-text: #e6e6e6;
--sub-text: #aaaaaa;
--line: #373737;
--button: #929292;
--highlight: #5595ff;
--main-bg: #181818;
--sub-bg: #101010;
--new: #ed5f5f;
}
.system-theme {
--main-text: #0c0c0d;
--sub-text: #737373;
--line: #ededf0;
--button: #d7d7db;
--highlight: #5595ff;
--main-bg: #ffffff;
--sub-bg: #ffffff;
--new: #ff4f4f;
}
@media (prefers-color-scheme: dark) {
.system-theme {
--main-text: #e6e6e6;
--sub-text: #aaaaaa;
--line: #373737;
@ -22,9 +44,13 @@ body {
}
}
body {
background-color: var(--main-bg);
}
.optionsPage {
font-family: "Segoe UI", "San Francisco", "Ubuntu", "Fira Sans", "Roboto", "Arial", "Helvetica",
sans-serif;
font-family: "Segoe UI", "San Francisco", "Ubuntu", "Fira Sans", "Roboto",
"Arial", "Helvetica", sans-serif;
font-size: 15px;
font-weight: 400;
color: var(--main-text);

View file

@ -10,6 +10,7 @@ import InputArea from "./InputArea";
import ResultArea from "./ResultArea";
import Footer from "./Footer";
import "../styles/PopupPage.scss";
import { getBackgroundColor } from "../../settings/defaultColors";
const logDir = "popup/PopupPage";
@ -58,7 +59,8 @@ export default class PopupPage extends Component {
overWriteLogLevel();
updateLogLevel();
document.body.dataset.theme = getSettings("theme");
this.themeClass = getSettings("theme") + "-theme";
document.body.classList.add(this.themeClass)
const targetLang = getSettings("targetLang");
let langHistory = getSettings("langHistory");
if (!langHistory) {

View file

@ -1,11 +1,71 @@
.light-theme {
--main-text: #0c0c0d;
--sub-text: #737373;
--line: #ededf0;
--button: #d7d7db;
--highlight: #5595ff;
--main-bg: #ffffff;
--confirm: #ff4f4f;
--error: #d70022;
--warn: #ff8f00;
--success: #058b00;
--info: #0a84ff;
}
.dark-theme {
--main-text: #e6e6e6;
--sub-text: #aaaaaa;
--line: #373737;
--button: #929292;
--highlight: #5595ff;
--main-bg: #181818;
--highlight-bg: #2e4343;
--confirm: #ed5f5f;
--error: #ca1532;
--warn: #ee8e12;
--success: #2a9c26;
--info: #1471d0;
}
.system-theme {
--main-text: #0c0c0d;
--sub-text: #737373;
--line: #ededf0;
--button: #d7d7db;
--highlight: #5595ff;
--main-bg: #ffffff;
--confirm: #ff4f4f;
--error: #d70022;
--warn: #ff8f00;
--success: #058b00;
--info: #0a84ff;
}
@media (prefers-color-scheme: dark) {
.system-theme {
--main-text: #e6e6e6;
--sub-text: #aaaaaa;
--line: #373737;
--button: #929292;
--highlight: #5595ff;
--main-bg: #181818;
--highlight-bg: #2e4343;
--confirm: #ed5f5f;
--error: #ca1532;
--warn: #ee8e12;
--success: #2a9c26;
--info: #1471d0;
}
}
html {
scrollbar-width: none;
}
body {
margin: 0;
font-family: "Segoe UI", "San Francisco", "Ubuntu", "Fira Sans", "Roboto", "Arial", "Helvetica",
sans-serif;
font-family: "Segoe UI", "San Francisco", "Ubuntu", "Fira Sans", "Roboto",
"Arial", "Helvetica", sans-serif;
font-size: 13px;
width: 100%;
min-width: 348px;
@ -26,31 +86,4 @@ body {
::-moz-selection {
background: var(--line);
}
--main-text: #0c0c0d;
--sub-text: #737373;
--line: #ededf0;
--button: #d7d7db;
--highlight: #5595ff;
--main-bg: #ffffff;
--confirm: #ff4f4f;
--error: #d70022;
--warn: #ff8f00;
--success: #058b00;
--info: #0a84ff;
&[data-theme="dark"] {
--main-text: #e6e6e6;
--sub-text: #aaaaaa;
--line: #373737;
--button: #929292;
--highlight: #5595ff;
--main-bg: #181818;
--highlight-bg: #2e4343;
--confirm: #ed5f5f;
--error: #ca1532;
--warn: #ee8e12;
--success: #2a9c26;
--info: #1471d0;
}
}

View file

@ -0,0 +1,41 @@
import { getSettings } from "./settings";
export const RESULT_FONT_COLOR_LIGHT = "#000000";
export const RESULT_FONT_COLOR_DARK = "#e6e6e6";
export const CANDIDATE_FONT_COLOR_LIGHT = "#737373";
export const CANDIDATE_FONT_COLOR_DARK = "#aaaaaa";
export const BG_COLOR_LIGHT = "#ffffff";
export const BG_COLOR_DARK = "#181818";
/**
* Return style object if color override is enabled
*/
export function getResultFontColor() {
const isOverrideColors = getSettings("isOverrideColors");
if (!isOverrideColors) return undefined;
return { color: getSettings("resultFontColor") };
}
/**
* Return style object if color override is enabled
*/
export function getCandidateFontColor() {
const isOverrideColors = getSettings("isOverrideColors");
if (!isOverrideColors) return undefined;
return { color: getSettings("candidateFontColor") };
}
/**
* Return style object if color override is enabled
*/
export function getBackgroundColor() {
const isOverrideColors = getSettings("isOverrideColors");
if (!isOverrideColors) return undefined;
return { backgroundColor: getSettings("bgColor") };
}

View file

@ -2,6 +2,14 @@ import React from "react";
import browser from "webextension-polyfill";
import generateLangOptions from "src/common/generateLangOptions";
import { getSettings, setSettings } from "./settings";
import {
RESULT_FONT_COLOR_LIGHT,
RESULT_FONT_COLOR_DARK,
CANDIDATE_FONT_COLOR_LIGHT,
CANDIDATE_FONT_COLOR_DARK,
BG_COLOR_LIGHT,
BG_COLOR_DARK
} from "./defaultColors"
const getDefaultLangs = () => {
const uiLang = browser.i18n.getUILanguage();
@ -300,7 +308,7 @@ export default [
title: "themeLabel",
captions: ["themeCaptionLabel"],
type: "select",
default: getTheme(),
default: 'system',
options: [
{
name: "lightLabel",
@ -309,6 +317,10 @@ export default [
{
name: "darkLabel",
value: "dark"
},
{
name: "systemLabel",
value: "system"
}
]
},
@ -479,27 +491,40 @@ export default [
default: 10,
placeholder: 10
},
{
id: "isOverrideColors",
title: "isOverrideColorsLabel",
captions: [],
type: "checkbox",
default: false
},
{
id: "resultFontColor",
title: "resultFontColorLabel",
captions: [],
type: "color",
default: getTheme() === "light" ? "#000000" : "#e6e6e6"
default:
getTheme() === "light"
? RESULT_FONT_COLOR_LIGHT
: RESULT_FONT_COLOR_DARK,
},
{
id: "candidateFontColor",
title: "candidateFontColorLabel",
captions: [],
type: "color",
default: getTheme() === "light" ? "#737373" : "#aaaaaa"
default:
getTheme() === "light"
? CANDIDATE_FONT_COLOR_LIGHT
: CANDIDATE_FONT_COLOR_DARK,
},
{
id: "bgColor",
title: "bgColorLabel",
captions: [],
type: "color",
default: getTheme() === "light" ? "#ffffff" : "#181818"
}
default: getTheme() === "light" ? BG_COLOR_LIGHT : BG_COLOR_DARK,
},
]
}
]