Skip to content

TRIOS Color System: Centralized Color Control for Chromium + TRIOS Extension #500

@gHashTag

Description

@gHashTag

TRIOS Color System — Централизованное управление цветом

AEL v2.0 | GO. Target repo: /Users/playra/BrowserOS


Архитектурная карта цветовой системы

Проект состоит из трёх независимых слоёв — у каждого своя система цвета:

┌─────────────────────────────────────────────────┐
│  LAYER 3: TRIOS Extension (React/Tailwind/CSS)  │
│  apps/agent/styles/global.css                   │
│  CSS variables: --background, --card, --sidebar │
├─────────────────────────────────────────────────┤
│  LAYER 2: Chromium C++ Patches                  │
│  chromium_patches/chrome/browser/themes/        │
│  chromium_patches/chrome/browser/browseros/core │
│  SkColor, BrowserColorScheme, kUserColor        │
├─────────────────────────────────────────────────┤
│  LAYER 1: User Preferences (Runtime)            │
│  ~/Library/Application Support/BrowserOS/       │
│  Default/Preferences (JSON)                     │
└─────────────────────────────────────────────────┘

Проблема: Изменение одного слоя не влияет на другие. Нужен единый источник правды.


ЦЕЛЬ: Единый источник — trios_theme.h

Создать один файл-константы который читают ВСЕ три слоя:

packages/browseros/chromium_patches/
  chrome/browser/browseros/core/trios_theme.h   ← ЕДИНЫЙ ИСТОЧНИК

Phase 1: Создать trios_theme.h — Single Source of Truth

Создать новый файл:
packages/browseros/chromium_patches/chrome/browser/browseros/core/trios_theme.h

// Copyright 2026 TRIOS
// Central color system for TRIOS — edit HERE only

#ifndef CHROME_BROWSER_BROWSEROS_CORE_TRIOS_THEME_H_
#define CHROME_BROWSER_BROWSEROS_CORE_TRIOS_THEME_H_

#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/mojom/themes.mojom.h"

namespace trios {

// ═══════════════════════════════════════
//  EDIT ONLY THIS SECTION TO CHANGE THEME
// ═══════════════════════════════════════

// Chromium browser frame color (toolbar, tab strip)
// 0x000000 = pure black
constexpr SkColor kFrameColor = SkColorSetRGB(0x00, 0x00, 0x00);

// User accent color (seed for Material You palette)
constexpr SkColor kAccentColor = SkColorSetRGB(0x88, 0x88, 0x88);

// Default browser color scheme: kDark = 2, kLight = 1, kSystem = 0
constexpr int kDefaultColorScheme =
    static_cast<int>(ThemeService::BrowserColorScheme::kDark);

// Color variant: kNeutral, kTonalSpot, kVibrant, kExpressive
constexpr ui::mojom::BrowserColorVariant kColorVariant =
    ui::mojom::BrowserColorVariant::kNeutral;

// ═══════════════════════════════════════
//  CSS variables exported to Extension
//  (used by generate_css_vars.py to
//   auto-generate global.css)
// ═══════════════════════════════════════

// Background: oklch(0 0 0) = #000000
constexpr char kCSSBackground[] = "oklch(0 0 0)";
constexpr char kCSSCard[]       = "oklch(0.04 0 0)";
constexpr char kCSSBorder[]     = "oklch(0.18 0 0)";
constexpr char kCSSForeground[] = "oklch(0.93 0 0)";
constexpr char kCSSMuted[]      = "oklch(0.08 0 0)";
constexpr char kCSSAccent[]     = "oklch(0.14 0 0)";
constexpr char kCSSSidebar[]    = "oklch(0 0 0)";
constexpr char kCSSInput[]      = "oklch(0.12 0 0)";

}  // namespace trios

#endif  // CHROME_BROWSER_BROWSEROS_CORE_TRIOS_THEME_H_

Phase 2: Подключить trios_theme.h в theme_service.cc

