Get started
Desain Impor Tema Kustom Tweakcn
Desain Impor Tema Kustom Tweakcn
Status: disetujui di terminal pada 2026-04-22
Ringkasan
Tambahkan tepat satu slot tema UI Kontrol kustom lokal browser yang dapat diimpor dari tautan berbagi tweakcn. Keluarga tema bawaan yang ada tetap claw, knot, dan dash. Keluarga baru custom berperilaku seperti keluarga tema OpenClaw normal dan mendukung mode light, dark, dan system ketika payload tweakcn yang diimpor menyertakan set token terang dan gelap.
Tema yang diimpor hanya disimpan di profil browser saat ini bersama pengaturan UI Kontrol lainnya. Tema ini tidak ditulis ke konfigurasi Gateway dan tidak disinkronkan lintas perangkat atau browser.
Masalah
Sistem tema UI Kontrol saat ini tertutup pada tiga keluarga tema yang di-hard-code:
ui/src/ui/theme.tsui/src/ui/views/config.tsui/src/styles/base.css
Pengguna dapat beralih di antara keluarga bawaan dan varian mode, tetapi mereka tidak dapat membawa tema dari tweakcn tanpa mengedit CSS repo. Hasil yang diminta lebih kecil daripada sistem tema umum: pertahankan tiga bawaan dan tambahkan satu slot impor yang dikendalikan pengguna yang dapat diganti dari tautan tweakcn.
Tujuan
- Pertahankan keluarga tema bawaan yang ada tanpa perubahan.
- Tambahkan tepat satu slot kustom yang diimpor, bukan pustaka tema.
- Terima tautan berbagi tweakcn atau URL langsung
https://tweakcn.com/r/themes/{id}. - Pertahankan tema yang diimpor hanya di penyimpanan lokal browser.
- Buat slot yang diimpor berfungsi dengan kontrol mode
light,dark, dansystemyang ada. - Jaga perilaku kegagalan tetap aman: impor yang buruk tidak pernah merusak tema UI aktif.
Bukan tujuan
- Tidak ada pustaka multi-tema atau daftar impor lokal browser.
- Tidak ada persistensi sisi Gateway atau sinkronisasi lintas perangkat.
- Tidak ada editor CSS arbitrer atau editor JSON tema mentah.
- Tidak ada pemuatan otomatis aset font jarak jauh dari tweakcn.
- Tidak ada upaya mendukung payload tweakcn yang hanya mengekspos satu mode.
- Tidak ada refaktor tema seluruh repo di luar seam yang diperlukan untuk UI Kontrol.
Keputusan pengguna yang sudah dibuat
- Pertahankan tiga tema bawaan.
- Tambahkan satu slot impor bertenaga tweakcn.
- Simpan tema yang diimpor di browser, bukan konfigurasi Gateway.
- Dukung
light,dark, dansystemuntuk slot yang diimpor. - Menimpa slot kustom dengan impor berikutnya adalah perilaku yang dimaksudkan.
Pendekatan yang direkomendasikan
Tambahkan id keluarga tema keempat, custom, ke model tema UI Kontrol. Keluarga custom menjadi dapat dipilih hanya ketika impor tweakcn yang valid tersedia. Payload yang diimpor dinormalisasi menjadi rekaman tema kustom khusus OpenClaw dan disimpan di penyimpanan lokal browser bersama pengaturan UI lainnya.
Saat runtime, OpenClaw merender tag <style> terkelola yang mendefinisikan blok variabel CSS kustom yang sudah di-resolve:
:root[data-theme="custom"] { ... }
:root[data-theme="custom-light"] { ... }
Ini menjaga variabel tema kustom tetap terscope ke keluarga custom dan menghindari kebocoran variabel CSS inline ke keluarga bawaan.
Arsitektur
Model tema
Perbarui ui/src/ui/theme.ts:
- Perluas
ThemeNameuntuk menyertakancustom. - Perluas
ResolvedThemeuntuk menyertakancustomdancustom-light. - Perluas
VALID_THEME_NAMES. - Perbarui
resolveTheme()agarcustommencerminkan perilaku keluarga yang ada:custom + dark->customcustom + light->custom-lightcustom + system->customataucustom-lightberdasarkan preferensi OS
Tidak ada alias lama yang ditambahkan untuk custom.
Model persistensi
Perluas persistensi UiSettings di ui/src/ui/storage.ts dengan satu payload tema kustom opsional:
customTheme?: ImportedCustomTheme
Bentuk tersimpan yang direkomendasikan:
type ImportedCustomTheme = {
sourceUrl: string;
themeId: string;
label: string;
importedAt: string;
light: Record<string, string>;
dark: Record<string, string>;
};
Catatan:
sourceUrlmenyimpan input pengguna asli setelah normalisasi.themeIdadalah id tema tweakcn yang diekstrak dari URL.labeladalah bidangnametweakcn saat tersedia, jika tidakCustom.lightdandarksudah berupa peta token OpenClaw yang dinormalisasi, bukan payload tweakcn mentah.- Payload yang diimpor berada berdampingan dengan pengaturan lokal browser lainnya dan diserialisasi di dokumen penyimpanan lokal yang sama.
- Jika data tema kustom tersimpan hilang atau tidak valid saat dimuat, abaikan payload dan kembali ke
theme: "claw"ketika keluarga tersimpan adalahcustom.
Penerapan runtime
Tambahkan pengelola stylesheet tema kustom yang sempit di runtime UI Kontrol, dimiliki dekat ui/src/ui/app-settings.ts dan ui/src/ui/theme.ts.
Tanggung jawab:
- Buat atau perbarui satu tag
<style id="openclaw-custom-theme">yang stabil didocument.head. - Emit CSS hanya ketika payload tema kustom yang valid tersedia.
- Hapus konten tag style ketika payload dihapus.
- Pertahankan CSS keluarga bawaan di
ui/src/styles/base.css; jangan menyisipkan token yang diimpor ke stylesheet yang di-check-in.
Pengelola ini berjalan setiap kali pengaturan dimuat, disimpan, diimpor, atau dihapus.
Selector mode terang
Implementasi sebaiknya memilih data-theme-mode="light" untuk styling terang lintas keluarga, bukan memperlakukan custom-light secara khusus. Jika selector yang ada dipatok ke data-theme="light" dan perlu berlaku untuk setiap keluarga terang, perluas selector itu sebagai bagian dari pekerjaan ini.
UX impor
Perbarui ui/src/ui/views/config.ts di bagian Appearance:
- Tambahkan kartu tema
Customdi sampingClaw,Knot, danDash. - Tampilkan kartu sebagai nonaktif ketika tidak ada tema kustom yang diimpor.
- Tambahkan panel impor di bawah grid tema dengan:
- satu input teks untuk tautan berbagi tweakcn atau URL
/r/themes/{id} - satu tombol
Import - satu jalur
Replaceketika payload kustom sudah ada - satu aksi
Clearketika payload kustom sudah ada
- satu input teks untuk tautan berbagi tweakcn atau URL
- Tampilkan label tema yang diimpor dan host sumber ketika payload ada.
- Jika tema aktif adalah
custom, mengimpor pengganti langsung menerapkannya. - Jika tema aktif bukan
custom, impor hanya menyimpan payload baru hingga pengguna memilih kartuCustom.
Pemilih tema pengaturan cepat di ui/src/ui/views/config-quick.ts juga harus menampilkan Custom hanya ketika payload ada.
Penguraian URL dan pengambilan jarak jauh
Jalur impor browser menerima:
https://tweakcn.com/themes/{id}https://tweakcn.com/r/themes/{id}
Implementasi harus menormalisasi kedua bentuk menjadi:
https://tweakcn.com/r/themes/{id}
Browser kemudian mengambil endpoint /r/themes/{id} yang sudah dinormalisasi secara langsung.
Gunakan validator skema sempit untuk payload eksternal. Skema zod lebih disarankan karena ini adalah batas eksternal yang tidak tepercaya.
Bidang jarak jauh yang diperlukan:
nametingkat atas sebagai string opsionalcssVars.themesebagai object opsionalcssVars.lightsebagai objectcssVars.darksebagai object
Jika cssVars.light atau cssVars.dark hilang, tolak impor. Ini disengaja: perilaku produk yang disetujui adalah dukungan mode penuh, bukan sintesis best-effort untuk sisi yang hilang.
Pemetaan token
Jangan mencerminkan variabel tweakcn secara membabi buta. Normalisasi subset terbatas ke token OpenClaw dan turunkan sisanya dalam helper.
Token yang diimpor langsung
Dari setiap blok mode tweakcn:
backgroundforegroundcardcard-foregroundpopoverpopover-foregroundprimaryprimary-foregroundsecondarysecondary-foregroundmutedmuted-foregroundaccentaccent-foregrounddestructivedestructive-foregroundborderinputringradius
Dari cssVars.theme bersama saat tersedia:
font-sansfont-mono
Jika blok mode menimpa font-sans, font-mono, atau radius, nilai lokal mode yang menang.
Token yang diturunkan untuk OpenClaw
Pengimpor menurunkan variabel khusus OpenClaw dari warna dasar yang diimpor:
--bg-accent--bg-elevated--bg-hover--panel--panel-strong--panel-hover--chrome--chrome-strong--text--text-strong--chat-text--muted--muted-strong--accent-hover--accent-muted--accent-subtle--accent-glow--focus--focus-ring--focus-glow--secondary--secondary-foreground--danger--danger-muted--danger-subtle
Aturan penurunan berada di helper murni agar dapat diuji secara independen. Formula pencampuran warna yang tepat adalah detail implementasi, tetapi helper harus memenuhi dua batasan:
- mempertahankan kontras yang terbaca dekat dengan maksud tema yang diimpor
- menghasilkan output yang stabil untuk payload impor yang sama
Token yang diabaikan di v1
Token tweakcn ini sengaja diabaikan pada versi pertama:
chart-*sidebar-*font-serifshadow-*tracking-*letter-spacingspacing
Ini menjaga cakupan pada token yang benar-benar dibutuhkan UI Kontrol saat ini.
Font
String stack font diimpor jika ada, tetapi OpenClaw tidak memuat aset font jarak jauh di v1. Jika stack yang diimpor mereferensikan font yang tidak tersedia di browser, perilaku fallback normal berlaku.
Perilaku kegagalan
Impor buruk harus gagal tertutup.
- Format URL tidak valid: tampilkan galat validasi inline, jangan mengambil.
- Host atau bentuk path tidak didukung: tampilkan galat validasi inline, jangan mengambil.
- Kegagalan jaringan, respons non-OK, atau JSON cacat: tampilkan galat inline, biarkan payload tersimpan saat ini tidak tersentuh.
- Kegagalan skema atau blok terang/gelap yang hilang: tampilkan galat inline, biarkan payload tersimpan saat ini tidak tersentuh.
- Aksi hapus:
- menghapus payload kustom tersimpan
- menghapus konten tag style kustom terkelola
- jika
customaktif, mengganti keluarga tema kembali keclaw
- Payload kustom tersimpan tidak valid pada pemuatan pertama:
- abaikan payload tersimpan
- jangan emit CSS kustom
- jika keluarga tema yang tersimpan adalah
custom, kembali keclaw
Tidak pada titik mana pun impor yang gagal boleh meninggalkan dokumen aktif dengan variabel CSS kustom parsial yang diterapkan.
File yang diharapkan berubah dalam implementasi
File utama:
ui/src/ui/theme.tsui/src/ui/storage.tsui/src/ui/app-settings.tsui/src/ui/views/config.tsui/src/ui/views/config-quick.tsui/src/styles/base.css
Helper baru yang mungkin:
ui/src/ui/custom-theme.ts
Pengujian:
ui/src/ui/app-settings.test.tsui/src/ui/storage.node.test.tsui/src/ui/views/config.browser.test.ts- pengujian terfokus baru untuk penguraian URL dan normalisasi payload
Pengujian
Cakupan implementasi minimum:
- uraikan URL tautan berbagi menjadi id tema tweakcn
- normalisasi
/themes/{id}dan/r/themes/{id}menjadi URL fetch - tolak host yang tidak didukung dan id cacat
- validasi bentuk payload tweakcn
- petakan payload tweakcn yang valid menjadi peta token terang dan gelap OpenClaw yang dinormalisasi
- muat dan simpan payload kustom di pengaturan lokal browser
- resolve
customuntuklight,dark, dansystem - nonaktifkan pemilihan
Customketika tidak ada payload - terapkan tema yang diimpor segera ketika
customsudah aktif - kembali ke
clawketika tema kustom aktif dihapus
Target verifikasi manual:
- impor tema tweakcn yang diketahui dari Settings
- beralih di antara
light,dark, dansystem - beralih antara
customdan keluarga bawaan - muat ulang halaman dan konfirmasi tema kustom yang diimpor bertahan secara lokal
Catatan rollout
Fitur ini sengaja kecil. Jika pengguna nanti meminta beberapa tema impor, penggantian nama, ekspor, atau sinkronisasi lintas perangkat, perlakukan itu sebagai desain lanjutan. Jangan pra-membangun abstraksi pustaka tema dalam implementasi ini.