Feature: Enhance Apperance Settings

This commit is contained in:
Carrianna 2026-02-13 16:53:37 +08:00
parent ac225c738e
commit 9c34f8e82b
3 changed files with 565 additions and 60 deletions

View file

@ -8,5 +8,10 @@
"pathRestrictionPaths": [],
"runningIcon": "⏳",
"pausedIcon": "💐",
"timeDisplayFormat": "smart"
"timeDisplayFormat": "smart",
"timerDisplayStyle": "badge",
"runningTextColor": "#10b981",
"runningBgColor": "rgba(16, 185, 129, 0.15)",
"pausedTextColor": "#6b7280",
"pausedBgColor": "rgba(107, 114, 128, 0.12)"
}

456
main.js
View file

@ -18,7 +18,11 @@ class TimerWidget extends WidgetType {
toDOM() {
const span = document.createElement('span');
span.className = 'timer-widget-display';
// Detect running vs paused state from the HTML class
const isRunning = this.htmlText.includes('class="timer-r"');
const stateClass = isRunning ? 'timer-widget-running' : 'timer-widget-paused';
span.className = `timer-widget-display ${stateClass}`;
// Extract visible content from HTML (【⏳00:00:00 】)
const match = this.htmlText.match(/>([^<]*)<\/span>/);
@ -482,7 +486,8 @@ const TRANSLATIONS = {
bycheckbox: {
name: "Timer by Checkbox",
desc: "Configure checkbox-based timer controls"
}
},
appearance: { name: "Appearance Settings" }
},
autostop: {
name: "Auto-stop timers",
@ -519,6 +524,32 @@ const TRANSLATIONS = {
smart: "Smart Format - Hide hours when zero (MM:SS), show full format (HH:MM:SS) when > 1 hour"
}
},
timerDisplayStyle: {
name: "Timer Display Style",
desc: "Choose the visual style for timer display (applies to both edit and reading modes)",
choice: {
badge: "Badge - Timer shown as a styled badge with background and border",
plain: "Plain - Timer shown as simple colored text"
}
},
timerColors: {
runningText: {
name: "Running Timer Text Color",
desc: "Text color for running timers"
},
runningBg: {
name: "Running Timer Background Color",
desc: "Background color for running timers (badge mode only)"
},
pausedText: {
name: "Paused Timer Text Color",
desc: "Text color for paused timers"
},
pausedBg: {
name: "Paused Timer Background Color",
desc: "Background color for paused timers (badge mode only)"
}
},
enableCheckboxToTimer: {
name: "Enable checkbox to timer",
desc: "Allow checkboxes to control timers",
@ -569,7 +600,8 @@ const TRANSLATIONS = {
bycheckbox: {
name: "通过任务状态自动控制计时器",
desc: "你可以在切换任务状态复选框类型的同时自动生成或更新计时器对Tasks Plugin任务插件用户友好"
}
},
appearance: { name: "外观设置" }
},
autostop: {
name: "自动停止计时器",
@ -606,6 +638,32 @@ const TRANSLATIONS = {
smart: "智能格式 - 小时为零时隐藏 (MM:SS)超过1小时时显示完整格式 (HH:MM:SS)"
}
},
timerDisplayStyle: {
name: "计时器显示风格",
desc: "选择计时器的显示风格(同时应用于编辑模式和阅读模式)",
choice: {
badge: "徽章样式 - 带背景色和边框的标签风格",
plain: "纯文本样式 - 仅显示彩色文字"
}
},
timerColors: {
runningText: {
name: "运行中计时器文字颜色",
desc: "运行中计时器的文字颜色"
},
runningBg: {
name: "运行中计时器背景颜色",
desc: "运行中计时器的背景颜色(仅徽章模式)"
},
pausedText: {
name: "已暂停计时器文字颜色",
desc: "已暂停计时器的文字颜色"
},
pausedBg: {
name: "已暂停计时器背景颜色",
desc: "已暂停计时器的背景颜色(仅徽章模式)"
}
},
enableCheckboxToTimer: {
name: "使用任务状态控制计时器",
desc: "启用此功能后,你可以通过更改任务框的状态自动控制计时器的启动、暂停、继续",
@ -656,7 +714,8 @@ const TRANSLATIONS = {
bycheckbox: {
name: "通過任務狀態自動控制計時器",
desc: "你可以在切換任務狀態的同時自动生成或更新計時器對Tasks Plugin任務插件用戶友好"
}
},
appearance: { name: "外觀設定" }
},
autostop: {
name: "自動停止計時器",
@ -693,6 +752,32 @@ const TRANSLATIONS = {
smart: "智能格式 - 小時為零時隱藏 (MM:SS)超過1小時時顯示完整格式 (HH:MM:SS)"
}
},
timerDisplayStyle: {
name: "計時器顯示風格",
desc: "選擇計時器的顯示風格(同時應用於編輯模式和閱讀模式)",
choice: {
badge: "徽章樣式 - 帶背景色和邊框的標籤風格",
plain: "純文字樣式 - 僅顯示彩色文字"
}
},
timerColors: {
runningText: {
name: "運行中計時器文字顏色",
desc: "運行中計時器的文字顏色"
},
runningBg: {
name: "運行中計時器背景顏色",
desc: "運行中計時器的背景顏色(僅徽章模式)"
},
pausedText: {
name: "已暫停計時器文字顏色",
desc: "已暫停計時器的文字顏色"
},
pausedBg: {
name: "已暫停計時器背景顏色",
desc: "已暫停計時器的背景顏色(僅徽章模式)"
}
},
enableCheckboxToTimer: {
name: "使用任務狀態控制計時器",
desc: "啟用此功能後,你可以通過更改任務框的狀態自動控制計時器的啟動、暫停、繼續",
@ -743,7 +828,8 @@ const TRANSLATIONS = {
bycheckbox: {
name: "チェックボックスでタイマーを自動制御",
desc: "チェックボックスを切り替えるだけでタイマーが自動作成・更新されます。Tasks プラグインユーザーに特に便利です。"
}
},
appearance: { name: "外観設定" }
},
autostop: {
name: "タイマーの自動停止",
@ -780,6 +866,32 @@ const TRANSLATIONS = {
smart: "スマートフォーマット - 0時間の場合は非表示 (MM:SS)、1時間以上の場合はフルフォーマット (HH:MM:SS) を表示"
}
},
timerDisplayStyle: {
name: "タイマー表示スタイル",
desc: "タイマーの表示スタイルを選択してください(編集モードと閲覧モードの両方に適用されます)",
choice: {
badge: "バッジスタイル - 背景色と枠線付きのラベルスタイル",
plain: "プレーンスタイル - シンプルなカラーテキスト"
}
},
timerColors: {
runningText: {
name: "実行中タイマーの文字色",
desc: "実行中タイマーのテキスト色"
},
runningBg: {
name: "実行中タイマーの背景色",
desc: "実行中タイマーの背景色(バッジモードのみ)"
},
pausedText: {
name: "一時停止タイマーの文字色",
desc: "一時停止タイマーのテキスト色"
},
pausedBg: {
name: "一時停止タイマーの背景色",
desc: "一時停止タイマーの背景色(バッジモードのみ)"
}
},
enableCheckboxToTimer: {
name: "タスク状態制御タイマーを使います",
desc: "この機能を有効にすると、タスクボックスの状態を変更することでタイマーの起動、停止、継続を自働的に制御できます。",
@ -830,7 +942,8 @@ const TRANSLATIONS = {
bycheckbox: {
name: "체크박스를 통한 자동 타이머 제어",
desc: "태스크 상태를 전환하는 동안 타이머를 자동으로 생성하거나 업데이트할 수 있으며, Tasks Plugin 사용자들에게 매우 우호적입니다"
}
},
appearance: { name: "외관 설정" }
},
autostop: {
name: "타이머 자동 정지",
@ -867,6 +980,32 @@ const TRANSLATIONS = {
smart: "스마트 형식 - 0시간일 때 숨김 (MM:SS), 1시간 이상일 때 전체 형식 (HH:MM:SS) 표시"
}
},
timerDisplayStyle: {
name: "타이머 표시 스타일",
desc: "타이머의 표시 스타일을 선택하세요 (편집 모드와 읽기 모드 모두에 적용됩니다)",
choice: {
badge: "배지 스타일 - 배경색과 테두리가 있는 라벨 스타일",
plain: "일반 스타일 - 심플한 컬러 텍스트"
}
},
timerColors: {
runningText: {
name: "실행 중 타이머 텍스트 색상",
desc: "실행 중인 타이머의 텍스트 색상"
},
runningBg: {
name: "실행 중 타이머 배경 색상",
desc: "실행 중인 타이머의 배경 색상 (배지 모드 전용)"
},
pausedText: {
name: "일시정지 타이머 텍스트 색상",
desc: "일시정지된 타이머의 텍스트 색상"
},
pausedBg: {
name: "일시정지 타이머 배경 색상",
desc: "일시정지된 타이머의 배경 색상 (배지 모드 전용)"
}
},
enableCheckboxToTimer: {
name: "체크박스로 타이머 제어",
desc: "이 기능을 사용하면 작업 상자의 상태를 변경하여 타이머의 시작, 일시 정지, 계속을 자동으로 제어할 수 있습니다",
@ -1506,11 +1645,20 @@ class TimerPlugin extends obsidian.Plugin {
pathRestrictionPaths: [],
runningIcon: '⏳',
pausedIcon: '💐',
timeDisplayFormat: 'full'
timeDisplayFormat: 'full',
timerDisplayStyle: 'badge',
// Color customization
runningTextColor: '#10b981',
runningBgColor: 'rgba(16, 185, 129, 0.15)',
pausedTextColor: '#6b7280',
pausedBgColor: 'rgba(107, 114, 128, 0.12)'
};
await this.loadSettings();
// Apply timer display style to body
this.applyDisplayStyle();
// Initialize TimerFileManager with settings
this.fileManager = new TimerFileManager(this.app, this.settings);
@ -1685,6 +1833,15 @@ class TimerPlugin extends obsidian.Plugin {
onunload() {
this.manager.clearAll();
this.fileManager.clearLocations();
// Clean up body class
document.body.classList.remove('timer-style-badge', 'timer-style-plain');
// Clean up CSS custom properties
const root = document.documentElement;
['--timer-running-color', '--timer-running-bg', '--timer-running-border',
'--timer-running-bg-hover', '--timer-running-border-hover',
'--timer-paused-color', '--timer-paused-bg', '--timer-paused-border',
'--timer-paused-bg-hover', '--timer-paused-border-hover'
].forEach(prop => root.style.removeProperty(prop));
}
@ -1954,6 +2111,63 @@ class TimerPlugin extends obsidian.Plugin {
}
}
applyDisplayStyle() {
const style = this.settings.timerDisplayStyle || 'badge';
document.body.classList.remove('timer-style-badge', 'timer-style-plain');
document.body.classList.add(`timer-style-${style}`);
this.applyTimerColors();
}
/**
* Convert a hex color to rgba with given alpha
*/
hexToRgba(hex, alpha) {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
/**
* Apply user-customized timer colors as CSS custom properties
*/
applyTimerColors() {
const root = document.documentElement;
const s = this.settings;
// Running colors
const runningColor = s.runningTextColor || '#10b981';
const runningBg = s.runningBgColor || 'rgba(16, 185, 129, 0.15)';
root.style.setProperty('--timer-running-color', runningColor);
root.style.setProperty('--timer-running-bg', runningBg);
// Compute border & hover variants from bg
// Parse runningBg to derive border (higher alpha) and hover (higher alpha)
const runningBgMatch = runningBg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),?\s*([\d.]*)\)/);
if (runningBgMatch) {
const [, rr, rg, rb, ra] = runningBgMatch;
const baseAlpha = parseFloat(ra) || 0.15;
root.style.setProperty('--timer-running-border', `rgba(${rr}, ${rg}, ${rb}, ${Math.min(baseAlpha + 0.15, 1)})`);
root.style.setProperty('--timer-running-bg-hover', `rgba(${rr}, ${rg}, ${rb}, ${Math.min(baseAlpha + 0.1, 1)})`);
root.style.setProperty('--timer-running-border-hover', `rgba(${rr}, ${rg}, ${rb}, ${Math.min(baseAlpha + 0.35, 1)})`);
}
// Paused colors
const pausedColor = s.pausedTextColor || '#6b7280';
const pausedBg = s.pausedBgColor || 'rgba(107, 114, 128, 0.12)';
root.style.setProperty('--timer-paused-color', pausedColor);
root.style.setProperty('--timer-paused-bg', pausedBg);
const pausedBgMatch = pausedBg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),?\s*([\d.]*)\)/);
if (pausedBgMatch) {
const [, pr, pg, pb, pa] = pausedBgMatch;
const baseAlpha = parseFloat(pa) || 0.12;
root.style.setProperty('--timer-paused-border', `rgba(${pr}, ${pg}, ${pb}, ${Math.min(baseAlpha + 0.13, 1)})`);
root.style.setProperty('--timer-paused-bg-hover', `rgba(${pr}, ${pg}, ${pb}, ${Math.min(baseAlpha + 0.08, 1)})`);
root.style.setProperty('--timer-paused-border-hover', `rgba(${pr}, ${pg}, ${pb}, ${Math.min(baseAlpha + 0.28, 1)})`);
}
}
toggleTimerbyCheckboxState(oldCheckboxState, newCheckboxState, newLineText, view, lineNum) {
if (oldCheckboxState === '') {
@ -1996,6 +2210,20 @@ class TimerSettingTab extends obsidian.PluginSettingTab {
return filePath + '/';
}
/**
* Convert rgba string to hex color for color picker input
*/
rgbaToHex(rgba) {
const match = rgba.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
if (match) {
const r = parseInt(match[1]).toString(16).padStart(2, '0');
const g = parseInt(match[2]).toString(16).padStart(2, '0');
const b = parseInt(match[3]).toString(16).padStart(2, '0');
return `#${r}${g}${b}`;
}
return rgba; // fallback if already hex
}
display() {
const { containerEl } = this;
containerEl.empty();
@ -2054,47 +2282,6 @@ class TimerSettingTab extends obsidian.PluginSettingTab {
});
});
// Timer icon settings
new obsidian.Setting(containerEl)
.setName(lang.timerIcon.runningIcon.name)
.setDesc(lang.timerIcon.runningIcon.desc)
.addText(text => {
text
.setValue(this.plugin.settings.runningIcon)
.onChange(async(value) => {
this.plugin.settings.runningIcon = value || '⏳';
await this.plugin.saveSettings();
});
});
new obsidian.Setting(containerEl)
.setName(lang.timerIcon.pausedIcon.name)
.setDesc(lang.timerIcon.pausedIcon.desc)
.addText(text => {
text
.setValue(this.plugin.settings.pausedIcon)
.onChange(async(value) => {
this.plugin.settings.pausedIcon = value || '💐';
await this.plugin.saveSettings();
});
});
// Time display format settings
const timeFormatLang = lang.timeDisplayFormat;
new obsidian.Setting(containerEl)
.setName(timeFormatLang.name)
.setDesc(timeFormatLang.desc)
.addDropdown(dropdown => {
dropdown
.addOption('full', timeFormatLang.choice.full)
.addOption('smart', timeFormatLang.choice.smart)
.setValue(this.plugin.settings.timeDisplayFormat || 'full')
.onChange(async(value) => {
this.plugin.settings.timeDisplayFormat = value;
await this.plugin.saveSettings();
});
});
containerEl.createEl('div', { text: '' });
containerEl.createEl('h3', { text: lang.sections.bycommand.name });
new obsidian.Setting(containerEl)
@ -2255,6 +2442,179 @@ class TimerSettingTab extends obsidian.PluginSettingTab {
}
}
}
// ===== Appearance Settings Section =====
containerEl.createEl('div', { text: '' });
containerEl.createEl('h3', { text: lang.sections.appearance.name });
// Time display format settings
const timeFormatLang = lang.timeDisplayFormat;
new obsidian.Setting(containerEl)
.setName(timeFormatLang.name)
.setDesc(timeFormatLang.desc)
.addDropdown(dropdown => {
dropdown
.addOption('full', timeFormatLang.choice.full)
.addOption('smart', timeFormatLang.choice.smart)
.setValue(this.plugin.settings.timeDisplayFormat || 'full')
.onChange(async(value) => {
this.plugin.settings.timeDisplayFormat = value;
await this.plugin.saveSettings();
});
});
// Timer display style settings
const displayStyleLang = lang.timerDisplayStyle;
new obsidian.Setting(containerEl)
.setName(displayStyleLang.name)
.setDesc(displayStyleLang.desc)
.addDropdown(dropdown => {
dropdown
.addOption('badge', displayStyleLang.choice.badge)
.addOption('plain', displayStyleLang.choice.plain)
.setValue(this.plugin.settings.timerDisplayStyle || 'badge')
.onChange(async(value) => {
this.plugin.settings.timerDisplayStyle = value;
await this.plugin.saveSettings();
this.plugin.applyDisplayStyle();
this.display(); // Re-render to show/hide bg color pickers
});
});
// Color customization settings
const colorLang = lang.timerColors;
const isBadge = (this.plugin.settings.timerDisplayStyle || 'badge') === 'badge';
// Helper: create a color picker setting
const addColorSetting = (name, desc, settingKey, defaultColor) => {
const setting = new obsidian.Setting(containerEl)
.setName(name)
.setDesc(desc);
setting.controlEl.createEl('input', {
type: 'color',
value: this.plugin.settings[settingKey] || defaultColor,
cls: 'timer-color-input-native'
}, (input) => {
input.style.width = '40px';
input.style.height = '30px';
input.style.border = 'none';
input.style.padding = '0';
input.style.cursor = 'pointer';
input.style.backgroundColor = 'transparent';
input.addEventListener('input', async(e) => {
this.plugin.settings[settingKey] = e.target.value;
// For bg color, convert hex to rgba
if (settingKey.endsWith('BgColor')) {
const hex = e.target.value;
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
this.plugin.settings[settingKey] = `rgba(${r}, ${g}, ${b}, 0.15)`;
}
await this.plugin.saveSettings();
this.plugin.applyTimerColors();
});
});
return setting;
};
// Running timer icon
new obsidian.Setting(containerEl)
.setName(lang.timerIcon.runningIcon.name)
.setDesc(lang.timerIcon.runningIcon.desc)
.addText(text => {
text
.setValue(this.plugin.settings.runningIcon)
.onChange(async(value) => {
this.plugin.settings.runningIcon = value || '⏳';
await this.plugin.saveSettings();
});
});
// Running text color
addColorSetting(
colorLang.runningText.name,
colorLang.runningText.desc,
'runningTextColor',
'#10b981'
);
// Running bg color (badge mode only)
if (isBadge) {
const runBgSetting = new obsidian.Setting(containerEl)
.setName(colorLang.runningBg.name)
.setDesc(colorLang.runningBg.desc);
runBgSetting.controlEl.createEl('input', {
type: 'color',
value: this.rgbaToHex(this.plugin.settings.runningBgColor || 'rgba(16, 185, 129, 0.15)'),
cls: 'timer-color-input-native'
}, (input) => {
input.style.width = '40px';
input.style.height = '30px';
input.style.border = 'none';
input.style.padding = '0';
input.style.cursor = 'pointer';
input.style.backgroundColor = 'transparent';
input.addEventListener('input', async(e) => {
const hex = e.target.value;
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
this.plugin.settings.runningBgColor = `rgba(${r}, ${g}, ${b}, 0.15)`;
await this.plugin.saveSettings();
this.plugin.applyTimerColors();
});
});
}
// Paused timer icon
new obsidian.Setting(containerEl)
.setName(lang.timerIcon.pausedIcon.name)
.setDesc(lang.timerIcon.pausedIcon.desc)
.addText(text => {
text
.setValue(this.plugin.settings.pausedIcon)
.onChange(async(value) => {
this.plugin.settings.pausedIcon = value || '💐';
await this.plugin.saveSettings();
});
});
// Paused text color
addColorSetting(
colorLang.pausedText.name,
colorLang.pausedText.desc,
'pausedTextColor',
'#6b7280'
);
// Paused bg color (badge mode only)
if (isBadge) {
const pausedBgSetting = new obsidian.Setting(containerEl)
.setName(colorLang.pausedBg.name)
.setDesc(colorLang.pausedBg.desc);
pausedBgSetting.controlEl.createEl('input', {
type: 'color',
value: this.rgbaToHex(this.plugin.settings.pausedBgColor || 'rgba(107, 114, 128, 0.12)'),
cls: 'timer-color-input-native'
}, (input) => {
input.style.width = '40px';
input.style.height = '30px';
input.style.border = 'none';
input.style.padding = '0';
input.style.cursor = 'pointer';
input.style.backgroundColor = 'transparent';
input.addEventListener('input', async(e) => {
const hex = e.target.value;
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
this.plugin.settings.pausedBgColor = `rgba(${r}, ${g}, ${b}, 0.12)`;
await this.plugin.saveSettings();
this.plugin.applyTimerColors();
});
});
}
}
}