File: packages/browseros/chromium_patches/chrome/browser/themes/theme_service.cc

Изменить текущий патч:

+#include "chrome/browser/browseros/core/trios_theme.h"

 // RegisterProfilePrefs:
-  static_cast<int>(ThemeService::BrowserColorScheme::kLight),
+  trios::kDefaultColorScheme,

-  static_cast<int>(ThemeService::BrowserColorScheme::kLight));
+  trios::kDefaultColorScheme);

Phase 3: Подключить в browseros_prefs.cc — SyncDefaultTheme

File: packages/browseros/chromium_patches/chrome/browser/browseros/core/browseros_prefs.cc

Изменить функцию SyncDefaultTheme:

+#include "chrome/browser/browseros/core/trios_theme.h"

 void SyncDefaultTheme(PrefService* pref_service) {
   const PrefService::Preference* user_color_pref =
       pref_service->FindPreference(::prefs::kUserColor);
   if (user_color_pref && user_color_pref->IsDefaultValue()) {
     pref_service->SetInteger(::prefs::kUserColor,
-                             static_cast<int>(SkColorSetRGB(136, 136, 136)));
+                             static_cast<int>(trios::kFrameColor));
     pref_service->SetString(::prefs::kCurrentThemeID,
                             "user_color_theme_id");
     pref_service->SetInteger(
         ::prefs::kBrowserColorVariant,
-        static_cast<int>(ui::mojom::BrowserColorVariant::kNeutral));
+        static_cast<int>(trios::kColorVariant));
+    pref_service->SetInteger(
+        ::prefs::kBrowserColorScheme,
+        trios::kDefaultColorScheme);
   }
 }

Phase 4: BUILD.gn — добавить trios_theme.h в сборку

File: packages/browseros/chromium_patches/chrome/browser/browseros/core/BUILD.gn

 sources = [
+  "trios_theme.h",
   "browseros_prefs.cc",
   "browseros_prefs.h",
   ...
 ]

Phase 5: Python-скрипт — генерация CSS из trios_theme.h

Создать packages/browseros/tools/generate_css_vars.py:

#!/usr/bin/env python3
"""
Auto-generates global.css dark theme variables from trios_theme.h
Run: python3 tools/generate_css_vars.py
"""
import re
import pathlib

THEME_H = pathlib.Path(
    "chromium_patches/chrome/browser/browseros/core/trios_theme.h"
)
CSS_FILE = pathlib.Path(
    "../browseros-agent/apps/agent/styles/global.css"
)

# Parse C++ constexpr string values
pattern = re.compile(r'constexpr char k(CSS\w+)\[\]\s*=\s*"([^"]+)"')
theme = {}
for m in pattern.finditer(THEME_H.read_text()):
    key = m.group(1).replace('CSS', '').lower()
    theme[key] = m.group(2)

# Build CSS block
def make_block(selector, bg_key='background'):
    return f"""{selector} {{
  --background: {theme.get('background', 'oklch(0 0 0)')};
  --foreground: {theme.get('foreground', 'oklch(0.93 0 0)')};
  --card: {theme.get('card', 'oklch(0.04 0 0)')};
  --card-foreground: {theme.get('foreground', 'oklch(0.93 0 0)')};
  --popover: {theme.get('card', 'oklch(0.04 0 0)')};
  --popover-foreground: {theme.get('foreground', 'oklch(0.93 0 0)')};
  --sidebar: {theme.get('sidebar', 'oklch(0 0 0)')};
  --muted: {theme.get('muted', 'oklch(0.08 0 0)')};
  --muted-foreground: oklch(0.60 0 0);
  --accent: {theme.get('accent', 'oklch(0.14 0 0)')};
  --accent-foreground: {theme.get('foreground', 'oklch(0.93 0 0)')};
  --border: {theme.get('border', 'oklch(0.18 0 0)')};
  --input: {theme.get('input', 'oklch(0.12 0 0)')};
}}"""

