ธีมไทย 5 แบบ: สลับโหมดมืด/สว่างของ Claude Code และวาดแถบสีธีมเหนือช่องพิมพ์

ธีมไทย 5 แบบ: 🇹🇭 สงกรานต์, 🌕 ลอยกระทง, 🌙 ดาร์กไทย (ค่าเริ่มต้น), 🤍 มินิมอล, 🛍️ ตลาดนัด เลือกแล้วจะสลับธีมหลักของ Claude Code เป็นโหมดมืดหรือสว่างตามธีม และวาดแถบสีของธีมไว้เหนือช่องพิมพ์ ธีมที่เลือกจะจำไว้ข้าม session
| คำสั่ง | ทำอะไร |
|---|---|
/skin | ดูรายการธีม |
/skin loykrathong | เปลี่ยนธีม |
/skin off | ซ่อนแถบธีม |
/skin-random | สุ่มธีม |
/plugin install claude-skins-th --marketplace tksoft11/claude-code-mods-th
ต้องตั้ง CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 ก่อนเปิด claude (ดู README หลัก)
เปิด hooks/register.tsx แล้วอ่านตามบทที่เขียนไว้ในคอมเมนต์:
$.config.set และรับมือกับ { deny }$.storee.args)<Text color>Mod ไม่มี DOM จึงเปลี่ยนสีทุกส่วนของหน้าจอไม่ได้ สิ่งที่ Mod คุมได้คือธีมหลัก (มืด/สว่าง) และสีของสิ่งที่ Mod วาดเอง ถ้าองค์กรล็อกการตั้งค่าธีมไว้ จะขึ้นคำเตือนแทน
hooks/register.tsx 147 lines1/**
2 * ============================================================================
3 * MOD 02: Claude Skins TH - ธีมไทย 5 แบบ (ฉบับสอนทำ)
4 * ============================================================================
5 * แรงบันดาลใจจาก: https://github.com/hellosverre/claude-skins
6 *
7 * หน้าที่ของ Mod นี้:
8 * 1. มีธีมไทย 5 แบบ: สงกรานต์, ลอยกระทง, ดาร์กไทย, มินิมอล, ตลาดนัด
9 * 2. เปลี่ยนธีมของ Claude Code (มืด/สว่าง) ผ่าน $.config.set("theme")
10 * 3. วาดแถบสีของธีมเหนือช่องพิมพ์ ด้วยสี hex ของธีมนั้น
11 * 4. จำธีมที่เลือกไว้ข้าม session ด้วย $.store
12 *
13 * หมายเหตุ: Mod ไม่มี DOM จึง inject CSS ไม่ได้ สีที่ Mod คุมได้คือ
14 * สีของ element ที่ Mod วาดเอง (Text color="#hex") + ธีมหลักของ Claude Code
15 */
16
17import type { EngineInterface, Register } from 'claude-code'
18
19// ==========================================================================
20// บทที่ 1: นิยามธีมเป็น Object - แก้ตรงนี้เพื่อสร้างธีมของคุณเอง
21// ==========================================================================
22type Skin = {
23 name: string
24 base: 'dark' | 'light' // ธีมหลักของ Claude Code ที่จะสลับไป
25 accent: string // สีหลัก (hex)
26 soft: string // สีรอง (hex)
27 tagline: string
28}
29
30const SKINS: Record<string, Skin> = {
31 songkran: { name: '🇹🇭 สงกรานต์', base: 'light', accent: '#0288d1', soft: '#ffb300', tagline: 'ฟ้า-เหลืองทอง สดใส' },
32 loykrathong: { name: '🌕 ลอยกระทง', base: 'dark', accent: '#ffd54f', soft: '#9575cd', tagline: 'ดำ-ม่วง-ทอง ค่ำคืน' },
33 'dark-thai': { name: '🌙 ดาร์กไทย', base: 'dark', accent: '#4db6ac', soft: '#80cbc4', tagline: 'ดาร์กสบายตา เขียวมิ้นท์' },
34 minimal: { name: '🤍 มินิมอล', base: 'light', accent: '#424242', soft: '#9e9e9e', tagline: 'ขาวคลีน โฟกัสงาน' },
35 taladnat: { name: '🛍️ ตลาดนัด', base: 'dark', accent: '#ff1744', soft: '#ffea00', tagline: 'สีจัดจ้านแบบป้ายตลาด' },
36}
37
38const DEFAULT_SKIN = 'dark-thai'
39const STORE_KEY = 'skin' // key ใน $.store (เก็บข้าม session)
40
41let currentSkin = DEFAULT_SKIN // id ของธีมที่เลือกอยู่ ("" = ซ่อนแถบธีม)
42
43// เปลี่ยนธีมที่แสดงแล้วสั่งให้แถบวาดใหม่
44function setSkin($: EngineInterface, id: string): void {
45 currentSkin = id
46 $.ui.invalidate('ui.render')
47}
48
49// ==========================================================================
50// บทที่ 2: เปลี่ยนธีมหลักของ Claude Code
51// ==========================================================================
52// $.config.set ทำเหมือนผู้ใช้เปลี่ยนใน /config เอง อาจได้ { deny } กลับมา
53// (เช่น องค์กรล็อกค่าไว้) จึงต้องเช็คก่อนบอกว่าสำเร็จ
54async function applyBaseTheme($: EngineInterface, base: 'dark' | 'light'): Promise<string> {
55 const row = (await $.config.list()).find(r => r.key === 'theme')
56 if (!row) return 'ไม่พบการตั้งค่า theme ใน /config'
57 if (row.value === base) return ''
58 if (row.options && !row.options.includes(base)) return `ธีม "${base}" ไม่มีใน /config`
59
60 const result = await $.config.set({ key: 'theme', value: base })
61 return 'deny' in result && result.deny ? `เปลี่ยนธีมหลักไม่ได้: ${result.deny}` : ''
62}
63
64// เลือกธีม: เปลี่ยนแถบ + เก็บใน $.store (จำข้าม session)
65async function chooseSkin($: EngineInterface, id: string): Promise<string> {
66 const skin = SKINS[id]
67 if (!skin) return `❌ ไม่มีธีม "${id}" ลองพิมพ์ /skin เพื่อดูรายการ`
68
69 setSkin($, id)
70 await $.store.set(STORE_KEY, id)
71 const warning = await applyBaseTheme($, skin.base)
72
73 return `🎨 เปลี่ยนเป็นธีม ${skin.name} (${skin.tagline})${warning ? `\n⚠️ ${warning}` : ''}`
74}
75
76function listSkins(current: string): string {
77 const lines = Object.entries(SKINS).map(
78 ([id, s]) => `${id === current ? '👉' : ' '} ${s.name.padEnd(14)} /skin ${id.padEnd(12)} ${s.tagline}`,
79 )
80 return ['🎨 ธีมไทยทั้งหมด (Mod 02)', '----------------------------------------', ...lines, '', '/skin off = ซ่อนแถบธีม | /skin-random = สุ่มธีม'].join('\n')
81}
82
83export const register: Register = on => {
84 // ==========================================================================
85 // บทที่ 3: session.start - โหลดธีมที่เคยเลือก + ลงทะเบียนคำสั่ง
86 // ==========================================================================
87 on('session.start', async ($, e, next) => {
88 const saved = await $.store.get(STORE_KEY)
89 const id = typeof saved === 'string' && (saved === '' || SKINS[saved]) ? saved : DEFAULT_SKIN
90 setSkin($, id)
91
92 await $.command.register({ name: 'skin', description: 'เปลี่ยนธีมไทย (ไม่ใส่ชื่อ = ดูรายการ)', argumentHint: '[ชื่อธีม|off]' })
93 await $.command.register({ name: 'skin-random', description: 'สุ่มธีมไทย' })
94
95 return next(e)
96 })
97
98 // ==========================================================================
99 // บทที่ 4: คำสั่งแบบมี argument - /skin loykrathong
100 // ==========================================================================
101 on('command.run', { command: 'skin' }, async ($, e) => {
102 const arg = e.args.trim().toLowerCase() // e.args = ข้อความหลังชื่อคำสั่ง
103 if (arg === '' || arg === 'list') return { text: listSkins(currentSkin) }
104 if (arg === 'off') {
105 setSkin($, '')
106 await $.store.set(STORE_KEY, '')
107 return { text: '🙈 ซ่อนแถบธีมแล้ว (/skin <ชื่อ> เพื่อเปิดอีกครั้ง)' }
108 }
109 return { text: await chooseSkin($, arg) }
110 })
111
112 on('command.run', { command: 'skin-random' }, async $ => {
113 const ids = Object.keys(SKINS)
114 const id = ids[Math.floor(Math.random() * ids.length)] ?? DEFAULT_SKIN
115 return { text: `🎲 สุ่มได้...\n${await chooseSkin($, id)}` }
116 })
117
118 // ==========================================================================
119 // บทที่ 5: วาดแถบธีมเหนือช่องพิมพ์ด้วยสี hex ของธีม
120 // ==========================================================================
121 on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
122 const skin = currentSkin ? SKINS[currentSkin] : undefined
123 if (e.props.hasSurvey || !skin) return next(e)
124
125 const { Box, Text } = $.ui.resolve(e)
126 return (
127 <Box>
128 <Text color={skin.accent} bold>
129 {skin.name}
130 </Text>
131 <Text color={skin.soft}> · {skin.tagline}</Text>
132 </Box>
133 )
134 })
135}
136
137/**
138 * ========================================================================
139 * การบ้าน / ต่อยอด
140 * ========================================================================
141 * 1. สร้างธีมของคุณเอง: ก็อป 'dark-thai' ใน SKINS แล้วตั้งชื่อใหม่ เช่น 'my-brand'
142 * เปลี่ยน accent/soft เป็นสีแบรนด์ (แดงธงชาติ #ed1c24, น้ำเงิน #241d4f, ทอง #ffd700)
143 * บันทึกไฟล์ แล้ว /reload-plugins และ /skin my-brand
144 * 2. เปลี่ยนธีมอัตโนมัติตามเวลา: กลางวันใช้ธีมสว่าง กลางคืนใช้ธีมมืด ด้วย $.clock.every
145 * 3. แสดงแถบธีมเฉพาะตอนเริ่ม session แล้วซ่อนเองหลัง 1 นาที ด้วย $.clock.after
146 */
147