View file

@ -1,27 +1,167 @@
.timer-r {
color: #10b981;
/* ===== CSS Custom Properties (defaults, overridden by JS) ===== */
:root {
/* Running timer colors */
--timer-running-color: #10b981;
--timer-running-bg: rgba(16, 185, 129, 0.15);
--timer-running-border: rgba(16, 185, 129, 0.3);
--timer-running-bg-hover: rgba(16, 185, 129, 0.25);
--timer-running-border-hover: rgba(16, 185, 129, 0.5);
/* Paused timer colors */
--timer-paused-color: #6b7280;
--timer-paused-bg: rgba(107, 114, 128, 0.12);
--timer-paused-border: rgba(107, 114, 128, 0.25);
--timer-paused-bg-hover: rgba(107, 114, 128, 0.2);
--timer-paused-border-hover: rgba(107, 114, 128, 0.4);
}
/* Timer widget display in edit mode */
/* ===== Common widget base ===== */
.timer-widget-display {
display: inline-block;
cursor: pointer;
user-select: none;
}
/* ===== Badge Style (default) ===== */
/* Badge common properties */
.timer-style-badge .timer-r,
.timer-style-badge .timer-p,
.timer-style-badge .timer-widget-running,
.timer-style-badge .timer-widget-paused {
display: inline-block;
padding: 0 4px;
margin: 0 2px;
border-radius: 3px;
background-color: rgba(16, 185, 129, 0.15);
color: #10b981;
font-weight: 500;
cursor: pointer;
user-select: none;
border: 1px solid rgba(16, 185, 129, 0.3);
font-family: system-ui, -apple-system, sans-serif;
font-size: 0.95em;
transition: background-color 0.2s ease;
transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
.timer-widget-display:hover {
background-color: rgba(16, 185, 129, 0.25);
border-color: rgba(16, 185, 129, 0.5);
/* Badge - Running timer (preview mode) */
.timer-style-badge .timer-r {
background-color: var(--timer-running-bg);
color: var(--timer-running-color);
border: 1px solid var(--timer-running-border);
}
.timer-style-badge .timer-r:hover {
background-color: var(--timer-running-bg-hover);
border-color: var(--timer-running-border-hover);
}
/* Badge - Paused timer (preview mode) */
.timer-style-badge .timer-p {
background-color: var(--timer-paused-bg);
color: var(--timer-paused-color);
border: 1px solid var(--timer-paused-border);
}
.timer-style-badge .timer-p:hover {
background-color: var(--timer-paused-bg-hover);
border-color: var(--timer-paused-border-hover);
}
/* Badge - Running timer widget (edit mode) */
.timer-style-badge .timer-widget-running {
background-color: var(--timer-running-bg);
color: var(--timer-running-color);
border: 1px solid var(--timer-running-border);
cursor: pointer;
}
.timer-style-badge .timer-widget-running:hover {
background-color: var(--timer-running-bg-hover);
border-color: var(--timer-running-border-hover);
}
/* Badge - Paused timer widget (edit mode) */
.timer-style-badge .timer-widget-paused {
background-color: var(--timer-paused-bg);
color: var(--timer-paused-color);
border: 1px solid var(--timer-paused-border);
cursor: pointer;
}
.timer-style-badge .timer-widget-paused:hover {
background-color: var(--timer-paused-bg-hover);
border-color: var(--timer-paused-border-hover);
}
/* ===== Plain Style ===== */
/* Plain - Running timer (preview mode) */
.timer-style-plain .timer-r {
color: var(--timer-running-color);
}
/* Plain - Paused timer (preview mode) - no special style, inherit default */
.timer-style-plain .timer-p {
color: var(--timer-paused-color);
}
/* Plain - Running timer widget (edit mode) */
.timer-style-plain .timer-widget-running {
color: var(--timer-running-color);
cursor: pointer;
}
/* Plain - Paused timer widget (edit mode) */
.timer-style-plain .timer-widget-paused {
color: var(--timer-paused-color);
cursor: pointer;
}
/* ===== Color Picker Settings UI ===== */
.timer-color-setting {
display: flex;
align-items: center;
gap: 8px;
}
.timer-color-preview {
width: 28px;
height: 28px;
border-radius: 4px;
border: 1px solid var(--background-modifier-border);
cursor: pointer;
transition: box-shadow 0.2s ease;
}
.timer-color-preview:hover {
box-shadow: 0 0 0 2px var(--interactive-accent);
}
.timer-color-input {
position: absolute;
width: 0;
height: 0;
opacity: 0;
overflow: hidden;
}