Omni主題切換API:開發者集成主題切換功能的接口

你是否在開發擴展時遇到過主題適配難題?Omni的主題切換API讓開發者能夠輕鬆集成暗色/亮色主題切換功能,無需手動管理複雜的樣式變量。本文將詳解如何使用Omni的主題系統,實現跟隨系統設置或手動控制的主題切換功能。

主題系統基礎架構

Omni通過CSS變量和媒體查詢實現主題切換,核心定義在src/content.css文件中。系統採用雙主題模式設計,通過CSS變量隔離不同主題的樣式屬性。

主題變量定義

Omni使用CSS變量定義主題樣式,主要包含背景色、邊框色、文本色等基礎屬性:

/* 暗色主題變量 - [src/content.css](https://link.gitcode.com/i/708b5a6dea380e95944d7603ca38865e) L32-L45 */
@media (prefers-color-scheme: dark) {
  .omni-extension {
    --background: #1e2128;
    --border: #35373e;
    --text: #f1f1f1;
    --text-2: #c5c6ca;
    --text-3: #a5a5ae;
    --select: #17191e;
    --accent: #6068d2;
    --accent-hover: #484fac;
    --shortcut: #383e4a;
    --placeholder: #63687b;
    --background-2: #292d36;
  }
}

/* 亮色主題變量 - [src/content.css](https://link.gitcode.com/i/708b5a6dea380e95944d7603ca38865e) L47-L60 */
@media (prefers-color-scheme: light) {
  .omni-extension {
    --background: #fafcff;
    --border: #f2f3fb;
    --text: #2b2d41;
    --text-2: #2b2d41;
    --text-3: #929db2;
    --select: #eff3f9;
    --accent: #6068d2;
    --accent-hover: #484fac;
    --shortcut: #dadeea;
    --placeholder: #bac2d1;
    --background-2: #292d36;
  }
}

主題切換原理

Omni主題系統基於CSS媒體查詢prefers-color-scheme實現自動切換,當系統主題變化時,瀏覽器會自動應用對應主題的CSS變量。開發者可以通過JavaScript接口覆蓋系統設置,實現手動主題控制。

API接口使用指南

檢測當前主題模式

通過window.matchMediaAPI可以檢測用户系統的主題偏好:

// 檢測系統主題偏好
const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
console.log('當前系統主題:', isDarkMode ? '暗色' : '亮色');

手動切換主題

要實現手動主題切換,需要動態修改根元素的類名,覆蓋CSS媒體查詢的默認行為:

// 手動切換到暗色主題
document.documentElement.classList.add('dark-mode');
document.documentElement.classList.remove('light-mode');

// 手動切換到亮色主題
document.documentElement.classList.add('light-mode');
document.documentElement.classList.remove('dark-mode');

監聽主題變化

通過監聽媒體查詢的變化事件,可以實時響應系統主題切換:

// 監聽主題變化
const themeQuery = window.matchMedia('(prefers-color-scheme: dark)');
themeQuery.addEventListener('change', (e) => {
  const newTheme = e.matches ? 'dark' : 'light';
  console.log('系統主題已切換為:', newTheme);
  // 在這裏更新UI或存儲用户偏好
});

集成示例:主題切換按鈕

以下是一個完整的主題切換按鈕實現示例,包含UI元素和交互邏輯:

<!-- 主題切換按鈕 -->
<button id="theme-toggle" class="omni-theme-toggle">
  <svg class="theme-icon" width="24" height="24">
    <!-- 太陽/月亮圖標 -->
  </svg>
</button>

<style>
  /* 主題切換按鈕樣式 */
  .omni-theme-toggle {
    background: var(--background);
    border: 1px solid var(--border);
    color: var(--text);
    border-radius: 4px;
    padding: 8px;
    cursor: pointer;
  }
  
  .omni-theme-toggle:hover {
    background: var(--background-2);
  }
</style>

<script>
  // 主題切換邏輯
  const themeToggle = document.getElementById('theme-toggle');
  let isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
  
  // 初始化按鈕狀態
  updateThemeIcon();
  
  // 切換主題
  themeToggle.addEventListener('click', () => {
    isDark = !isDark;
    document.documentElement.classList.toggle('dark-mode', isDark);
    document.documentElement.classList.toggle('light-mode', !isDark);
    updateThemeIcon();
    // 可選:保存用户偏好到localStorage
    localStorage.setItem('omni-theme', isDark ? 'dark' : 'light');
  });
  
  // 更新圖標
  function updateThemeIcon() {
    const icon = themeToggle.querySelector('.theme-icon');
    icon.innerHTML = isDark ? 
      '<path d="M20.742 13.045a8.088 8.088 0 01-2.077.271c-2.135 0-4.14-.83-5.667-2.36a8.174 8.174 0 01-2.36-5.667c0-2.135.83-4.14 2.36-5.667A8.101 8.101 0 0113.045 2.077C15.818 2 18 4.182 18 7c0 2.818-2.182 5-5 5a8.287 8.287 0 01-.271 2.077 8.456 8.456 0 01.271 2.077 8.287 8.287 0 012.077.271 8.088 8.088 0 012.077-.271c2.818 0 5 2.182 5 5a8.18 8.18 0 01-.271 2.077z"/>' :
      '<path d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zm0-18c4.411 0 8 3.589 8 8s-3.589 8-8 8-8-3.589-8-8 3.589-8 8-8z"/>';
  }
</script>

高級應用:持久化主題設置

為了提供更好的用户體驗,建議將用户的主題偏好保存到本地存儲,並在擴展啓動時恢復:

// 初始化主題
function initTheme() {
  const savedTheme = localStorage.getItem('omni-theme');
  const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
  
  // 優先級:保存的主題 > 系統主題
  const isDark = savedTheme ? savedTheme === 'dark' : systemDark;
  
  document.documentElement.classList.toggle('dark-mode', isDark);
  document.documentElement.classList.toggle('light-mode', !isDark);
}

// 在擴展加載時調用
initTheme();

瀏覽器兼容性處理

Omni主題系統在Firefox和Chrome擴展中略有差異,主要體現在背景腳本的API調用上:

  • Chrome版本:src/background.js
  • Firefox版本:firefox/background.js

開發者在實現跨瀏覽器擴展時,需要注意使用不同瀏覽器的API前綴(chrome. vs browser.)。

總結與最佳實踐

Omni主題切換API提供了靈活的主題控制能力,通過CSS變量和媒體查詢的結合,實現了簡潔高效的主題管理方案。建議開發者:

  1. 始終使用CSS變量而非硬編碼顏色值
  2. 同時支持系統主題和手動切換
  3. 持久化保存用户主題偏好
  4. 在UI中提供明確的主題狀態指示

通過遵循這些實踐,你可以為用户提供一致且個性化的主題體驗,提升擴展的專業度和易用性。完整的主題實現代碼可參考src/content.css和firefox/content.css文件。