diff --git a/locales/en.json b/locales/en.json
index a765d2e..d2e1fdd 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -20,6 +20,9 @@
"settings.backgroundColor": "Background color",
"settings.backgroundColor.white": "White",
"settings.backgroundColor.black": "Black",
+ "settings.colorMode": "Color mode",
+ "settings.colorMode.light": "Light",
+ "settings.colorMode.dark": "Dark",
"settings.interval": "Auto play interval",
"settings.interval.unit": "s",
"settings.direction.rtl": "Right to left",
@@ -39,4 +42,4 @@
"seek.previewAlt": "Preview of page {{page}}",
"loading": "Loading",
"error.pageRequestFailed": "Request failed for page {{page}}"
-}
+}
\ No newline at end of file
diff --git a/locales/id.json b/locales/id.json
index 80ade16..9986101 100644
--- a/locales/id.json
+++ b/locales/id.json
@@ -20,6 +20,9 @@
"settings.backgroundColor": "Warna latar",
"settings.backgroundColor.white": "Putih",
"settings.backgroundColor.black": "Hitam",
+ "settings.colorMode": "Mode warna",
+ "settings.colorMode.light": "Terang",
+ "settings.colorMode.dark": "Gelap",
"settings.interval": "Interval putar otomatis",
"settings.interval.unit": "dtk",
"settings.direction.rtl": "Kanan",
@@ -39,4 +42,4 @@
"seek.previewAlt": "Pratinjau halaman {{page}}",
"loading": "Memuat",
"error.pageRequestFailed": "Permintaan halaman {{page}} gagal"
-}
+}
\ No newline at end of file
diff --git a/locales/ja.json b/locales/ja.json
index 3112adb..c989da5 100644
--- a/locales/ja.json
+++ b/locales/ja.json
@@ -20,6 +20,9 @@
"settings.backgroundColor": "背景色",
"settings.backgroundColor.white": "白",
"settings.backgroundColor.black": "黒",
+ "settings.colorMode": "カラーモード",
+ "settings.colorMode.light": "ライト",
+ "settings.colorMode.dark": "ダーク",
"settings.interval": "自動再生の秒数",
"settings.interval.unit": "秒",
"settings.direction.rtl": "右",
@@ -39,4 +42,4 @@
"seek.previewAlt": "{{page}}ページのプレビュー",
"loading": "読み込み中",
"error.pageRequestFailed": "{{page}}ページのリクエストに失敗しました"
-}
+}
\ No newline at end of file
diff --git a/locales/ko.json b/locales/ko.json
index 0f31352..d686d23 100644
--- a/locales/ko.json
+++ b/locales/ko.json
@@ -20,6 +20,9 @@
"settings.backgroundColor": "배경색",
"settings.backgroundColor.white": "흰색",
"settings.backgroundColor.black": "검정",
+ "settings.colorMode": "컬러 모드",
+ "settings.colorMode.light": "라이트",
+ "settings.colorMode.dark": "다크",
"settings.interval": "자동 재생 간격",
"settings.interval.unit": "초",
"settings.direction.rtl": "오른쪽",
@@ -39,4 +42,4 @@
"seek.previewAlt": "{{page}}페이지 미리보기",
"loading": "로딩 중",
"error.pageRequestFailed": "{{page}}페이지 요청 실패"
-}
+}
\ No newline at end of file
diff --git a/locales/th.json b/locales/th.json
index 2233e72..7b826a6 100644
--- a/locales/th.json
+++ b/locales/th.json
@@ -20,6 +20,9 @@
"settings.backgroundColor": "สีพื้นหลัง",
"settings.backgroundColor.white": "ขาว",
"settings.backgroundColor.black": "ดำ",
+ "settings.colorMode": "โหมดสี",
+ "settings.colorMode.light": "สว่าง",
+ "settings.colorMode.dark": "มืด",
"settings.interval": "ระยะเวลาเล่นอัตโนมัติ",
"settings.interval.unit": "วินาที",
"settings.direction.rtl": "ขวา",
@@ -39,4 +42,4 @@
"seek.previewAlt": "ตัวอย่างหน้า {{page}}",
"loading": "กำลังโหลด",
"error.pageRequestFailed": "ขอหน้า {{page}} ไม่สำเร็จ"
-}
+}
\ No newline at end of file
diff --git a/locales/zh-CN.json b/locales/zh-CN.json
index de076df..309971b 100644
--- a/locales/zh-CN.json
+++ b/locales/zh-CN.json
@@ -20,6 +20,9 @@
"settings.backgroundColor": "背景颜色",
"settings.backgroundColor.white": "白色",
"settings.backgroundColor.black": "黑色",
+ "settings.colorMode": "颜色模式",
+ "settings.colorMode.light": "浅色",
+ "settings.colorMode.dark": "深色",
"settings.interval": "自动播放间隔",
"settings.interval.unit": "秒",
"settings.direction.rtl": "向右",
@@ -39,4 +42,4 @@
"seek.previewAlt": "第 {{page}} 页预览",
"loading": "加载中",
"error.pageRequestFailed": "第 {{page}} 页请求失败"
-}
+}
\ No newline at end of file
diff --git a/src/components/arrow-buttons.styles.ts b/src/components/arrow-buttons.styles.ts
index 4eb72bb..1d57d96 100644
--- a/src/components/arrow-buttons.styles.ts
+++ b/src/components/arrow-buttons.styles.ts
@@ -94,7 +94,7 @@ export const arrowButtonsStyles = `
left: 50%;
width: 20px;
height: 20px;
- color: #666;
+ color: var(--comimi-muted);
transform: translate(-50%, -50%);
pointer-events: none;
}
diff --git a/src/components/center-message.styles.ts b/src/components/center-message.styles.ts
index e858b89..db254b4 100644
--- a/src/components/center-message.styles.ts
+++ b/src/components/center-message.styles.ts
@@ -18,10 +18,10 @@ export const centerMessageStyles = `
box-sizing: border-box;
padding: 6px 12px;
border-radius: 8px;
- background: rgba(255, 255, 255, 0.5);
+ background: var(--comimi-overlay);
box-shadow: var(--comimi-shadow);
backdrop-filter: blur(5px);
- color: #666;
+ color: var(--comimi-muted);
font-size: 12px;
font-weight: 400;
line-height: 1.45;
diff --git a/src/components/controls-dock.styles.ts b/src/components/controls-dock.styles.ts
index 3dfd677..59b3891 100644
--- a/src/components/controls-dock.styles.ts
+++ b/src/components/controls-dock.styles.ts
@@ -97,13 +97,13 @@ export const controlsDockStyles = `
}
.comimi-seek-current {
- color: #333;
+ color: var(--comimi-fg);
font-size: 12px;
font-weight: 700;
}
.comimi-seek-total {
- color: #999;
+ color: var(--comimi-soft);
font-size: 12px;
font-weight: 400;
margin-left: 0.4em;
@@ -122,7 +122,7 @@ export const controlsDockStyles = `
right: 0;
height: 8px;
border-radius: 999px;
- background: #e0e0e0;
+ background: var(--comimi-line);
overflow: hidden;
transform: translateY(-50%);
transition: height 0.36s var(--comimi-spring);
@@ -139,7 +139,7 @@ export const controlsDockStyles = `
top: 0;
height: 100%;
border-radius: 999px;
- background: #666;
+ background: var(--comimi-accent);
}
.comimi-seek-bar[data-direction="rtl"] .comimi-seek-fill {
@@ -183,7 +183,7 @@ export const controlsDockStyles = `
margin-top: -5px;
border: 0;
border-radius: 50%;
- background: #666;
+ background: var(--comimi-accent);
box-shadow: none;
transition:
transform 0.36s var(--comimi-spring),
@@ -205,7 +205,7 @@ export const controlsDockStyles = `
height: 18px;
border: 0;
border-radius: 50%;
- background: #666;
+ background: var(--comimi-accent);
box-shadow: none;
transition:
transform 0.36s var(--comimi-spring),
@@ -264,7 +264,7 @@ export const controlsDockStyles = `
position: relative;
width: 80px;
aspect-ratio: 100 / 141;
- background: #fff;
+ background: var(--comimi-page-surface);
border-radius: 6px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
@@ -285,7 +285,7 @@ export const controlsDockStyles = `
justify-content: center;
box-sizing: border-box;
padding: 8px;
- color: #aaa;
+ color: var(--comimi-icon-subtle);
font-size: 11px;
font-weight: 700;
line-height: 1.4;
@@ -293,8 +293,8 @@ export const controlsDockStyles = `
}
.comimi-seek-preview-label {
- color: #333;
- background: rgba(255, 255, 255, 0.5);
+ color: var(--comimi-fg);
+ background: var(--comimi-overlay);
backdrop-filter: blur(5px);
box-shadow: var(--comimi-shadow);
border-radius: 8px;
@@ -327,7 +327,7 @@ export const controlsDockStyles = `
padding: 0;
border: 0;
background: transparent;
- color: #666;
+ color: var(--comimi-muted);
cursor: pointer;
}
@@ -375,7 +375,7 @@ export const controlsDockStyles = `
width: 140px;
height: 6px;
border-radius: 999px;
- background: #e0e0e0;
+ background: var(--comimi-line);
overflow: hidden;
}
@@ -384,7 +384,7 @@ export const controlsDockStyles = `
position: absolute;
inset: 0;
border-radius: 999px;
- background: #666;
+ background: var(--comimi-accent);
animation: comimi-autoplay-progress 3s linear 0s infinite;
}
@@ -404,7 +404,7 @@ export const controlsDockStyles = `
height: 30px;
display: grid;
grid-template-columns: 1fr 1fr;
- background: #eeeeee;
+ background: var(--comimi-surface-2);
border-radius: 8px;
transform: translate(-50%, -50%);
transition: width 0.36s var(--comimi-spring);
@@ -425,7 +425,7 @@ export const controlsDockStyles = `
padding: 0;
border: 0;
background: transparent;
- color: #666;
+ color: var(--comimi-muted);
cursor: pointer;
}
@@ -466,7 +466,7 @@ export const controlsDockStyles = `
display: block;
width: 100%;
height: 100%;
- color: #666;
+ color: var(--comimi-muted);
transition: transform 0.36s var(--comimi-spring);
}
@@ -506,7 +506,7 @@ export const controlsDockStyles = `
z-index: 50;
pointer-events: none;
overflow: hidden;
- background: rgba(0, 0, 0, 0.06);
+ background: var(--comimi-dim);
opacity: 0;
transition: opacity 0.16s linear;
}
@@ -519,7 +519,7 @@ export const controlsDockStyles = `
display: block;
position: absolute;
inset: 0;
- background: #666;
+ background: var(--comimi-accent);
animation: comimi-autoplay-progress 3s linear 0s infinite;
}
diff --git a/src/components/icons.styles.ts b/src/components/icons.styles.ts
index 06cbfda..83eb768 100644
--- a/src/components/icons.styles.ts
+++ b/src/components/icons.styles.ts
@@ -32,7 +32,7 @@ export const iconStyles = `
width: 17px;
height: 3px;
border-radius: 999px;
- background: #666;
+ background: var(--comimi-muted);
}
.comimi-menu-svg span:nth-child(1) {
diff --git a/src/components/inputs.styles.ts b/src/components/inputs.styles.ts
index 7e9fae3..bd94e19 100644
--- a/src/components/inputs.styles.ts
+++ b/src/components/inputs.styles.ts
@@ -9,7 +9,7 @@ export const inputsStyles = `
position: absolute;
inset: 0;
border-radius: 8px;
- background: #eeeeee;
+ background: var(--comimi-surface-2);
transition: inset 0.36s var(--comimi-spring);
}
@@ -43,8 +43,8 @@ export const inputsStyles = `
}
.comimi-selectbox-select option {
- color: #333;
- background-color: #fff;
+ color: var(--comimi-fg);
+ background-color: var(--comimi-page-surface);
}
.comimi-selectbox-label {
@@ -53,7 +53,7 @@ export const inputsStyles = `
box-sizing: border-box;
width: 100%;
padding: 8px 32px 8px 12px;
- color: #333;
+ color: var(--comimi-fg);
font-size: 12px;
font-weight: 400;
line-height: 1.45;
@@ -68,7 +68,7 @@ export const inputsStyles = `
z-index: 1;
width: 16px;
height: 16px;
- color: #aaa;
+ color: var(--comimi-icon-subtle);
transform: translateY(-50%) rotate(90deg);
pointer-events: none;
}
@@ -109,12 +109,12 @@ export const inputsStyles = `
width: 32px;
height: 18px;
border-radius: 999px;
- background: #eeeeee;
+ background: var(--comimi-surface-2);
transition: background-color 0.2s linear;
}
.comimi-toggle-switch[data-checked="true"] .comimi-toggle-track {
- background: #666;
+ background: var(--comimi-accent);
}
.comimi-toggle-knob {
@@ -124,14 +124,14 @@ export const inputsStyles = `
width: 14px;
height: 14px;
border-radius: 50%;
- background: #666;
+ background: var(--comimi-accent);
transition:
transform 0.36s var(--comimi-spring),
background-color 0.2s linear;
}
.comimi-toggle-switch[data-checked="true"] .comimi-toggle-knob {
- background: #fff;
+ background: var(--comimi-contrast);
transform: translateX(100%);
}
@@ -164,11 +164,11 @@ export const inputsStyles = `
}
.comimi-toggle-label-on {
- color: #333;
+ color: var(--comimi-fg);
}
.comimi-toggle-label-off {
- color: #aaa;
+ color: var(--comimi-icon-subtle);
transform: translateX(100%);
}
@@ -199,7 +199,7 @@ export const inputsStyles = `
right: 0;
height: 6px;
border-radius: 999px;
- background: #eeeeee;
+ background: var(--comimi-surface-2);
overflow: hidden;
transform: translateY(-50%);
transition: height 0.36s var(--comimi-spring);
@@ -214,7 +214,7 @@ export const inputsStyles = `
.comimi-range-slider-fill {
display: block;
height: 100%;
- background: #666;
+ background: var(--comimi-accent);
border-radius: inherit;
}
@@ -246,7 +246,7 @@ export const inputsStyles = `
margin-top: -6px;
border: 0;
border-radius: 50%;
- background: #666;
+ background: var(--comimi-accent);
box-shadow: none;
transition:
transform 0.36s var(--comimi-spring),
@@ -268,7 +268,7 @@ export const inputsStyles = `
height: 18px;
border: 0;
border-radius: 50%;
- background: #666;
+ background: var(--comimi-accent);
box-shadow: none;
transition:
transform 0.36s var(--comimi-spring),
@@ -293,7 +293,7 @@ export const inputsStyles = `
.comimi-range-slider-value {
width: 36px;
- color: #666;
+ color: var(--comimi-muted);
font-size: 11px;
font-weight: 400;
line-height: 1;
diff --git a/src/components/loading-icon.styles.ts b/src/components/loading-icon.styles.ts
index 0f4ea04..26760e7 100644
--- a/src/components/loading-icon.styles.ts
+++ b/src/components/loading-icon.styles.ts
@@ -22,12 +22,16 @@ export const loadingIconStyles = `
.comimi-loading-stroke {
fill: none;
- stroke: #ccc;
+ stroke: var(--comimi-loading-stroke);
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 10px;
}
+.comimi-loading-body {
+ fill: var(--comimi-loading-body);
+}
+
.comimi-loading-mimi {
transform-origin: 56px 43px;
}
@@ -52,7 +56,7 @@ export const loadingIconStyles = `
}
.comimi-loading-eye {
- fill: #ccc;
+ fill: var(--comimi-loading-eye);
transform-origin: center;
transform-box: fill-box;
animation:
@@ -61,7 +65,7 @@ export const loadingIconStyles = `
}
.comimi-loading-icon-text {
- color: #aaa;
+ color: var(--comimi-loading-text);
font-size: 12px;
font-weight: 700;
line-height: 1.45;
diff --git a/src/components/loading-icon.ts b/src/components/loading-icon.ts
index d40efcc..01c3444 100644
--- a/src/components/loading-icon.ts
+++ b/src/components/loading-icon.ts
@@ -9,7 +9,7 @@ const LOADING_SVG = `
-
+
diff --git a/src/components/menu-panel.styles.ts b/src/components/menu-panel.styles.ts
index 0c99d53..806e286 100644
--- a/src/components/menu-panel.styles.ts
+++ b/src/components/menu-panel.styles.ts
@@ -87,7 +87,7 @@ export const menuPanelStyles = `
.comimi-menu-title {
display: block;
width: 100%;
- color: #333;
+ color: var(--comimi-fg);
font-size: 15px;
font-weight: 700;
overflow: hidden;
@@ -98,7 +98,7 @@ export const menuPanelStyles = `
.comimi-menu-author {
display: block;
width: 100%;
- color: #666;
+ color: var(--comimi-muted);
font-size: 12px;
font-weight: 400;
overflow: hidden;
@@ -116,7 +116,7 @@ export const menuPanelStyles = `
.comimi-menu-border {
width: 100%;
height: 1px;
- background: #e0e0e0;
+ background: var(--comimi-line);
}
.comimi-menu-view {
@@ -161,17 +161,17 @@ export const menuPanelStyles = `
border: 0;
border-radius: 10px;
background: transparent;
- color: #666;
+ color: var(--comimi-muted);
cursor: pointer;
transition: background-color 0.24s linear;
}
.comimi-menu-link:hover {
- background: #f1f1f1;
+ background: var(--comimi-hover);
}
.comimi-menu-link-text {
- color: #666;
+ color: var(--comimi-muted);
font-size: 14px;
font-weight: 700;
line-height: 1.45;
@@ -182,7 +182,7 @@ export const menuPanelStyles = `
display: block;
width: 20px;
height: 20px;
- color: #aaa;
+ color: var(--comimi-icon-subtle);
}
.comimi-menu-link-arrow > svg {
@@ -211,7 +211,7 @@ export const menuPanelStyles = `
padding: 0;
border: 0;
background: transparent;
- color: #666;
+ color: var(--comimi-muted);
cursor: pointer;
text-align: center;
}
@@ -221,9 +221,9 @@ export const menuPanelStyles = `
display: block;
width: 100%;
aspect-ratio: 100 / 141;
- background: #fff;
+ background: var(--comimi-page-surface);
border-radius: 6px;
- outline: 3px solid #e0e0e0;
+ outline: 3px solid var(--comimi-line);
}
.comimi-page-list-thumb-html {
@@ -235,7 +235,7 @@ export const menuPanelStyles = `
box-sizing: border-box;
padding: 8px;
text-align: center;
- color: #aaa;
+ color: var(--comimi-icon-subtle);
font-size: 11px;
font-weight: 700;
line-height: 1.4;
@@ -252,7 +252,7 @@ export const menuPanelStyles = `
}
.comimi-page-list-text {
- color: #666;
+ color: var(--comimi-muted);
font-size: 14px;
font-weight: 700;
}
@@ -276,7 +276,7 @@ export const menuPanelStyles = `
}
.comimi-shortcut-heading {
- color: #666;
+ color: var(--comimi-muted);
font-size: 12px;
font-weight: 700;
line-height: 1.45;
@@ -310,11 +310,11 @@ export const menuPanelStyles = `
align-items: center;
padding: 4px 8px;
border-radius: 7px;
- background: #eeeeee;
+ background: var(--comimi-surface-2);
}
.comimi-shortcut-key {
- color: #666;
+ color: var(--comimi-muted);
font-size: 13px;
font-weight: 700;
line-height: 1.45;
@@ -323,14 +323,14 @@ export const menuPanelStyles = `
.comimi-shortcut-or::before {
content: "or";
display: block;
- color: #666;
+ color: var(--comimi-muted);
font-size: 11px;
font-weight: 400;
line-height: 1.45;
}
.comimi-shortcut-label {
- color: #666;
+ color: var(--comimi-muted);
font-size: 13px;
font-weight: 400;
line-height: 1.45;
@@ -355,7 +355,7 @@ export const menuPanelStyles = `
position: absolute;
inset: 0;
border-radius: 8px;
- background: #eeeeee;
+ background: var(--comimi-surface-2);
transition: inset 0.36s var(--comimi-spring), border-radius 0.36s var(--comimi-spring);
}
@@ -369,7 +369,7 @@ export const menuPanelStyles = `
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
- color: #666;
+ color: var(--comimi-muted);
font-size: 14px;
font-weight: 700;
line-height: 1.45;
@@ -382,7 +382,7 @@ export const menuPanelStyles = `
left: 8px;
width: 22px;
height: 22px;
- color: #aaa;
+ color: var(--comimi-icon-subtle);
transform: translateY(-50%) scaleX(-1);
pointer-events: none;
}
diff --git a/src/components/move-direction-guide.styles.ts b/src/components/move-direction-guide.styles.ts
index aa3d304..4287031 100644
--- a/src/components/move-direction-guide.styles.ts
+++ b/src/components/move-direction-guide.styles.ts
@@ -8,8 +8,8 @@ export const moveDirectionGuideStyles = `
height: var(--comimi-move-guide-size);
transform: translate(-50%, -50%);
border-radius: 16px;
- background: rgba(255, 255, 255, 0.7);
- box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.1);
+ background: var(--comimi-overlay);
+ box-shadow: var(--comimi-shadow);
backdrop-filter: blur(5px);
pointer-events: none;
z-index: 1;
@@ -52,7 +52,7 @@ export const moveDirectionGuideStyles = `
width: 30px;
height: 6px;
border-radius: 999px;
- background-color: #666;
+ background-color: var(--comimi-accent);
animation: comimi-move-guide-arrow 0.6s ease-in-out 0.8s both;
}
@@ -66,7 +66,7 @@ export const moveDirectionGuideStyles = `
width: 16px;
height: 6px;
border-radius: 999px;
- background-color: #666;
+ background-color: var(--comimi-accent);
transform-origin: 3px center;
}
@@ -87,7 +87,7 @@ export const moveDirectionGuideStyles = `
font-weight: 400;
text-align: center;
line-height: 1.45;
- color: #666;
+ color: var(--comimi-muted);
}
@keyframes comimi-move-guide-arrow {
diff --git a/src/components/notifications.styles.ts b/src/components/notifications.styles.ts
index 64dc33c..8e72def 100644
--- a/src/components/notifications.styles.ts
+++ b/src/components/notifications.styles.ts
@@ -20,7 +20,7 @@ export const notificationsStyles = `
width: fit-content;
padding: 6px 13px 6px 8px;
border-radius: 999px;
- background-color: #666;
+ background-color: var(--comimi-accent);
animation: comimi-toast-popup 0.37s ease-in-out 0s both;
}
@@ -29,11 +29,11 @@ export const notificationsStyles = `
width: 10px;
height: 10px;
border-radius: 50%;
- background: #888;
+ background: var(--comimi-soft);
}
.comimi-toast-text {
- color: #fff;
+ color: var(--comimi-contrast);
font-size: 12px;
font-weight: 700;
line-height: 1.45;
diff --git a/src/components/page-stage.styles.ts b/src/components/page-stage.styles.ts
index 954b8d3..fa34f50 100644
--- a/src/components/page-stage.styles.ts
+++ b/src/components/page-stage.styles.ts
@@ -93,8 +93,8 @@ export const pageStageStyles = `
position: relative;
width: min(100%, 960px);
height: min(100%, 680px);
- background: #fff;
- color: #111;
+ background: var(--comimi-page-surface);
+ color: var(--comimi-page-fg);
overflow: auto;
}
diff --git a/src/components/scroll-fade.styles.ts b/src/components/scroll-fade.styles.ts
index 3d63a0a..890e864 100644
--- a/src/components/scroll-fade.styles.ts
+++ b/src/components/scroll-fade.styles.ts
@@ -20,12 +20,12 @@ export const scrollFadeStyles = `
.comimi-scrollfade::before {
top: 0;
- background: linear-gradient(to bottom, #fff, transparent);
+ background: linear-gradient(to bottom, var(--comimi-scrollfade), transparent);
}
.comimi-scrollfade::after {
bottom: 0;
- background: linear-gradient(to top, #fff, transparent);
+ background: linear-gradient(to top, var(--comimi-scrollfade), transparent);
}
.comimi-scrollfade[data-scroll-up="true"]::before {
diff --git a/src/components/settings-panel.styles.ts b/src/components/settings-panel.styles.ts
index 968d536..942a0bd 100644
--- a/src/components/settings-panel.styles.ts
+++ b/src/components/settings-panel.styles.ts
@@ -38,7 +38,7 @@ export const settingsPanelStyles = `
}
.comimi-settings-panel-title {
- color: #333;
+ color: var(--comimi-fg);
font-size: 14px;
font-weight: 700;
text-align: center;
@@ -51,13 +51,13 @@ export const settingsPanelStyles = `
}
.comimi-settings-label {
- color: #333;
+ color: var(--comimi-fg);
font-size: 12px;
font-weight: 400;
}
.comimi-settings-static-value {
- color: #999;
+ color: var(--comimi-soft);
font-size: 13px;
font-weight: 500;
}
diff --git a/src/components/settings-panel.ts b/src/components/settings-panel.ts
index 58a486d..d471aed 100644
--- a/src/components/settings-panel.ts
+++ b/src/components/settings-panel.ts
@@ -1,6 +1,7 @@
import { I18n } from "../i18n/i18n";
import type {
BackgroundColor,
+ ColorMode,
HideableControl,
ReadingDirection,
ViewerState
@@ -19,12 +20,14 @@ export class SettingsPanel {
private coverLabel: HTMLDivElement;
private directionLabel: HTMLDivElement;
private backgroundColorLabel: HTMLDivElement;
+ private colorModeLabel: HTMLDivElement;
private intervalLabel: HTMLDivElement;
private localeSelect: Selectbox;
private coverToggle: ToggleSwitch;
private directionSelect: Selectbox;
private backgroundColorSelect: Selectbox;
+ private colorModeSelect: Selectbox;
private intervalSlider: RangeSlider;
private staticValues: Partial> = {};
@@ -65,6 +68,11 @@ export class SettingsPanel {
backgroundColor: backgroundColor as BackgroundColor
})
);
+ this.colorModeSelect = new Selectbox((colorMode) =>
+ this.callbacks.updateSettings({
+ colorMode: colorMode as ColorMode
+ })
+ );
this.intervalSlider = new RangeSlider((seconds) =>
this.callbacks.updateSettings({
autoPageTurnIntervalMs: Math.max(1, seconds) * 1000
@@ -77,6 +85,7 @@ export class SettingsPanel {
this.coverLabel = this.createLabel();
this.directionLabel = this.createLabel();
this.backgroundColorLabel = this.createLabel();
+ this.colorModeLabel = this.createLabel();
this.intervalLabel = this.createLabel();
this.inner.append(
@@ -101,6 +110,11 @@ export class SettingsPanel {
this.intervalLabel,
this.intervalSlider.getElement()
),
+ this.buildSection(
+ "colorMode",
+ this.colorModeLabel,
+ this.colorModeSelect.getElement()
+ ),
this.buildSection(
"backgroundColor",
this.backgroundColorLabel,
@@ -122,6 +136,7 @@ export class SettingsPanel {
this.backgroundColorLabel.textContent = this.i18n.t(
"settings.backgroundColor"
);
+ this.colorModeLabel.textContent = this.i18n.t("settings.colorMode");
this.intervalLabel.textContent = this.i18n.t("settings.interval");
const localeOptions = [
@@ -146,6 +161,16 @@ export class SettingsPanel {
value: "black"
}
];
+ const colorModeOptions = [
+ {
+ label: this.i18n.t("settings.colorMode.light"),
+ value: "light"
+ },
+ {
+ label: this.i18n.t("settings.colorMode.dark"),
+ value: "dark"
+ }
+ ];
const intervalUnit = this.i18n.t("settings.interval.unit");
const intervalSeconds = Math.round(
state.settings.autoPageTurnIntervalMs / 1000
@@ -154,12 +179,14 @@ export class SettingsPanel {
this.localeSelect.setOptions(localeOptions);
this.directionSelect.setOptions(directionOptions);
this.backgroundColorSelect.setOptions(backgroundColorOptions);
+ this.colorModeSelect.setOptions(colorModeOptions);
this.intervalSlider.setUnit(intervalUnit);
this.localeSelect.setValue(state.settings.locale);
this.coverToggle.setChecked(state.settings.hasCover);
this.directionSelect.setValue(state.settings.readingDirection);
this.backgroundColorSelect.setValue(state.settings.backgroundColor);
+ this.colorModeSelect.setValue(state.settings.colorMode);
this.intervalSlider.setValue(intervalSeconds);
this.setStaticValue(
@@ -176,6 +203,10 @@ export class SettingsPanel {
"backgroundColor",
this.labelFor(backgroundColorOptions, state.settings.backgroundColor)
);
+ this.setStaticValue(
+ "colorMode",
+ this.labelFor(colorModeOptions, state.settings.colorMode)
+ );
this.root.dataset.open = String(state.panel === "settings");
diff --git a/src/components/splash-screen.styles.ts b/src/components/splash-screen.styles.ts
index 2f3f21a..2b6d71e 100644
--- a/src/components/splash-screen.styles.ts
+++ b/src/components/splash-screen.styles.ts
@@ -3,7 +3,7 @@ export const splashScreenStyles = `
position: absolute;
inset: 0;
z-index: 10;
- background-color: #e0e0e0;
+ background-color: var(--comimi-splash-bg);
overflow: hidden;
animation: comimi-splash-clip 1s cubic-bezier(0.82, 0.01, 0.48, 1.02) 1s both;
pointer-events: none;
@@ -74,9 +74,17 @@ export const splashScreenStyles = `
overflow: visible;
}
+.comimi-splash-body {
+ fill: var(--comimi-splash-symbol-fill);
+}
+
+.comimi-splash-typo-letter {
+ fill: var(--comimi-splash-typo-fill);
+}
+
.comimi-splash-stroke {
fill: none;
- stroke: #fff;
+ stroke: var(--comimi-splash-stroke);
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 10px;
@@ -99,6 +107,7 @@ export const splashScreenStyles = `
}
.comimi-splash-eye {
+ fill: var(--comimi-splash-eye-fill);
transform-origin: center;
transform-box: fill-box;
animation: comimi-splash-eye 0.4s ease-in-out 0.2s forwards;
@@ -127,12 +136,12 @@ export const splashScreenStyles = `
.comimi-splash-heart::before {
transform: translateX(-32%) rotate(45deg);
- background-color: #eee;
+ background-color: var(--comimi-splash-heart-left);
}
.comimi-splash-heart::after {
transform: translateX(32%) rotate(-45deg);
- background-color: #fff;
+ background-color: var(--comimi-splash-heart-right);
}
.comimi-splash-heart-1 {
@@ -148,7 +157,7 @@ export const splashScreenStyles = `
bottom: 0;
left: 50%;
transform: translate(-50%, 120%);
- color: #fff;
+ color: var(--comimi-splash-text);
font-size: 16px;
font-weight: 700;
line-height: 1.45;
diff --git a/src/components/splash-screen.ts b/src/components/splash-screen.ts
index 0c9c45d..3fcdbc4 100644
--- a/src/components/splash-screen.ts
+++ b/src/components/splash-screen.ts
@@ -82,7 +82,7 @@ function buildDefaultSplashSymbol(): SVGSVGElement {
"d",
"M80.44,49.41H31.46c-12.97,6.71-21.6,18.57-21.6,32.1,0,5.8,1.59,11.3,4.43,16.21h83.34c2.83-4.92,4.43-10.41,4.43-16.21,0-13.53-8.63-25.4-21.6-32.1Z"
);
- body.setAttribute("fill", "#e0e0e0");
+ body.setAttribute("class", "comimi-splash-body");
svg.append(body);
const eyes = document.createElementNS(SVG_NS, "g");
@@ -93,7 +93,6 @@ function buildDefaultSplashSymbol(): SVGSVGElement {
eye.setAttribute("cx", cx);
eye.setAttribute("cy", "78.21");
eye.setAttribute("r", "6");
- eye.setAttribute("fill", "#fff");
eyes.append(eye);
}
svg.append(eyes);
@@ -121,7 +120,7 @@ function renderSplashTypo(): HTMLDivElement {
for (const d of letters) {
const path = document.createElementNS(SVG_NS, "path");
path.setAttribute("d", d);
- path.setAttribute("fill", "#fff");
+ path.setAttribute("class", "comimi-splash-typo-letter");
svg.append(path);
}
diff --git a/src/components/tooltip.styles.ts b/src/components/tooltip.styles.ts
index 457518b..c1b756d 100644
--- a/src/components/tooltip.styles.ts
+++ b/src/components/tooltip.styles.ts
@@ -5,10 +5,10 @@ export const tooltipStyles = `
left: 50%;
padding: 6px 10px;
border-radius: 8px;
- background: rgba(255, 255, 255, 0.5);
+ background: var(--comimi-overlay);
box-shadow: var(--comimi-shadow);
backdrop-filter: blur(5px);
- color: #333;
+ color: var(--comimi-fg);
font-size: 12px;
font-weight: 600;
line-height: 1.45;
diff --git a/src/components/view-mode-switcher.styles.ts b/src/components/view-mode-switcher.styles.ts
index 461a287..7a8d0a8 100644
--- a/src/components/view-mode-switcher.styles.ts
+++ b/src/components/view-mode-switcher.styles.ts
@@ -38,7 +38,7 @@ export const viewModeSwitcherStyles = `
width: 60px;
height: 100%;
border-radius: 16px;
- background: #666;
+ background: var(--comimi-accent);
transition: transform 0.36s var(--comimi-spring);
}
@@ -52,13 +52,13 @@ export const viewModeSwitcherStyles = `
padding: 0;
border: 0;
background: transparent;
- color: #666;
+ color: var(--comimi-muted);
cursor: pointer;
transition: color 0.2s linear;
}
.comimi-view-switcher-button[data-selected="true"] {
- color: #fff;
+ color: var(--comimi-contrast);
}
.comimi-view-switcher-icon-wrap {
diff --git a/src/components/viewer-root.styles.ts b/src/components/viewer-root.styles.ts
index 73ceb0f..0f2cfb1 100644
--- a/src/components/viewer-root.styles.ts
+++ b/src/components/viewer-root.styles.ts
@@ -6,10 +6,34 @@ export const viewerRootStyles = `
--comimi-fg: #333;
--comimi-muted: #666;
--comimi-soft: #999;
+ --comimi-accent: #666;
+ --comimi-contrast: #fff;
+ --comimi-icon-subtle: #aaa;
--comimi-line: #e0e0e0;
--comimi-shadow: 0 0 8px rgba(0, 0, 0, 0.1);
--comimi-glass: rgba(255, 255, 255, 0.8);
--comimi-glass-strong: rgba(255, 255, 255, 0.8);
+ --comimi-hover: #f1f1f1;
+ --comimi-overlay: rgba(255, 255, 255, 0.5);
+ --comimi-page-surface: #fff;
+ --comimi-page-fg: #111;
+ --comimi-loading-stroke: #ccc;
+ --comimi-loading-body: #fff;
+ --comimi-loading-eye: #ccc;
+ --comimi-loading-text: #aaa;
+ --comimi-splash-bg: #e0e0e0;
+ --comimi-splash-stroke: #fff;
+ --comimi-splash-heart-left: #eee;
+ --comimi-splash-heart-right: #fff;
+ --comimi-splash-text: #fff;
+ --comimi-splash-symbol-fill: #e0e0e0;
+ --comimi-splash-eye-fill: #fff;
+ --comimi-splash-typo-fill: #fff;
+ --comimi-scrollfade: #fff;
+ --comimi-dim: rgba(0, 0, 0, 0.06);
+ --comimi-handle-bg: #fff;
+ --comimi-handle-dot: #bbb;
+ --comimi-handle-dot-hover: #888;
--comimi-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
background: var(--comimi-bg);
color: var(--comimi-fg);
@@ -42,8 +66,55 @@ export const viewerRootStyles = `
}
}
-.comimi-root[data-bg="black"] {
+.comimi-root[data-color-mode="dark"] {
--comimi-bg: #000;
+ --comimi-surface: #191919;
+ --comimi-surface-2: #272727;
+ --comimi-fg: #f2f2f2;
+ --comimi-muted: #cdcdcd;
+ --comimi-soft: #969696;
+ --comimi-accent: #d2d2d2;
+ --comimi-contrast: #121212;
+ --comimi-icon-subtle: #a8a8a8;
+ --comimi-line: #3a3a3a;
+ --comimi-shadow: 0 0 12px rgba(0, 0, 0, 0.45);
+ --comimi-glass: rgba(22, 22, 22, 0.82);
+ --comimi-glass-strong: rgba(16, 16, 16, 0.88);
+ --comimi-hover: rgba(255, 255, 255, 0.08);
+ --comimi-overlay: rgba(16, 16, 16, 0.62);
+ --comimi-page-surface: #111;
+ --comimi-page-fg: #f2f2f2;
+ --comimi-loading-stroke: #7b7b7b;
+ --comimi-loading-body: #000;
+ --comimi-loading-eye: #b5b5b5;
+ --comimi-loading-text: #b0b0b0;
+ --comimi-splash-bg: #1b1b1b;
+ --comimi-splash-stroke: #c8c8c8;
+ --comimi-splash-heart-left: #5a5a5a;
+ --comimi-splash-heart-right: #c8c8c8;
+ --comimi-splash-text: #d5d5d5;
+ --comimi-splash-symbol-fill: #1b1b1b;
+ --comimi-splash-eye-fill: #d8d8d8;
+ --comimi-splash-typo-fill: #d8d8d8;
+ --comimi-scrollfade: #111;
+ --comimi-dim: rgba(255, 255, 255, 0.08);
+ --comimi-handle-bg: #111;
+ --comimi-handle-dot: #666;
+ --comimi-handle-dot-hover: #888;
+}
+
+.comimi-root[data-page-bg="white"] {
+ --comimi-bg: #fff;
+ --comimi-scrollfade: #fff;
+ --comimi-page-surface: #fff;
+ --comimi-page-fg: #111;
+}
+
+.comimi-root[data-page-bg="black"] {
+ --comimi-bg: #111;
+ --comimi-scrollfade: #111;
+ --comimi-page-surface: #111;
+ --comimi-page-fg: #f2f2f2;
}
.comimi-root[data-layout="wide"] {
@@ -75,7 +146,7 @@ export const viewerRootStyles = `
position: relative;
width: 100%;
height: 20px;
- background: #fff;
+ background: var(--comimi-handle-bg);
cursor: ns-resize;
touch-action: none;
}
@@ -89,7 +160,7 @@ export const viewerRootStyles = `
width: 40px;
height: 3px;
border-radius: 999px;
- background: #bbb;
+ background: var(--comimi-handle-dot);
transition:
width 0.36s cubic-bezier(0.34, 1.56, 0.64, 1),
height 0.36s cubic-bezier(0.34, 1.56, 0.64, 1),
@@ -100,7 +171,7 @@ export const viewerRootStyles = `
.comimi-resize-handle:hover::after {
width: 52px;
height: 5px;
- background: #888;
+ background: var(--comimi-handle-dot-hover);
}
}
diff --git a/src/defaults.ts b/src/defaults.ts
index 82c361d..3618667 100644
--- a/src/defaults.ts
+++ b/src/defaults.ts
@@ -10,6 +10,7 @@ export const defaultSettings: ViewerSettings = {
layoutMode: "inline",
autoPageTurnIntervalMs: 5000,
backgroundColor: "white",
+ colorMode: "light",
zoom: {
min: 1,
max: 4,
diff --git a/src/renderer/viewer-renderer.ts b/src/renderer/viewer-renderer.ts
index 57db97c..e3ce23e 100644
--- a/src/renderer/viewer-renderer.ts
+++ b/src/renderer/viewer-renderer.ts
@@ -127,6 +127,7 @@ export class ViewerRenderer {
this.cleanup = [];
this.i18n.setLocale(state.settings.locale);
this.root.dataset.layout = state.layout.mode;
+ this.root.dataset.colorMode = state.settings.colorMode;
this.root.dataset.bg = state.settings.backgroundColor;
if (state.layout.mode === "wide" && state.layout.wideHeightPx) {
diff --git a/src/types.ts b/src/types.ts
index 9d2dc3b..3b924d9 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -1,6 +1,7 @@
export type ReadingDirection = "rtl" | "ltr";
export type PageTurnMode = "single" | "spread";
export type BackgroundColor = "white" | "black";
+export type ColorMode = "light" | "dark";
export type LayoutMode =
| "inline"
| "wide"
@@ -18,6 +19,7 @@ export type HideableControl =
| "direction"
| "interval"
| "backgroundColor"
+ | "colorMode"
// ツールバーの操作
| "pageMode"
| "autoplay"
@@ -69,6 +71,7 @@ export interface ViewerSettings {
layoutMode: LayoutMode;
autoPageTurnIntervalMs: number;
backgroundColor: BackgroundColor;
+ colorMode: ColorMode;
zoom: {
min: number;
max: number;