css = CSS_FILE.read_text()
# Replace :root and .dark blocks (between markers)
root_block = make_block(':root')
dark_block = make_block('.dark')

# Simple replacement of existing blocks
import re
css = re.sub(r':root\s*\{[^}]+\}', root_block, css, count=1)
css = re.sub(r'\.dark\s*\{[^}]+\}', dark_block, css, count=1)

CSS_FILE.write_text(css)
print(f'✓ Updated {CSS_FILE}')
print(f'  background: {theme.get("background")}')
print(f'  card: {theme.get("card")}')

Добавить в package.json scripts:

"theme:sync": "cd packages/browseros && python3 tools/generate_css_vars.py"

Phase 6: Runtime Preferences — быстрый фикс без ребилда

Этот скрипт меняет тему СРАЗУ без пересборки Chromium:

Создать packages/browseros/tools/set_dark_theme.py:

#!/usr/bin/env python3
"""Apply TRIOS dark theme to current BrowserOS user profile.
No rebuild needed — takes effect on next BrowserOS restart."""
import json, pathlib, sys

PREFS = pathlib.Path.home() / \
    "Library/Application Support/BrowserOS/Default/Preferences"

if not PREFS.exists():
    sys.exit(f"Profile not found: {PREFS}")

data = json.loads(PREFS.read_text())

# kDark=2 for BrowserColorScheme
browser = data.setdefault('browser', {})
browser['color_scheme2'] = 2  # kDark

# Black frame color (SkColor ARGB: 0xFF000000)
browser['user_color2'] = 0xFF000000  # pure black

# Remove cached theme to force recompute
data.pop('extensions', {}).pop('theme', None)
extensions = data.setdefault('extensions', {})
extensions['theme'] = {'id': '', 'pack_hash': ''}

PREFS.write_text(json.dumps(data, indent=2))
print('✓ TRIOS dark theme applied')
print('  Restart BrowserOS to see changes')

Добавить в package.json:

"theme:apply": "python3 packages/browseros/tools/set_dark_theme.py"

Phase 7: wxt/storage dev-mode fix (уже в issue #499)

File: packages/browseros-agent/apps/agent/lib/theme/theme-storage.ts

Fallback для bun dev — localStorage с дефолтом 'dark'.
(Детали в issue #499)


Итоговая схема управления

  trios_theme.h          ← ЕДИНСТВЕННОЕ место для правки цветов
      │
      ├── theme_service.cc       → kDefaultColorScheme → Chromium frame
      │
      ├── browseros_prefs.cc     → SyncDefaultTheme() → kUserColor / kBrowserColorScheme
      │
      └── generate_css_vars.py   → global.css          → Extension UI
                                                           (--background, --card, etc.)

  set_dark_theme.py  → Preferences JSON  → быстрый runtime override (без ребилда)

Workflow для смены цвета

# 1. Открыть trios_theme.h и изменить константы
vim packages/browseros/chromium_patches/chrome/browser/browseros/core/trios_theme.h

# 2. Синхронизировать CSS Extension
bun run theme:sync  # или: python3 packages/browseros/tools/generate_css_vars.py

# 3. Применить к runtime профилю (без ребилда!)
bun run theme:apply  # или: python3 packages/browseros/tools/set_dark_theme.py

# 4. Перезапустить dev server
bun dev

# 5. Rebuild Chromium (только для frame/toolbar цвета)
cd packages/browseros && ./build.sh

Verification

  • trios_theme.h существует и компилируется
  • theme_service.cc использует trios::kDefaultColorScheme
  • browseros_prefs.cc использует trios::kFrameColor
  • generate_css_vars.py обновляет global.css из trios_theme.h
  • set_dark_theme.py применяет тему без ребилда
  • bun dev показывает чёрный фон
  • package.json содержит theme:sync и theme:apply
  • Один файл = одно место для изменения всего цвета

Commit

feat(theme): centralized TRIOS color system via trios_theme.h | Closes #[this]

φ² + 1/φ² = 3 | TRINITY DARK

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions